如何在pandas中将两个具有不同列标签的数据框相乘?

7
我试图对两个具有不同列标签的数据框进行乘法(加法/除法等)运算。
我相信这是可能的,但最好的方法是什么?我尝试使用rename先更改一个df上的列,但是(1)我宁愿不这样做,(2)我的真实数据在列上有多重索引(其中只有一层多重索引被不同地标记),而且对于这种情况,rename似乎很棘手...
因此,为了尝试概括我的问题,如何使用map定义要相乘的列来得到df1 * df2?
df1 = pd.DataFrame([1,2,3], index=['1', '2', '3'], columns=['a', 'b', 'c'])
df2 = pd.DataFrame([4,5,6], index=['1', '2', '3'], columns=['d', 'e', 'f'])
map = {'a': 'e', 'b': 'd', 'c': 'f'}

df1 * df2 = ?

在问题中,您说“不同的列”,但您的示例有“不同的索引”。这是哪一个? - Avaris
好的,我澄清了原始问题。 - jmloser
6个回答

10

我也曾经为这个问题困扰过。

看起来pandas需要矩阵相乘时,两个数据框必须具有相同的列名。

我进行了很多搜索,并在设置扩展中找到了一个例子,即向数据框添加一列。

对于你的问题,

rs = pd.np.multiply(ds2, ds1)

rs将与ds2具有相同的列名。

假设我们想要在同一数据框中将多个列与其他几个列相乘,并将这些结果附加到原始数据框中。

例如,ds1、ds2在同一个数据框ds中。我们可以

ds[['r1', 'r2', 'r3']] = pd.np.multiply(ds[['a', 'b', 'c']], ds[['d', 'e', 'f']])

我希望这些能够帮到你。

这个有文档吗? - ConanG
pd.np.multiply 是一个非常好的、干净的解决方案,正是我在保留其中一个数据框的列名时正在寻找的。谢谢。 - Florent

2

由于pd.np正在被弃用,因此更新解决方案如下:df1.multiply(np.array(df2)

它将保留df1的列名,并按顺序将其乘以df2的列


1

另一种解决方案是假设索引和列都被正确地定位:

df_mul= pd.DataFrame(df1.values * df2.values, columns= df1.columns, index= df1.index)

1

这是一个相当旧的问题,正如nnsk所说,pd.np正在被弃用。

一个不错的解决方案是df1 * df2.values。这将产生两个数据帧的逐元素乘积,并保留df1的列名。


1

我刚刚遇到了同样的问题。看起来 pandas 希望列和行索引都对齐才能进行逐元素乘法,所以您可以在乘法期间使用 rename 进行映射:

>>> df1 = pd.DataFrame([[1,2,3]], index=['1', '2', '3'], columns=['a', 'b', 'c'])
>>> df2 = pd.DataFrame([[4,5,6]], index=['1', '2', '3'], columns=['d', 'e', 'f'])
>>> df1
   a  b  c
1  1  2  3
2  1  2  3
3  1  2  3
>>> df2
   d  e  f
1  4  5  6
2  4  5  6
3  4  5  6
>>> mapping = {'a' : 'e', 'b' : 'd', 'c' : 'f'}
>>> df1.rename(columns=mapping) * df2
   d  e   f
1  8  5  18
2  8  5  18
3  8  5  18

如果您想要“自然”列的顺序,可以像这样动态创建映射:
>>> df1 * df2.rename(columns=dict(zip(df2.columns, df1.columns)))

例如,要计算两个矩阵的“Frobenius内积”,可以执行以下操作:
>>> (df1 * df2.rename(columns=dict(zip(df2.columns, df1.columns)))).sum().sum()
96

0

假设索引已经对齐,您可能只想按正确顺序对齐两个DataFrame中的列,并将两个DataFrame的.values相除。

假设mapping = {'a' : 'e', 'b' : 'd', 'c' : 'f'}

v1 = df1.reindex(columns=['a', 'b', 'c']).values
v2 = df2.reindex(columns=['e', 'd', 'f']).values
rs = DataFrame(v1 / v2, index=v1.index, columns=['a', 'b', 'c'])

1
希望有比直接操作值并构建新数据框更“简洁”的解决方案。也许没有。 - jmloser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接