Pandas是一個很有用的庫,它包含了大量用於操作數據的內置函數。其中,transform()在處理行或列時非常有用。
在本文中,我們將介紹以下最常用的Pandas transform()用途:
轉換值組合groupby()過濾數據在組級別處理缺失值請查看我的Github repo以獲取原始碼;https://github.com/BindiChen/machine-learning/blob/master/data-analysis/013-pandas-transform/pandas-transform.ipynb
1.轉換值
我們來看看pd.transform(func, axis=0)
第一個參數func指定用於操作數據的函數。它可以是函數、字符串函數名、函數列表或軸標籤->函數的字典第二個參數軸指定函數應用於哪個軸。0表示對每列應用func,1表示對每行應用func。讓我們看看transform()是如何在一些示例的幫助下工作的。
函數
我們可以把函數傳遞給func。例如
df = pd.DataFrame({'A': [1,2,3], 'B': [10,20,30] })def plus_10(x): return x+10df.transform(plus_10)
也可以使用lambda表達式。下面是plus_10()的lambda等價形式:
df.transform(lambda x: x+10)字符串函數
我們可以將任何有效的Pandas字符串函數傳遞給func,例如'sqrt':
df.transform('sqrt')
函數列表
func可以是函數的列表。例如,來自NumPy的sqrt和exp:
df.transform([np.sqrt, np.exp])
軸標籤->函數的字典
func可以是軸標籤->函數的字典。例如
df.transform({ 'A': np.sqrt, 'B': np.exp,})
2.組合groupby()
Pandas transform()最引人注目的用法之一是組合groupy()結果。
讓我們通過一個例子來看看這是如何工作的。假設我們有一個關於連鎖餐廳的數據集
df = pd.DataFrame({ 'restaurant_id': [101,102,103,104,105,106,107], 'address': ['A','B','C','D', 'E', 'F', 'G'], 'city': ['London','London','London','Oxford','Oxford', 'Durham', 'Durham'], 'sales': [10,500,48,12,21,22,14]})
我們可以看到,每個城市都有多家餐廳在銷售。我們想知道「每一家餐廳在本市的銷售額佔比是多少」。預期輸出為:
在這個計算中最棘手的部分是,我們需要得到一個城市的總銷售額,並將其合併到數據中,以得到百分比。
有兩種解決方案:
groupby()、apply()和merge()groupby()和transform()解決方案1:groupby()、apply()和merge()
第一種解決方案是使用groupby()分割數據,並使用apply()聚合每個組,然後使用merge()將結果合併回原始數據幀中
第1步:使用groupby()和apply()計算城市銷售總額
city_sales = df.groupby('city')['sales'] .apply(sum).rename('city_total_sales').reset_index()
groupby('city')通過在city列上分組來拆分數據。對於每個組,函數sum應用於sales列,以計算每個組的總和。最後,將新列重命名為city_total_sales並重置索引(注意:需要reset_inde()來清除groupby('city')生成的索引。
此外,Pandas還有一個內置的sum()函數,下面是Pandas sum()的等效函數:
city_sales = df.groupby('city')['sales'] .sum().rename('city_total_sales').reset_index()第2步:使用merge()函數合併結果
df_new = pd.merge(df, city_sales, how='left')
使用merge()和left outer join的how='left'將組結果合併回到原始的DataFrame中
第3步:計算百分比
最後,可以計算並格式化百分比。
df_new['pct'] = df_new['sales'] / df_new['city_total_sales']df_new['pct'] = df_new['pct'].apply(lambda x: format(x, '.2%'))
這當然是我們的工作。但這是一個多步驟的過程,需要額外的代碼才能以我們需要的形式獲取數據。
我們可以使用transform()函數有效地解決這個問題
解決方案2:groupby()和transform()
這個解決方案改變了遊戲規則。一行代碼就可以解決應用和合併問題。
步驟1:使用groupby()和transform()計算城市銷售總額
轉換函數在執行轉換後保留與原始數據集相同數量的項。因此,使用groupby後跟transform(sum)的單行步驟返回相同的輸出。
df['city_total_sales'] = df.groupby('city')['sales'] .transform('sum')
第2步:計算百分比
最後,這和求百分比是一樣的。
df['pct'] = df['sales'] / df['city_total_sales']df['pct'] = df['pct'].apply(lambda x: format(x, '.2%'))3.過濾數據
transform()也可用於過濾數據。在這裡,我們試圖獲得該市總銷售額超過40的記錄
df[df.groupby('city')['sales'].transform('sum') > 40]
4.在組級別處理丟失的值
Pandas transform()的另一個用法是在組級別處理丟失的值。讓我們用一個例子來看看這是如何工作的。
這裡有一個數據幀供演示
df = pd.DataFrame({ 'name': ['A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'], 'value': [1, np.nan, np.nan, 2, 8, 2, np.nan, 3]})
在上面的示例中,可以按名稱將數據分成三組,每個組都缺少值。替換缺失值的常見解決方案是用平均值替換NaN。
讓我們看看每組的平均值。
df.groupby('name')['value'].mean()nameA 1.0B 5.0C 2.5Name: value, dtype: float64在這裡,我們可以使用transform()將缺少的值替換為組平均值。
df['value'] = df.groupby('name') .transform(lambda x: x.fillna(x.mean()))
你可以在我的Github上獲取原始碼:https://github.com/BindiChen/machine-learning/blob/master/data-analysis/013-pandas-transform/pandas-transform.ipynb