与 PyODPS DataFrame 的比较#

PyODPS DataFrame 是 MaxCompute 提供的类似 DataFrame 的包,是 PyODPS 包的一部分。它可以让 Python 数据分析人员使用类似于 pandas 的一组操作符来查询 MaxCompute 数据。尽管操作符相似,但两套 API 的用法差异很大。仅凭 pandas 的知识,开发者可能难以深入使用 PyODPS DataFrame。

虽然 PyODPS DataFrame 仍然是 PyODPS 的一部分,但建议使用 MaxFrame 创建新应用,以享受其与 pandas 的兼容性。

对象抽象#

PyODPS DataFrame 没有索引。这意味着大多数依赖索引的 pandas API 无法使用或不完全支持。

例如,pandas 中的算术运算依赖于索引对齐。也就是说,先对两个 DataFrame 进行对齐,然后执行算术运算。

>>> series1 = pd.Series([2, 1, 3], index=[1, 2, 4])
>>> series2 = pd.Series([1, 5, 6], index=[1, 3, 4])
>>> series1 + series2
1    3.0
2    NaN
3    NaN
4    9.0
dtype: float64

然而,当索引缺失时,这种操作不被支持。

为了支持这种操作,在 MaxFrame 中需要为 DataFrame 或 Series 添加索引列。如果索引缺失,则会添加一个默认的 RangeIndex。因此上述语句可以被支持。

PyODPS DataFrame 和 MaxFrame 之间的另一个巨大差异在于,在 PyODPS DataFrame 中,数据对象和操作符的表示是混合的,这可能会让初学者感到困惑。例如,

df = o.get_table('table_name').to_df()  # df is a DataFrame instance
df2 = df["col1", "col2"]  # df2 is a CollectionExpr instance

在第二行中,df2CollectionExpr 的一个实例,意味着它是一个表达式,与 DataFrame 实例不同。然而,所有 DataFrame 函数都可以直接应用于 df2,与 DataFrame 实例没有什么不同。

而在 MaxFrame 中,数据对象和操作符是分别定义的。用户交互的数据对象都是少数几个数据类的实例,即 DataFrameSeriesIndex。对于上面的例子,现在所有实例都是 DataFrame。

df = md.read_odps_table('table_name')  # df is a DataFrame instance
df2 = df[["col1", "col2"]]  # df2 is also a DataFrame instance

函数#

PyODPS DataFrame 中的函数与 pandas 并不完全兼容。因此,要使用 PyODPS DataFrame 编写代码,用户需要先阅读文档。而 MaxFrame 的目标是创建与 pandas 兼容的 API。因此,PyODPS DataFrame 和 MaxFrame 之间存在 API 差异。这些差异列在下面。以 mf. 开头的方法表示这些非 pandas 方法是在 MaxFrame 中添加的,以便从 PyODPS DataFrame 迁移到 MaxFrame。请注意,在重写代码之前需要阅读这些函数的 API 文档。

PyODPS DataFrame API

MaxFrame API

DataFrame.append_id

不需要。默认情况下会添加 DataFrame 索引

DataFrame.bloom_filter

尚未实现

DataFrame.boxplot

DataFrame.plot.boxplot

DataFrame.concat

maxframe.dataframe.concat

DataFrame.describe

DataFrame.describe

DataFrame.distinct

DataFrame.drop_duplicates

DataFrame.except_

DataFrame.merge 与过滤器

DataFrame.exclude

DataFrame.drop

DataFrame.extract_kv

尚未实现

DataFrame.hist

DataFrame.plot.hist

DataFrame.inner_join

DataFrame.merge

DataFrame.intersect

DataFrame.merge

DataFrame.left_join

DataFrame.merge

DataFrame.limit

DataFrame.head

DataFrame.map_reduce

DataFrame.mf.map_reduce

DataFrame.minmax_scale

尚未实现

DataFrame.outer_join

DataFrame.merge

DataFrame.persist

DataFrame.to_odps_table

DataFrame.reshuffle

DataFrame.mf.reshuffle

DataFrame.right_join

DataFrame.merge

DataFrame.setdiff

DataFrame.merge

DataFrame.split

尚未实现

DataFrame.std_scale

尚未实现

DataFrame.sort

DataFrame.sort_values

DataFrame.switch

maxframe.dataframe.case_when

DataFrame.to_kv

尚未实现

DataFrame.union

maxframe.dataframe.concat

DatetimeSequenceExpr.date

Series.dt.date

DatetimeSequenceExpr.day

Series.dt.day

DatetimeSequenceExpr.dayofweek

Series.dt.dayofweek

DatetimeSequenceExpr.dayofyear

Series.dt.dayofyear

DatetimeSequenceExpr.hour

Series.dt.hour

DatetimeSequenceExpr.is_month_end

Series.dt.is_month_end

DatetimeSequenceExpr.is_month_start

Series.dt.is_month_start

DatetimeSequenceExpr.is_year_end

Series.dt.is_year_end

DatetimeSequenceExpr.is_year_start

Series.dt.is_year_start

DatetimeSequenceExpr.microsecond

Series.dt.microsecond

DatetimeSequenceExpr.min

Series.dt.min

DatetimeSequenceExpr.minute

Series.dt.minute

DatetimeSequenceExpr.month

Series.dt.month

DatetimeSequenceExpr.second

Series.dt.second

DatetimeSequenceExpr.strftime

Series.dt.strftime

DatetimeSequenceExpr.unix_timestamp

尚未实现

DatetimeSequenceExpr.week

Series.dt.week

DatetimeSequenceExpr.weekday

Series.dt.weekday

DatetimeSequenceExpr.weekofyear

Series.dt.weekofyear

DatetimeSequenceExpr.year

Series.dt.year

SequenceExpr.degrees

np.degrees(Series)

SequenceExpr.radians

np.radians(Series)

SequenceExpr.tolist

Series.to_numpy

SequenceExpr.to_datetime

maxframe.dataframe.to_datetime

SequenceExpr.topk

尚未实现

SequenceExpr.trunc

np.trunc(Series)

SequenceExpr.hll_count

尚未实现

StringSequenceExpr.capitalize

Series.str.capitalize

StringSequenceExpr.contains

Series.str.contains

StringSequenceExpr.count

Series.str.count

StringSequenceExpr.endswith

Series.str.endswith

StringSequenceExpr.find

Series.str.find

StringSequenceExpr.len

Series.str.len

StringSequenceExpr.ljust

Series.str.ljust

StringSequenceExpr.lower

Series.str.lower

StringSequenceExpr.lstrip

Series.str.lstrip

StringSequenceExpr.pad

Series.str.pad

StringSequenceExpr.repeat

Series.str.repeat

StringSequenceExpr.replace

Series.str.replace

StringSequenceExpr.rfind

Series.str.rfind

StringSequenceExpr.rjust

Series.str.rjust

StringSequenceExpr.rstrip

Series.str.rstrip

StringSequenceExpr.slice

Series.str.slice

StringSequenceExpr.startswith

Series.str.startswith

StringSequenceExpr.strip

Series.str.strip

StringSequenceExpr.swapcase

Series.str.swapcase

StringSequenceExpr.title

Series.str.title

StringSequenceExpr.translate

Series.str.translate

StringSequenceExpr.upper

Series.str.upper

StringSequenceExpr.zfill

Series.str.zfill

StringSequenceExpr.isalnum

Series.str.isalnum

StringSequenceExpr.isalpha

Series.str.isalpha

StringSequenceExpr.isdigit

Series.str.isdigit

StringSequenceExpr.isspace

Series.str.isspace

StringSequenceExpr.islower

Series.str.islower

StringSequenceExpr.isupper

Series.str.isupper

StringSequenceExpr.istitle

Series.str.istitle

StringSequenceExpr.isnumeric

Series.str.isnumeric

StringSequenceExpr.isdecimal

Series.str.isdecimal

执行#

PyODPS DataFrame 和 MaxFrame 都使用惰性执行来提升代码优化的效率。然而,调用这些作业的方式发生了变化。