您可以對DataFrame對象執行排序、去重、採樣、資料變換操作。
前提條件
您需要提前完成以下步驟,用於操作本文中的樣本:
準備樣本表pyodps_iris,詳情請參見Dataframe資料處理。
建立DataFrame。
from odps.df import DataFrame iris = DataFrame(o.get_table('pyodps_iris'))
排序
排序操作只能作用於Collection。
調用
sort
或者sort_values
方法進行排序。>>> iris.sort('sepalwidth').head(5) sepallength sepalwidth petallength petalwidth name 0 5.0 2.0 3.5 1.0 Iris-versicolor 1 6.2 2.2 4.5 1.5 Iris-versicolor 2 6.0 2.2 5.0 1.5 Iris-virginica 3 6.0 2.2 4.0 1.0 Iris-versicolor 4 5.5 2.3 4.0 1.3 Iris-versicolor
設定參數
ascending=False;
進行降序排列。>>> iris.sort('sepalwidth', ascending=False).head(5) sepallength sepalwidth petallength petalwidth name 0 5.7 4.4 1.5 0.4 Iris-setosa 1 5.5 4.2 1.4 0.2 Iris-setosa 2 5.2 4.1 1.5 0.1 Iris-setosa 3 5.8 4.0 1.2 0.2 Iris-setosa 4 5.4 3.9 1.3 0.4 Iris-setosa
設定
-
實現降序排列。>>> iris.sort(-iris.sepalwidth).head(5) sepallength sepalwidth petallength petalwidth name 0 5.7 4.4 1.5 0.4 Iris-setosa 1 5.5 4.2 1.4 0.2 Iris-setosa 2 5.2 4.1 1.5 0.1 Iris-setosa 3 5.8 4.0 1.2 0.2 Iris-setosa 4 5.4 3.9 1.3 0.4 Iris-setosa
實現多欄位排序。
>>> iris.sort(['sepalwidth', 'petallength']).head(5) sepallength sepalwidth petallength petalwidth name 0 5.0 2.0 3.5 1.0 Iris-versicolor 1 6.0 2.2 4.0 1.0 Iris-versicolor 2 6.2 2.2 4.5 1.5 Iris-versicolor 3 6.0 2.2 5.0 1.5 Iris-virginica 4 4.5 2.3 1.3 0.3 Iris-setosa
多欄位排序時,如果是升序降序不同,
ascending
參數可以用於傳入一個列表,長度必須等同於排序的欄位,它們的值都是BOOLEAN類型。>>> iris.sort(['sepalwidth', 'petallength'], ascending=[True, False]).head(5) sepallength sepalwidth petallength petalwidth name 0 5.0 2.0 3.5 1.0 Iris-versicolor 1 6.0 2.2 5.0 1.5 Iris-virginica 2 6.2 2.2 4.5 1.5 Iris-versicolor 3 6.0 2.2 4.0 1.0 Iris-versicolor 4 6.3 2.3 4.4 1.3 Iris-versicolor
下面代碼可以實現同樣的效果。
>>> iris.sort(['sepalwidth', -iris.petallength]).head(5) sepallength sepalwidth petallength petalwidth name 0 5.0 2.0 3.5 1.0 Iris-versicolor 1 6.0 2.2 5.0 1.5 Iris-virginica 2 6.2 2.2 4.5 1.5 Iris-versicolor 3 6.0 2.2 4.0 1.0 Iris-versicolor 4 6.3 2.3 4.4 1.3 Iris-versicolor
說明由於ODPS要求排序必須指定個數,所以在ODPS後端執行時,會通過
options.df.odps.sort.limit
指定排序個數,這個值預設是10000。如果需要排序盡量多的資料,可以把這個值設到較大的值。但是,這樣可能會導致OOM。
去重
您可以通過以下三種方式調用
distinct
方法,對Collection進行去重操作。>>> iris[['name']].distinct() name 0 Iris-setosa 1 Iris-versicolor 2 Iris-virginica
>>> iris.distinct('name') name 0 Iris-setosa 1 Iris-versicolor 2 Iris-virginica
>>> iris.distinct('name', 'sepallength').head(3) name sepallength 0 Iris-setosa 4.3 1 Iris-setosa 4.4 2 Iris-setosa 4.5
您可以調用
unique
對Sequence進行去重操作,但是調用unique
的Sequence不能用在列選擇中。>>> iris.name.unique() name 0 Iris-setosa 1 Iris-versicolor 2 Iris-virginica
錯誤樣本如下。
>>> iris[iris.name, iris.name.unique()]
採樣
要對一個Collection的資料採樣,可以調用sample
方法。PyODPS支援以下四種採樣方式:
除了按份數採樣外,其餘方法如果要在ODPS DataFrame上執行,需要Project支援XFlow,否則,這些方法只能在Pandas DataFrame後端上執行。
按份數採樣
在這種採樣方式下,資料被分為
parts
份,可選擇選取的份數序號。>>> iris.sample(parts=10) # 分成10份,預設取第0份。 >>> iris.sample(parts=10, i=0) # 手動指定取第0份。 >>> iris.sample(parts=10, i=[2, 5]) # 分成10份,取第2和第5份。 >>> iris.sample(parts=10, columns=['name', 'sepalwidth']) # 根據name和sepalwidth的值做採樣。
按權重列採樣
在這種採樣方式下,您可以指定權重列和資料條數、採樣比例。指定
replace
參數為True可啟用放回採樣。>>> iris.sample(n=100, weights='sepal_length') >>> iris.sample(n=100, weights='sepal_width', replace=True)
分層採樣
在這種採樣方式下,您可以指定用於分層的標籤列,同時為需要採樣的每個標籤指定採樣比例(
frac
參數)或條數 (n
參數)。暫不支援放回採樣。>>> iris.sample(strata='category', n={'Iris Setosa': 10, 'Iris Versicolour': 10}) >>> iris.sample(strata='category', frac={'Iris Setosa': 0.5, 'Iris Versicolour': 0.4})
資料縮放
DataFrame支援通過最大、最小值或平均值、標準差對資料進行縮放。樣本資料如下。
name id fid
0 name1 4 5.3
1 name2 2 3.5
2 name2 3 1.5
3 name1 4 4.2
4 name1 3 2.2
5 name1 3 4.1
使用
min_max_scale
方法進行歸一化。df.min_max_scale(columns=['fid']) name id fid 0 name1 4 1.000000 1 name2 2 0.526316 2 name2 3 0.000000 3 name1 4 0.710526 4 name1 3 0.184211 5 name1 3 0.684211
min_max_scale
還支援使用feature_range
參數指定輸出值的範圍。例如,需要使輸出值在 (-1, 1) 範圍內,樣本如下。df.min_max_scale(columns=['fid'], feature_range=(-1, 1)) name id fid 0 name1 4 1.000000 1 name2 2 0.052632 2 name2 3 -1.000000 3 name1 4 0.421053 4 name1 3 -0.631579 5 name1 3 0.368421
如果需要保留原始值,可以使用
preserve
參數。此時,縮放後的資料將會以新增列的形式追加到資料中,列名預設為原列名追加_scaled尾碼,該尾碼可使用suffix
參數更改。df.min_max_scale(columns=['fid'], preserve=True) name id fid fid_scaled 0 name1 4 5.3 1.000000 1 name2 2 3.5 0.526316 2 name2 3 1.5 0.000000 3 name1 4 4.2 0.710526 4 name1 3 2.2 0.184211 5 name1 3 4.1 0.684211
min_max_scale
也支援使用group
參數指定一個或多個分組列,在分組列中分別取最值進行縮放。df.min_max_scale(columns=['fid'], group=['name']) name id fid 0 name1 4 1.000000 1 name1 4 0.645161 2 name1 3 0.000000 3 name1 3 0.612903 4 name2 2 1.000000 5 name2 3 0.000000
結果顯示,
name1
和name2
兩組均按組中的最值進行了縮放。使用
std_scale
方法可以依照標準常態分佈對資料進行調整。std_scale
同樣支援preserve
參數保留原始列以及使用group
進行分組。df.std_scale(columns=['fid']) name id fid 0 name1 4 1.436467 1 name2 2 0.026118 2 name2 3 -1.540938 3 name1 4 0.574587 4 name1 3 -0.992468 5 name1 3 0.496234
空值處理
DataFrame支援篩去空值以及填充空值的功能。樣本資料如下。
id name f1 f2 f3 f4
0 0 name1 1.0 NaN 3.0 4.0
1 1 name1 2.0 NaN NaN 1.0
2 2 name1 3.0 4.0 1.0 NaN
3 3 name1 NaN 1.0 2.0 3.0
4 4 name1 1.0 NaN 3.0 4.0
5 5 name1 1.0 2.0 3.0 4.0
6 6 name1 NaN NaN NaN NaN
使用
dropna
,刪除subset
中包含空值的行。df.dropna(subset=['f1', 'f2', 'f3', 'f4']) id name f1 f2 f3 f4 0 5 name1 1.0 2.0 3.0 4.0
如果行中包含非空值則不刪除,可以使用
how=’all’
。df.dropna(how='all', subset=['f1', 'f2', 'f3', 'f4']) id name f1 f2 f3 f4 0 0 name1 1.0 NaN 3.0 4.0 1 1 name1 2.0 NaN NaN 1.0 2 2 name1 3.0 4.0 1.0 NaN 3 3 name1 NaN 1.0 2.0 3.0 4 4 name1 1.0 NaN 3.0 4.0 5 5 name1 1.0 2.0 3.0 4.0
使用
thresh
參數指定行中至少要有多少個非空值。df.dropna(thresh=3, subset=['f1', 'f2', 'f3', 'f4']) id name f1 f2 f3 f4 0 0 name1 1.0 NaN 3.0 4.0 2 2 name1 3.0 4.0 1.0 NaN 3 3 name1 NaN 1.0 2.0 3.0 4 4 name1 1.0 NaN 3.0 4.0 5 5 name1 1.0 2.0 3.0 4.0
調用
fillna
方法,使用常數或已有的列來填充未知值。使用常數填充未知值。
df.fillna(100, subset=['f1', 'f2', 'f3', 'f4']) id name f1 f2 f3 f4 0 0 name1 1.0 100.0 3.0 4.0 1 1 name1 2.0 100.0 100.0 1.0 2 2 name1 3.0 4.0 1.0 100.0 3 3 name1 100.0 1.0 2.0 3.0 4 4 name1 1.0 100.0 3.0 4.0 5 5 name1 1.0 2.0 3.0 4.0 6 6 name1 100.0 100.0 100.0 100.0
使用一個已有的列填充未知值。
df.fillna(df.f2, subset=['f1', 'f2', 'f3', 'f4']) id name f1 f2 f3 f4 0 0 name1 1.0 NaN 3.0 4.0 1 1 name1 2.0 NaN NaN 1.0 2 2 name1 3.0 4.0 1.0 4.0 3 3 name1 1.0 1.0 2.0 3.0 4 4 name1 1.0 NaN 3.0 4.0 5 5 name1 1.0 2.0 3.0 4.0 6 6 name1 NaN NaN NaN NaN
DataFrame提供了向前、向後填充的功能。您可以按照表格中的取值範圍為
method
參數進行賦值。取值
含義
bfill、backfill
向前填充。
ffill、pad
向後填充。
樣本
df.fillna(method='bfill', subset=['f1', 'f2', 'f3', 'f4']) id name f1 f2 f3 f4 0 0 name1 1.0 3.0 3.0 4.0 1 1 name1 2.0 1.0 1.0 1.0 2 2 name1 3.0 4.0 1.0 NaN 3 3 name1 1.0 1.0 2.0 3.0 4 4 name1 1.0 3.0 3.0 4.0 5 5 name1 1.0 2.0 3.0 4.0 6 6 name1 NaN NaN NaN NaN df.fillna(method='ffill', subset=['f1', 'f2', 'f3', 'f4']) id name f1 f2 f3 f4 0 0 name1 1.0 1.0 3.0 4.0 1 1 name1 2.0 2.0 2.0 1.0 2 2 name1 3.0 4.0 1.0 1.0 3 3 name1 NaN 1.0 2.0 3.0 4 4 name1 1.0 1.0 3.0 4.0 5 5 name1 1.0 2.0 3.0 4.0 6 6 name1 NaN NaN NaN NaN
您也可以使用
ffill
、bfill
函數簡化代碼。ffill
等價於fillna(method=’ffill’)
;bfill
等價於fillna(method=’bfill’)
。