本文向您介紹DataFrame支援的資料表的JOIN操作、UNION操作等資料合併操作。
前提條件
您需要提前置入以下樣本表資料,用於操作本文中的樣本,其中樣本來源資料下載請參見資料準備,使用到的兩個樣本表結構如下。
>>> from odps.df import DataFrame
>>> movies = DataFrame(o.get_table('pyodps_ml_100k_movies'))
>>> ratings = DataFrame(o.get_table('pyodps_ml_100k_ratings'))
>>> movies.dtypes
odps.Schema {
movie_id int64
title string
release_date string
video_release_date string
_url string
}
>>> ratings.dtypes
odps.Schema {
user_id int64
movie_id int64
rating int64
unix_timestamp int64
}
JOIN操作
DataFrame支援對兩個Collection執行join
的操作。
如果不指定
join
的條件,則DataFrame API會尋找名字相同的列,並作為join
的條件。>>> movies.join(ratings).head(3) movie_id title release_date video_release_date url user_id rating unix_timestamp 0 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 49 3 888068877 1 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 621 5 881444887 2 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 291 3 874833936
顯式指定
join
的條件。在join
時,如果on
條件在兩表中所選取的欄位名稱相同,則只會保留其中一個表的此欄位。>>> movies.join(ratings, on='movie_id').head(3) movie_id title release_date video_release_date url user_id rating unix_timestamp 0 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 49 3 888068877 1 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 621 5 881444887 2 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 291 3 874833936
在執行其他類型的
join
操作時,例如left_join
,兩表中相同名稱的欄位會被重新命名。>>> movies.left_join(ratings, on='movie_id').head(3) movie_id_x title release_date video_release_date url user_id movie_id_y rating unix_timestamp 0 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 49 3 3 888068877 1 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 621 3 5 881444887 2 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 291 3 3 874833936
樣本中,
movie_id
被重新命名為movie_id_x
、movie_id_y
,這與suffixes
參數有關,該參數的預設值為('_x', '_y')
。當遇到重名的列時,重名的列會被重新命名為指定的尾碼名。>>> ratings2 = ratings[ratings.exclude('movie_id'), ratings.movie_id.rename('movie_id2')] >>> ratings2.dtypes odps.Schema { user_id int64 rating int64 unix_timestamp int64 movie_id2 int64 } >>> movies.join(ratings2, on=[('movie_id', 'movie_id2')]).head(3) movie_id title release_date video_release_date url user_id rating unix_timestamp movie_id2 0 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 49 3 888068877 3 1 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 621 5 881444887 3 2 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 291 3 874833936 3
也可以在
on
中直接寫等於運算式。>>> movies.join(ratings2, on=[movies.movie_id == ratings2.movie_id2]).head(3) movie_id title release_date video_release_date url user_id rating unix_timestamp movie_id2 0 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 49 3 888068877 3 1 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 621 5 881444887 3 2 3 Four Rooms (1995) 01-Jan-1995 http://example.aliyundoc.com/M/title-exact?Four%20Rooms%... 291 3 874833936 3
在
self-join
時,可以調用view
方法分別提取欄位。>>> movies2 = movies.view() >>> movies.join(movies2, movies.movie_id == movies2.movie_id)[movies, movies2.movie_id.rename('movie_id2')].head(3) movie_id title_x release_date_x video_release_date_x \ 0 2 GoldenEye (1995) 01-Jan-1995 True 1 3 Four Rooms (1995) 01-Jan-1995 True 2 4 Get Shorty (1995) 01-Jan-1995 True url_x movie_id2 0 http://example.aliyundoc.com/M/title-exact?GoldenEye%20(... 2 1 http://example.aliyundoc.comtitle-exact?Four%20Rooms%... 3 2 http://example.aliyundoc.com/M/title-exact?Get%20Shorty%... 4
除了支援
join
,DataFrame還支援left_join
、right_join
和outer_join
。在執行上述外串連操作時, 預設會為重名列加上_x
和_y
尾碼,可通過在suffixes
參數中傳入一個二元tuple
進行自訂尾碼。如果需要在外串連中避免對位次相等的列取重複列,可以指定
merge_columns
選項。該選項會自動選擇兩列中的非空值作為新列的值。>>> movies.left_join(ratings, on='movie_id', merge_columns=True)
使用mapjoin
時,只需將mapjoin
設為True,執行時會對右表做mapjoin
操作。您也可以對分別來自ODPS和Pandas的Collection進行join
,或者對分別來自ODPS和資料庫的Collection進行join
,該計算會在ODPS上執行。
UNION操作
如果兩張表的欄位和類型都一致(欄位的順序可以不同),則可以使用union
或者concat
將它們合并成一張表。
>>> mov1 = movies[movies.movie_id < 3]['movie_id', 'title']
>>> mov2 = movies[(movies.movie_id > 3) & (movies.movie_id < 6)]['title', 'movie_id']
>>> mov1.union(mov2)
movie_id title
0 1 Toy Story (1995)
1 2 GoldenEye (1995)
2 4 Get Shorty (1995)
3 5 Copycat (1995)
您也可以對分別來自ODPS和Pandas的Collection進行union
操作,或者對分別來自ODPS和資料庫的Collection進行union
操作,相關的計算會在ODPS上執行。