[英]Subtract multiple columns based on foreign key in pandas
我試圖計算一個對象和它的基准之間的差異。 我有一個數據集,其中包含所有對象的日常記錄及其對應的值,如下所示:
obj_df
date id value_a value_b value_c value_d benchmark_id
01/21/2015 abc 10 41 19 22 efg
01/22/2015 abc 15 43 11 21 efg
01/21/2015 xyz 16 45 13 26 tuv
01/22/2015 xyz 13 48 12 22 tuv
01/21/2015 tru 10 39 15 21 efg
01/21/2015 tru 11 37 13 20 efg
我也有關於基准的數據。 值列在數據框之間共享。 基准集中的id對應於原始對象數據幀中的基准ID。
bm_df
date id value_a value_b value_c value_d
01/21/2015 efg 12 40 12 20
01/22/2015 efg 15 41 14 21
01/21/2015 tuv 14 42 11 19
01/22/2015 tuv 13 43 19 17
我試圖找到一種簡單的方法來返回一個數據幀,它給出了對象值和相應基准值之間的差異,以獲得看起來像這樣的數據幀。
diff_df
date id diff_a diff_b diff_c diff_d benchmark_id
01/21/2015 abc -2 1 7 2 efg
01/22/2015 abc 0 2 -3 0 efg
01/21/2015 xyz 2 3 2 7 tuv
01/22/2015 xyz 0 5 -7 5 tuv
01/21/2015 tru -4 -3 4 2 efg
01/21/2015 tru -2 -6 -6 3 efg
有幾點需要注意:
- 有多個對象而不是基准,因此索引的大小不同。
- 每個對象都有一個基准。
- 我並不特別關心原始價值觀。 差別。
- 某些基准對應於多個對象。 例如,'abc'和'tru'都使用'efg'作為基准。
我認為你可以使用sub
,然后通過concat
和last reindex
列添加列id
和benchmark_id
到obj_df
列的相同順序:
print (obj_df)
value_a value_b value_c value_d benchmark_id
date id
01/21/2015 abc 10 41 19 22 efg
01/22/2015 abc 15 43 11 21 efg
01/21/2015 xyz 16 45 13 26 tuv
01/22/2015 xyz 13 48 12 22 tuv
print (bm_df)
value_a value_b value_c value_d
date id
01/21/2015 efg 12 40 12 20
01/22/2015 efg 15 41 14 21
01/21/2015 tuv 14 42 11 19
01/22/2015 tuv 13 43 19 17
obj_df.reset_index(level=1, inplace=True)
bm_df.reset_index(level=1, inplace=True)
cols = ['value_a','value_b','value_c', 'value_d']
df = obj_df[cols].sub(bm_df[cols])
df = pd.concat([df, obj_df[['id','benchmark_id']]], axis=1)
.reindex(columns=obj_df.columns)
.reset_index()
print (df)
date id value_a value_b value_c value_d benchmark_id
0 01/21/2015 abc -2 1 7 2 efg
1 01/22/2015 abc 0 2 -3 0 efg
2 01/21/2015 xyz 2 3 2 7 tuv
3 01/22/2015 xyz 0 5 -7 5 tuv
腳步:
執行合並:
df = obj_df.merge(bm_df, left_on=['benchmark_id', 'date'], right_on=['id', 'date']) \
.drop(['id_y'], 1).set_index(['date'])
Helper函數通過輸入起始和結束列名來查找列索引位置:
def col_locate(df, start, end):
start_loc = df.columns.get_loc(start)
end_loc = df.columns.get_loc(end)
return list(range(start_loc, end_loc+1))
fir, sec = col_locate(df,'value_a_x','value_d_x'), col_locate(df,'value_a_y','value_d_y')
從objectDF
和benchmarkDF
減去值:
df_diff = pd.DataFrame(df.iloc[:, fir].values - df.iloc[:, sec].values,
columns=list('abcd'), index=df.index).add_prefix('diff_')
最后,以列方式連接它們:
pd.concat([df[['id_x', 'benchmark_id']], df_diff], axis=1)
注意:更新的DF
用於得出結果。
使用合並:
#inner join on FK
merge = obj_df.merge(bm_df, left_on = 'benchmark_id', right_on = 'id', suffixes = ['_obj', '_bm'])
#create new columns
for value in ['a', 'b', 'c']:
merge.loc[:, 'diff_%s'%value] = merge['value_%s_obj'%value] - merge['value_%s_bm'%value]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.