我有一个包含用户的数据框,每个用户都有多个ID:
df_id = pd.DataFrame({'group': ['a','a','b','b','a','a','b','b','a','a','b','b'],
'id1': ['erd','hgf','ewr','fgv','nbg','axc','bcv','ijh','plh','wqe','mnf','iud'],
'id2': ['dfg','bcw','urz','fwq','nfg','dfo','hiy','fgl','vcw','erq','dfi','vcs']})
df_id
group id1 id2
0 a erd dfg
1 a hgf bcw
2 b ewr urz
3 b fgv fwq
4 a nbg nfg
5 a axc dfo
6 b bcv hiy
7 b ijh fgl
8 a plh vcw
9 a wqe erq
10 b mnf dfi
11 b iud vcs
包含部分用户ID的其他2个数据框:
df_1 = pd.DataFrame({'uid1': ['ewr','nbg','hiy','dfg','wqe'],
'q': [1,1,0,1,0]
})
df_1
q uid1
0 1 ewr
1 1 nbg
2 0 hiy
3 1 dfg
4 0 wqe
df_2 = pd.DataFrame({'uid2': ['urz','nbg','axc','fgl','vcw'],
'q': ['low','high','low','high','high']
})
df_2
q uid2
0 low urz
1 high nbg
2 low axc
3 high fgl
4 high vcw
我想根据ID将所有3个合并在一起,但uidx
可以匹配id1
中的id2
或df_id
,所以我无法加入单列。此外,df_id
包含的用户数多于其他两个数据框中的任何一个,因此我预计会有很多NaN
我认为执行此合并/连接的唯一方法是遍历df_id
并检查两个id
列并手动添加其他数据帧中的值,但这非常慢。如果我要加入的值可以在id
列中,那么合并/加入的正确方法是什么?
所需的输出是:
group id1 id2 q_1 q_2
0 a erd dfg 1.0 NaN
1 a hgf bcw NaN NaN
2 b ewr urz 1.0 low
3 b fgv fwq NaN NaN
4 a nbg nfg 1.0 high
5 a axc dfo NaN low
6 b bcv hiy 0.0 NaN
7 b ijh fgl NaN high
8 a plh vcw NaN high
9 a wqe erq 0.0 NaN
10 b mnf dfi NaN NaN
11 b iud vcs NaN NaN
我的实际数据每个数据框有数百列,其中列名称变化很大,因此我寻找一种不需要单独/手动处理每列的方法。换句话说,我正在寻找一种不需要我手动指定列/数据帧名称的通用方法
答案 0 :(得分:1)
通常:
df_1 = df_1.set_index('uid1')
q_a = df_id.join(df_1,on='id1')
q_b = df_id.join(df_1,on='id2')
df_id['q_1'] = q_a['q'].fillna(q_b['q'])
在df_2上重复此操作,或者提取一个函数并将其应用于df_2。也许使用iloc
来避免使用列名。
答案 1 :(得分:0)
这是一种避免多次合并每个数据帧的方法,方法是将原始数据框的多个id*
列堆叠到一个id
列中,然后将每个数据帧合并一次。我不能保证你的数据会比更直接的方法更快(但如果不是,请告诉我)。
import numpy as np
# Set some initial arguments (you might do this programmatically instead)
id_cols = ['id1', 'id2']
df_list = [df_1, df_2]
q_list = ['q_{0}'.format(n + 1) for n in range(len(df_list))]
# Make a new df stacking all the id columns
s = df_id[id_cols].stack()
s.name = 'id'
df = pd.DataFrame(s).reset_index()
# Merge each dataframe on the id column once
for n, df_n in enumerate(df_list):
df_n.rename(columns={'q': 'q_{0}'.format(n + 1)}, inplace=True)
df = df.merge(df_n, left_on='id', right_on='uid{0}'.format(n + 1), how='left')
del df['uid{0}'.format(n + 1)]
# If there are multiple values that match, reconcile them
df = df.set_index(['level_0', 'level_1']).unstack(level=-1)
df = df.loc[:, q_list].groupby(level=0, axis=1).max(axis=1).replace({None: np.nan})
# Re-merge with the original dataframe
df_id.merge(df, left_index=True, right_index=True)
这给出了以下结果:
group id1 id2 q_1 q_2
0 a erd dfg 1.0 NaN
1 a hgf bcw NaN NaN
2 b ewr urz 1.0 low
3 b fgv fwq NaN NaN
4 a nbg nfg 1.0 high
5 a axc dfo NaN low
6 b bcv hiy 0.0 NaN
7 b ijh fgl NaN high
8 a plh vcw NaN high
9 a wqe erq 0.0 NaN
10 b mnf dfi NaN NaN
11 b iud vcs NaN NaN