[英]Pandas DataFrame apply function to multiple columns and output multiple columns
I have been scouring SO for the best way of applying a function that takes multiple separate Pandas DataFrame columns and outputs multiple new columns in the same said DataFrame. 假設我有以下內容:
def apply_func_to_df(df):
df[['new_A', 'new_B']] = df.apply(lambda x: transform_func(x['A'], x['B'], x['C']), axis=1)
def transform_func(value_A, value_B, value_C):
# do some processing and transformation and stuff
return new_value_A, new_value_B
我正在嘗試將此 function 如上所示應用於整個 DataFrame df
,以便 output 2 個新列。 但是,這可以推廣到一個用例/函數,它接收n
DataFrame 列並將m
個新列輸出到相同的 DataFrame。
以下是我一直在關注的事情(取得了不同程度的成功):
transform_func
以明確期望行(即字段) A
, B
, C
如下,然后對df進行應用:def transform_func_mod(df_row):
# do something with df_row['A'], df_row['B'], df_row['C]
return new_value_A, new_value_B
我想要一種非常通用和 Pythonic 的方式來完成這項任務,同時考慮性能(內存和時間方面)。 我將不勝感激任何輸入,因為我一直在努力解決這個問題,因為我不熟悉 Pandas。
按以下方式編寫您的transform_func :
示例:假設所有 3 列都是字符串類型,連接A和B列,將“一些字符串”添加到C :
def transform_func(row):
a = row.A; b = row.B; c = row.C;
return pd.Series([ a + b, c + '_xx'], index=['new_A', 'new_B'])
要僅獲取新值,請將此 function 應用於每一行:
df.apply(transform_func, axis=1)
請注意,生成的 DataFrame 保留了原始行的鍵(我們稍后將使用此功能)。
或者,如果您想將這些新列添加到 DataFrame 中,請將您的df與上述應用程序的結果連接起來,將連接結果保存在原始df下:
df = df.join(df.apply(transform_func, axis=1))
使用zip可能是最慢的選擇。 基於行的 function 應該更快,並且是更直觀的構造。 可能最快的方法是分別為每一列編寫 2 個向量化表達式。 在這種情況下,類似於:
df['new_A'] = df.A + df.B
df['new_B'] = df.C + '_xx'
但通常問題是基於行的 function 是否可以表示為矢量化表達式(正如我上面所做的那樣)。 在“否定”情況下,您可以應用基於行的 function。
要比較每個解決方案的速度,請使用%timeit 。
這個問題似乎與這個問題有些相關。 我參考了@spen.smith 在這個答案上的評論。
df = pd.DataFrame([[1,2,3], [2,3,4], [3,5,7]], columns = ['A', 'B', 'C'])
print(df)
A B C
0 1 2 3
1 2 3 4
2 3 5 7
與其修改 function 的返回值,不如照常創建
def add_subtract(args):
arg1, arg2 = args
ret1 = arg1 + arg2
ret2 = arg1 - arg2
return ret1, ret2
檢查使用apply
的 output 。 選項result_type='expand'
將結果返回為 dataframe 而不是一系列元組。
print(df[['B', 'C']].apply(add_subtract, axis=1, result_type='expand'))
0 1
0 5 -1
1 7 -1
2 12 -2
然后,我們可以通過轉置然后訪問值將apply
output 的列分配給兩個新系列。 轉置是必要的,因為調用values
的默認行為將每一行視為一個列表,而我們希望每一列都作為一個列表。 所以最終的表達式是:
df['D'], df['E'] = df[['B', 'C']].apply(add_subtract, axis=1, result_type='expand').transpose().values
print(df)
A B C D E
0 1 2 3 5 -1
1 2 3 4 7 -1
2 3 5 7 12 -2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.