熊猫枢轴并加入两个数据框
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】:您可以使用GroupBy
、numpy.repeat
、itertools.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】:
使用stack
、merge
和pivot
的另一种方法:
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 。以上是关于熊猫枢轴并加入两个数据框的主要内容,如果未能解决你的问题,请参考以下文章