pandas 在唯一主键对上合并n个 Dataframe

lf3rwulv  于 2023-04-04  发布在  其他
关注(0)|答案(2)|浏览(105)

我现在有一个dataframes的字典:

df_dict = {'apple': a_df, 'bees': b_df, 'food': c_df, 'yum': d_df}

每个dataframe都有嵌入其中的唯一主键。每个df的主键使用以下方法创建:df[p_k] = df[a] + df[b] + df[c]

df_dict['apple']
a b c d p_k
9 5 3 4 953
3 6 4 9 364
7 6 5 1 765

df_dict['bees']
a b c d p_k
9 5 3 2 953

df_dict['food']
a b c d p_k
7 6 5 3 765
1 2 1 7 121

df_dict['yum']
a b c d p_k
3 6 4 0 364
1 2 1 8 121

我们的目标是以一种计算效率高的方式(可能吗?)合并p_k上的所有 Dataframe 。每个p_k在不同的 Dataframe 中有恰好1个匹配对。匹配的p_k可以在dict中的任何 Dataframe 中找到。
上例的最终目标是如下所示

final_df
a b c d d_y p_k
9 5 3 4  2  953
3 6 4 9  0  364
1 2 1 7  8  121
7 6 5 1  3  765

我对.merge函数有一个基本的了解,但我正在寻找一种有效的搜索方法,因为真实的的问题是一个有30个 Dataframe 的dict,每个 Dataframe 有70行。

nhn9ugyo

nhn9ugyo1#

IIUC你想在合并两个 Dataframe 时保留第一个出现的行吗?如果是这样的话,你可以在每次连接两个 Dataframe 时对 Dataframe 值使用functools.reduce,并使用drop_duplicates删除重复的 Dataframe (默认情况下保留第一个值keep='first')
现在你还想保留d列。为此,你可以做的是再次减少,但这一次drop_duplicates基于除d之外的所有列,在这种情况下,删除p_k就足够了,并保留最后一个值。
然后合并这两个简化的 Dataframe 。代码如下所示:

from functools import reduce
df1 = reduce(
    lambda df1, df2: pd.concat([df1, df2], ignore_index=True).drop_duplicates("p_k"),
    df_dict.values(),
)
df2 = reduce(
    lambda df1, df2: pd.concat([df1, df2]).drop_duplicates(
        "p_k", keep="last", ignore_index=True
    ),
    df_dict.values(),
)
out = df1.merge(df2, on=["a", "b", "c", "p_k"], suffixes=("", "_y"))
print(out)

   a  b  c  d  p_k  d_y
0  9  5  3  4  953    2
1  3  6  4  9  364    0
2  7  6  5  1  765    3
3  1  2  1  7  121    8
v440hwme

v440hwme2#

试试这样的方法:

dc=pd.concat([d.set_index('p_k') for d in df_dict.values()])
dc_out=dc.assign(grp=dc.groupby(['p_k', 'a', 'b', 'c'])['d'].cumcount())\
         .set_index(['a', 'b','c', 'grp'], append=True)\
         .unstack('grp')

dc_out.columns = [f'{i}_y' if j==1 else f'{i}' for i, j in dc_out.columns]
df_out = dc_out.reset_index()
print(df_out)

输出:

p_k  a  b  c  d  d_y
0  121  1  2  1  7    8
1  364  3  6  4  9    0
2  765  7  6  5  1    3
3  953  9  5  3  4    2

相关问题