熊猫枢轴并加入两个数据框

Posted

技术标签:

【中文标题】熊猫枢轴并加入两个数据框【英文标题】:pandas pivot and join in two dataframes 【发布时间】:2019-01-07 20:20:27 【问题描述】:

我有两个数据框:

df1
   mag   cat
0  101   A1
1  256   A2  
2  760   A2
3  888   A3  
...

df2
   A1    A2    A3    ...
0  E50R  AZ33  REZ3 
1  T605  YYU6  YHG5
2  IR50  P0O9  BF53
3  NaN   YY9I  NaN

我想创建一个最终的 DataFrame,如下所示:

df
   101   256   760   888  ...
0  E50R  AZ33  AZ33  REZ3
1  T605  YYU6  YYU6  YHG5
2  IR50  P0O9  P0O9  BF53
3  NaN   YY9I  YY9I  NaN

我尝试了一些带有枢轴的东西,但它似乎没有完成这项工作 你能帮帮我吗?

【问题讨论】:

Here 是在 SO 上发布好问题的指南。你应该展示你迄今为止尝试过的东西。 我认为转置其中一张表并加入它们可能会奏效。 我认为 Josh 是对的,但您可能应该从清理数据开始。可能值得一试jstatsoft.org/article/view/v059i10 这已经是一个“最小”的例子了。我应该做些什么来最小化它? “清理数据”是什么意思? 【参考方案1】:

这比 Wen 的解决方案慢,但我认为概念上更简单:

newdf = df2[df1.cat]
newdf.columns = df1.mag

第一行说“newdf 的第 i 列应该是与df1.cat 的第 i 个元素对应的 df2 的列”。第二行说“newdf的列应该按照df1.mag命名”

【讨论】:

【参考方案2】:

您可以使用GroupBynumpy.repeatitertools.chain 的组合:

from itertools import chain

# map cat to list of mag
s = df1.groupby('cat')['mag'].apply(list)

# calculate indices for columns, including repeats
cols_idx = np.repeat(range(len(df2.columns)), s.map(len))

# apply indexing
res = df2.iloc[:, cols_idx]

# rename columns
res.columns = list(chain.from_iterable(df2.columns.map(s.get)))

print(res)

    101   256   760   888
0  E50R  AZ33  AZ33  REZ3
1  T605  YYU6  YYU6  YHG5
2  IR50  P0O9  P0O9  BF53
3   NaN  YY9I  YY9I   NaN

性能基准测试

这里有一些不错的不同解决方案,因此您可能对性能感兴趣。 Wen 的reindex 解决方案显然是赢家。

%timeit wen(df1, df2)   # 632 µs per loop
%timeit jpp(df1, df2)   # 2.55 ms per loop
%timeit scb(df1, df2)   # 7.98 ms per loop
%timeit abhi(df1, df2)  # 4.52 ms per loop

代码:

def jpp(df1, df2):
    s = df1.groupby('cat')['mag'].apply(list)
    cols_idx = np.repeat(range(len(df2.columns)), s.map(len))
    res = df2.iloc[:, cols_idx]
    res.columns = list(chain.from_iterable(df2.columns.map(s.get)))    
    return res

def scb(df1, df2):
    df_out = (df2.stack().reset_index()
                 .merge(df1, left_on='level_1', right_on='cat')[['level_0','mag',0]])
    return df_out.pivot('level_0','mag',0).reset_index(drop=True)    

def abhi(df1, df2):
    return df2.T.merge(df1, left_index=True, right_on='cat').drop('cat', axis=1).set_index('mag').T

def wen(df1, df2):
    newdf=df2.reindex(columns=df1.cat)
    newdf.columns=df1.mag
    return newdf

【讨论】:

【参考方案3】:

IIUC reindex +re-name

newdf=df2.reindex(columns=df1.cat)
newdf.columns=df1.mag
newdf
Out[519]: 
mag   101   256   760   888
0    E50R  AZ33  AZ33  REZ3
1    T605  YYU6  YYU6  YHG5
2    IR50  P0O9  P0O9  BF53
3     NaN  YY9I  YY9I   NaN

【讨论】:

【参考方案4】:

您可以通过转置和合并来完成此操作,然后将列“mag”设置为索引。然后再次转置它。

df2_transposed = df2.T
res = df2_transposed.merge(df1,how = "left",left_index=True,right_on='cat')
del res['cat']
res.set_index('mag', inplace=True)
res.T

mag 101      256    760     888
0   E50R    AZ33    AZ33    REZ3
1   T605    YYU6    YYU6    YHG5
2   IR50    P0O9    P0O9    BF53
3           YY9I    YY9I    

【讨论】:

不错。我也喜欢这个解决方案。仅供参考,如果您愿意 df2.T.merge(df1, left_index=True, right_on='cat').drop('cat', axis=1).set_index('mag').T【参考方案5】:

使用stackmergepivot 的另一种方法:

df_out = (df2.stack().reset_index()
             .merge(df1, left_on='level_1', right_on='cat')[['level_0','mag',0]])

df_out.pivot('level_0','mag',0).reset_index(drop=True)

输出:

mag   101   256   760   888
0    E50R  AZ33  AZ33  REZ3
1    T605  YYU6  YYU6  YHG5
2    IR50  P0O9  P0O9  BF53
3     NaN  YY9I  YY9I   NaN

【讨论】:

不错的 2-liner +1 :)。但我认为stack 让这变得很慢(我总是想知道为什么他们不能让它更快)。 我同意。您可能可以在那里使用 melt 。

以上是关于熊猫枢轴并加入两个数据框的主要内容,如果未能解决你的问题,请参考以下文章

加入两个熊猫数据框

根据线序加入两个熊猫数据框

根据多个条件加入两个熊猫数据框

加入两个具有重复值的熊猫数据框[重复]

无法加入熊猫中的数据框

带有自定义列的熊猫枢轴