熊猫 - 在连接 / 合并数据框之前检查列

2024-09-28 22:22:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含用户的数据帧,每个用户都有多个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

2个包含部分用户ID的其他数据帧:

^{pr2}$

我想根据id将所有3个合并在一起,但是,uidx可以匹配id1或{}中的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

我的实际数据每个dataframe有数百个列,其中的列名变化很大,所以我寻找一种不需要单独/手动处理每个列的方法。换句话说,我正在寻找一种不需要手动指定列/数据帧名称的通用方法


Tags: 数据用户iddfgroupnanerdid1
2条回答

一般情况下:

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来避免使用列名。在

这里有一个方法可以避免多次合并每个数据帧,方法是将原始数据帧的多个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)

结果如下:

^{pr2}$

相关问题 更多 >