Python - 将不同大小的数据帧相乘

时间:2018-02-02 00:43:29

标签: python pandas dataframe pivot-table multiplication

我有两个数据帧:

df1 - 是一个数据透视表,其中包含列和行的总计,两者都具有默认名称"所有" df2 - 我通过指定值并使用与上面数据透视表中使用的索引和列名相同的手动创建的df。此表没有总计。

我需要将第一个数据帧乘以第二个数据帧中的值。我预计总数将返回NaNs,因为总数不会存在于第二个表中。

当我执行乘法时,我收到以下错误:

ValueError: cannot join with no level specified and no overlapping names

当我在虚拟数据帧上尝试相同时,它按预期工作:

import pandas as pd
import numpy as np
table1 = np.matrix([[10, 20, 30, 60],
                  [50, 60, 70, 180],
                  [90, 10, 10, 110],
                  [150, 90, 110, 350]])
df1 = pd.DataFrame(data = table1, index = ['One','Two','Three', 'All'], columns =['A', 'B','C', 'All'] )
print(df1)

table2 = np.matrix([[1.0, 2.0, 3.0],
                  [5.0, 6.0, 7.0],
                  [2.0, 1.0, 5.0]])
df2 = pd.DataFrame(data = table2, index = ['One','Two','Three'], columns =['A', 'B','C'] )
print(df2)

df3 = df1*df2
print(df3)

这给了我以下输出:

         A   B    C  All
One     10  20   30   60
Two     50  60   70  180
Three   90  10   10  110
All    150  90  110  350

         A    B    C
One   1.00 2.00 3.00
Two   5.00 6.00 7.00
Three 2.00 1.00 5.00

           A  All      B      C
All      nan  nan    nan    nan
One    10.00  nan  40.00  90.00
Three 180.00  nan  10.00  50.00
Two   250.00  nan 360.00 490.00

因此,在视觉上,df1和df2之间的唯一区别是列和行的存在/不存在"所有"。

我认为我的虚拟数据帧和真实数据帧之间的唯一区别是真正的df1是使用pd.pivot_table方法创建的:

df1_real = pd.pivot_table(PY, values = ['Annual Pay'], index = ['PAR Rating'],
          columns = ['CR Range'], aggfunc = [np.sum], margins = True)

我确实需要保留总数,因为我在其他计算中使用它们。

我确定有一种解决方法,但我真的想了解为什么相同的代码适用于不同大小的某些数据帧但不适用于其他数据帧。或者问题可能完全不同。

感谢您的阅读。我意识到这是一个很长的帖子..

3 个答案:

答案 0 :(得分:2)

IIUC,

我的首选方法
您可以使用mul方法传递fill_value参数。在这种情况下,您需要一个值1(乘法标识)来保留值不会丢失的数据帧中的值。

df1.mul(df2, fill_value=1)

           A    All      B      C
All    150.0  350.0   90.0  110.0
One     10.0   60.0   40.0   90.0
Three  180.0  110.0   10.0   50.0
Two    250.0  180.0  360.0  490.0

替代方法
您还可以接受np.nan并使用后续combine_first填写df1

中缺少的内容
(df1 * df2).combine_first(df1)

           A    All      B      C
All    150.0  350.0   90.0  110.0
One     10.0   60.0   40.0   90.0
Three  180.0  110.0   10.0   50.0
Two    250.0  180.0  360.0  490.0

答案 1 :(得分:1)

我真的很喜欢Pir的方法,这是我的:-)

df1.loc[df2.index,df2.columns]*=df2
df1
Out[293]: 
           A      B      C  All
One     10.0   40.0   90.0   60
Two    250.0  360.0  490.0  180
Three  180.0   10.0   50.0  110
All    150.0   90.0  110.0  350

答案 2 :(得分:0)

@Wen,@ piRSquared,谢谢你的帮助。这就是我最终做的事情。可能有一个更优雅的解决方案,但这对我有用。

由于我能够将两个不同大小的虚拟数据帧相乘,我推断问题的大小并不大,但事实上其中一个数据帧是作为数据透视表创建的。不知何故,在此数据透视表中,标题未被识别,尽管在视觉上它们在那里。所以,我决定将数据透视表转换为常规数据帧。我采取的步骤:

  1. 使用此线程中的解决方案将数据透视表转换为记录,然后返回到数据框:pandas pivot table to data frame
  2. 使用上述同一线程中的解决方案清除列标题:pandas pivot table to data frame

  3. 在此帖子中将我的第一列设置为以下建议的索引:How to remove index from a created Dataframe in Python?

  4. 这给了我一个与之前相同的数据框,但不再是数据透视表。

    然后我能够将这两个数据帧相乘而没有任何问题。我使用了@Wen建议的方法,因为我喜欢它保留了结构。