本文為您介紹如何建立和操作DataFrame對象,以及使用DataFrame完成基本的資料處理。
資料準備
本文將以u.user、u.item和u.data資料進行舉例。其中u.user是使用者相關的資料,u.item是電影相關的資料,u.data是評分相關的資料。
建立表:
pyodps_ml_100k_users(使用者相關的資料)。CREATE TABLE IF NOT EXISTS pyodps_ml_100k_users ( user_id BIGINT COMMENT '使用者id', age BIGINT COMMENT '年齡', sex STRING COMMENT '性別', occupation STRING COMMENT '職業', zip_code STRING COMMENT '郵編' );pyodps_ml_100k_movies(電影相關的資料)。CREATE TABLE IF NOT EXISTS pyodps_ml_100k_movies ( movie_id BIGINT COMMENT '電影 ID', title STRING COMMENT '電影標題', release_date STRING COMMENT '上映日期', video_release_date STRING COMMENT '視頻發布日期', IMDb_URL STRING COMMENT 'IMDb 連結', unknown TINYINT COMMENT '未知', Action TINYINT COMMENT '動作', Adventure TINYINT COMMENT '冒險', Animation TINYINT COMMENT '動畫', Children TINYINT COMMENT '兒童', Comedy TINYINT COMMENT '喜劇', Crime TINYINT COMMENT '犯罪', Documentary TINYINT COMMENT '紀錄片', Drama TINYINT COMMENT '戲劇', Fantasy TINYINT COMMENT '奇幻', FilmNoir TINYINT COMMENT '黑色電影', Horror TINYINT COMMENT '恐怖', Musical TINYINT COMMENT '音樂', Mystery TINYINT COMMENT '懸疑', Romance TINYINT COMMENT '浪漫', SciFi TINYINT COMMENT '科幻', Thriller TINYINT COMMENT '驚悚', War TINYINT COMMENT '戰爭', Western TINYINT COMMENT '西部' );pyodps_ml_100k_ratings(評分相關的資料)。CREATE TABLE IF NOT EXISTS pyodps_ml_100k_ratings ( user_id BIGINT COMMENT '使用者id', movie_id BIGINT COMMENT '電影id', rating BIGINT COMMENT '得分', timestamp BIGINT COMMENT '時間戳記' )
基於Tunnel Upload 將本機資料檔案內容匯入MaxCompute的表中。更多Tunnel操作,請參見Tunnel命令。
Tunnel upload -fd | path_to_file/u.user pyodps_ml_100k_users; Tunnel upload -fd | path_to_file/u.item pyodps_ml_100k_movies; Tunnel upload -fd | path_to_file/u.data pyodps_ml_100k_ratings;
DataFrame對象操作
現在已經有了三張表,分別是pyodps_ml_100k_movies(電影相關的資料)、pyodps_ml_100k_users(使用者相關的資料)、pyodps_ml_100k_ratings(評分相關的資料)。以下樣本使用IPython運行。
確保已經安裝了Python。IPython是基於Python的,所以需要先安裝Python環境。接著通過pip install IPython 安裝IPython。安裝完成後,可以通過執行IPython命令來啟動IPython的互動式環境,開始編寫和執行Python代碼。
建立ODPS對象。
import os from odps import ODPS # 確保 ALIBABA_CLOUD_ACCESS_KEY_ID 環境變數設定為使用者 Access Key ID, # ALIBABA_CLOUD_ACCESS_KEY_SECRET 環境變數設定為使用者 Access Key Secret, # 不建議直接使用 Access Key ID / Access Key Secret 字串 o = ODPS( os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'), os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'), project='your-default-project', endpoint='your-end-point', )通過傳入Table對象建立一個DataFrame對象。
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()) df1 = df.sort(df['count'], ascending=False) print(df1.head(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的限制,詳情請參見配置選項。df = users.occupation.value_counts()[:10] print(df.head(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使用
join將這三張表聯合起來,然後儲存為一張新的表pyodps_ml_100k_lens。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 ideo_release_date string imdb_url string unknown int64 action int64 adventure int64 animation int64 children int64 comedy int64 crime int64 documentary int64 drama int64 fantasy int64 filmnoir int64 horror int64 musical int64 mystery int64 romance int64 scifi int64 thriller int64 war int64 western int64 user_id int64 rating int64 timestamp int64 age int64 sex string occupation string zip_code string }
Dataframe資料處理
請您首先下載鳶尾花資料集。本文使用DataWorks PyODPS節點功能,詳情請參見開發PyODPS 3任務。
建立測試資料表 。
使用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 '種類' ) ;
上傳測試資料 。
在建立表上單擊右鍵,選擇匯入資料,單擊下一步,上傳您剛下載的資料集。

單擊按位置匹配後匯入資料。
開啟相應的商務程序,按右鍵MaxCompute,選擇建立節點,選擇PyODPS 3,建立一個PyODPS節點,用於存放和運行代碼。
輸入代碼後,單擊運行
,運行後可在下方作業記錄處查看結果。代碼詳情如下。from odps import ODPS from odps.df import DataFrame, output import os # 確保 ALIBABA_CLOUD_ACCESS_KEY_ID 環境變數設定為使用者 Access Key ID, # ALIBABA_CLOUD_ACCESS_KEY_SECRET 環境變數設定為使用者 Access Key Secret, # 不建議直接使用 Access Key ID / Access Key Secret 字串 o = ODPS( os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'), os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'), project='your-default-project', endpoint='your-end-point', ) # 從ODPS表建立DataFrame對象iris。 iris = DataFrame(o.get_table('pyodps_iris')) print(iris.head(10)) # 列印iris部分內容。 print(iris.sepallength.head(5)) # 使用自訂函數求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))運行結果:
# print(iris.head(10)) sepallength sepalwidth petallength petalwidth name 0 4.9 3.0 1.4 0.2 Iris-setosa 1 4.7 3.2 1.3 0.2 Iris-setosa 2 4.6 3.1 1.5 0.2 Iris-setosa 3 5.0 3.6 1.4 0.2 Iris-setosa 4 5.4 3.9 1.7 0.4 Iris-setosa 5 4.6 3.4 1.4 0.3 Iris-setosa 6 5.0 3.4 1.5 0.2 Iris-setosa 7 4.4 2.9 1.4 0.2 Iris-setosa 8 4.9 3.1 1.5 0.1 Iris-setosa 9 5.4 3.7 1.5 0.2 Iris-setosa # print(iris.sepallength.head(5)) sepallength 0 4.9 1 4.7 2 4.6 3 5.0 4 5.4 # print(iris.apply(lambda row: row.sepallength + row.sepalwidth, axis=1, reduce=True, types='float').rename('sepaladd').head(3)) sepaladd 0 7.9 1 7.9 2 7.7 # print(iris.apply(handle,axis=1).head(5)) iris_add iris_sub 0 1.9 7.9 1 1.2 1.6 2 1.5 7.9 3 1.1 1.5 4 1.5 7.7