【问题标题】:Python - multiplying dataframes of different sizePython - 将不同大小的数据帧相乘
【发布时间】:2018-07-12 10:43:10
【问题描述】:

我有两个数据框:

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

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

当我执行乘法时,出现以下错误:

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 之间的唯一区别是“All”列和行的存在/不存在。

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

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

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

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

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

【问题讨论】:

    标签: python pandas dataframe pivot-table multiplication


    【解决方案1】:

    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
    

    【讨论】:

    • 知道如何从第一个 df 添加值来代替 NaN 肯定会派上用场。不过,我试图弄清楚的是,为什么我根本无法将两个真实世界的数据帧相乘。我收到一个错误:ValueError:无法加入,没有指定级别且没有重叠名称。当我尝试方法 df1.mul(df2, fill_value=1) 我得到一个错误: TypeError: f() got multiple values for argument 'fill_value'
    • @Tatiana 询问有关您的真实世界数据的问题可能很困难。但是学习如何将现实世界的数据减少到仍然存在问题的最小表示是一项值得练习的技能。尽最大努力向我们展示您所表达的问题本身的真实世界数据的最小样本。
    【解决方案2】:

    我真的很喜欢 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
    

    【讨论】:

    • 这似乎是一个优雅的解决方案——它甚至保留了布局!但是,我仍然无法将我的真实世界数据帧相乘。我用这种方法得到的错误是:KeyError: "None of [Index(['CR Range', 'CR Below 85', 'CR 85-95', 'CR 95-105', 'CR 105-115',\n 'CR 115-122', 'CR Above 122'],\n dtype='object')] are in the [columns]" 这些是我的 bins/categories 用于通过 pivot_table 方法聚合的原始数据。从视觉上看,它们肯定在那里,但似乎 python 没有看到它们..
    • @Tatiana 也许将您的样本数据稍微修改为您的真实数据格式?
    【解决方案3】:

    @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?

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

    然后我可以毫无问题地将这两个数据帧相乘。我使用了@Wen 建议的方法,因为我喜欢它保留了结构。

    【讨论】:

      猜你喜欢
      • 2019-02-28
      • 2022-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-12
      • 1970-01-01
      • 2013-02-17
      相关资源
      最近更新 更多