本文为您介绍如何创建和操作DataFrame对象,以及使用DataFrame完成基本的数据处理。
DataFrame对象操作
本文将以movielens 100K进行举例。现在已经有了三张表,分别是pyodps_ml_100k_movies
(电影相关的数据)、pyodps_ml_100k_users
(用户相关的数据)、pyodps_ml_100k_ratings
(评分有关的数据)。
- 当运行环境没有提供ODPS对象时,您需要自己创建该对象。
from odps import ODPS o = ODPS('**your-access-id**', '**your-secret-access-key**', project='**your-project**', endpoint='**your-end-point**')
- 创建一个DataFrame对象非常容易,只需传入Table对象即可。
from odps.df import DataFrame users = DataFrame(o.get_table('pyodps_ml_100k_users'))
- 您可以通过
dtypes
属性查看这个DataFrame的字段及字段类型。print(users.dtypes)
返回值odps.Schema { user_id int64 age int64 sex string occupation string zip_code string }
- 通过
head
方法,您可以取前N条数据并进行快速预览。print(users.head(10))
返回值user_id age sex occupation zip_code 0 1 24 M technician 85711 1 2 53 F other 94043 2 3 23 M writer 32067 3 4 24 M technician 43537 4 5 33 F other 15213 5 6 42 M executive 98101 6 7 57 M administrator 91344 7 8 36 M administrator 05201 8 9 29 M student 01002 9 10 53 M lawyer 90703
- 如果您不需要看到所有字段,则可以进行如下操作:
- 从中筛选出一部分字段。
print(users[['user_id', 'age']].head(5))
返回值user_id age 0 1 24 1 2 53 2 3 23 3 4 24 4 5 33
- 只做排除个别字段操作。
print(users.exclude('zip_code', 'age').head(5))
返回值user_id sex occupation 0 1 M technician 1 2 F other 2 3 M writer 3 4 M technician 4 5 F other
- 排除掉一些字段,通过计算得到一些新的列。例如将
sex
为M
的置为True,否则为False,并取名为sex_bool
。print(users.select(users.exclude('zip_code', 'sex'), sex_bool=users.sex == 'M').head(5))
返回值user_id age occupation sex_bool 0 1 24 technician True 1 2 53 other False 2 3 23 writer True 3 4 24 technician True 4 5 33 other False
- 从中筛选出一部分字段。
- 查看男用户和女用户的个数。
print(users.groupby(users.sex).agg(count=users.count()))
返回值sex count 0 F 273 1 M 670
- 将用户按职业划分,从高到低进行排序,查看人数最多的前10职业。
df = users.groupby('occupation').agg(count=users['occupation'].count()) print(df.sort(df['count'], ascending=False)[:10])
返回值或者通过occupation count 0 student 196 1 other 105 2 educator 95 3 administrator 79 4 engineer 67 5 programmer 66 6 librarian 51 7 writer 45 8 executive 32 9 scientist 31
value_counts
方法快速实现。该方法返回的行数受到options.df.odps.sort.limit
的限制,详情请参见配置选项。print(users.occupation.value_counts()[:10])
返回值occupation count 0 student 196 1 other 105 2 educator 95 3 administrator 79 4 engineer 67 5 programmer 66 6 librarian 51 7 writer 45 8 executive 32 9 scientist 31
- 通过更直观的图查看这份数据。在 IPython 中可以启用内嵌图表
%matplotlib inline
- 通过横向的柱状图实现可视化。
users['occupation'].value_counts().plot(kind='barh', x='occupation', ylabel='prefession')
显示的图表为
- 将年龄分为30组,查看年龄分布的直方图。
users.age.hist(bins=30, title="Distribution of users' ages", xlabel='age', ylabel='count of users')
显示的图表为
- 此时,只需要使用
join
将这三张表联合起来,然后保存为一张新的表。movies = DataFrame(o.get_table('pyodps_ml_100k_movies')) ratings = DataFrame(o.get_table('pyodps_ml_100k_ratings')) o.delete_table('pyodps_ml_100k_lens', if_exists=True) lens = movies.join(ratings).join(users).persist('pyodps_ml_100k_lens') print(lens.dtypes)
返回值odps.Schema { movie_id int64 title string release_date string video_release_date string imdb_url string user_id int64 rating int64 unix_timestamp int64 age int64 sex string occupation string zip_code string }
- 将年龄(0到80岁)分成8个年龄段。
labels = ['0-9', '10-19', '20-29', '30-39', '40-49', '50-59', '60-69', '70-79'] cut_lens = lens[lens, lens.age.cut(range(0, 81, 10), right=False, labels=labels).rename('年龄分组')]
- 取分组和年龄唯一的前10条查看。
print(cut_lens['年龄分组', 'age'].distinct()[:10])
返回值年龄分组 age 0 0-9 7 1 10-19 10 2 10-19 11 3 10-19 13 4 10-19 14 5 10-19 15 6 10-19 16 7 10-19 17 8 10-19 18 9 10-19 19
- 最后,查看在各个年龄分组下,用户的评分总数和评分均值。
print(cut_lens.groupby('年龄分组').agg(cut_lens.rating.count().rename('评分总数'), cut_lens.rating.mean().rename('评分均值')))
返回值年龄分组 评分均值 评分总数 0 0-9 3.767442 43 1 10-19 3.486126 8181 2 20-29 3.467333 39535 3 30-39 3.554444 25696 4 40-49 3.591772 15021 5 50-59 3.635800 8704 6 60-69 3.648875 2623 7 70-79 3.649746 197
Dataframe数据处理
请您首先下载鸢尾花数据集保存到本地作为示例数据。本文使用DataWorks PyODPS节点功能,详情请参见创建PyODPS 2节点。
- 创建测试数据表 使用DataWorks表管理功能新建表,完成后单击DDL模式。
输入建表语句如下,完成后提交表。
CREATE TABLE pyodps_iris ( sepallength double COMMENT '片长度(cm)', sepalwidth double COMMENT '片宽度(cm)', petallength double COMMENT '瓣长度(cm)', petalwidth double COMMENT '瓣宽度(cm)', name string COMMENT '种类' ) ;
- 上传测试数据 在新建表上单击右键,选择导入数据。
输入表名称后,上传您刚下载的数据集。
单击按位置匹配后导入数据。
- 新建一个PyODPS节点,用于存放和运行代码。
- 输入代码后,单击运行,运行后可在下方运行日志处查看结果。
代码详情如下。
from odps.df import DataFrame, output iris = DataFrame(o.get_table('pyodps_iris')) #从ODPS表创建DataFrame对象iris。 print(iris.head(10)) print(iris.sepallength.head(5)) #打印iris部分内容。 #使用自定义函数求iris的两列之和。 print(iris.apply(lambda row: row.sepallength + row.sepalwidth, axis=1, reduce=True, types='float').rename('sepaladd').head(3)) #指定函数的输出名称和类型。 @output(['iris_add', 'iris_sub'], ['float', 'float']) def handle(row): #使用yield关键字可返回多行结果。 yield row.sepallength - row.sepalwidth,row.sepallength + row.sepalwidth yield row.petallength - row.petalwidth,row.petallength + row.petalwidth #打印前5行结果,axis=1表示列的轴沿着水平的方向。 print(iris.apply(handle,axis=1).head(5))