如何计算熊猫中一行中所有元素的加权和?

Posted

技术标签:

【中文标题】如何计算熊猫中一行中所有元素的加权和?【英文标题】:How to compute weighted sum of all elements in a row in pandas? 【发布时间】:2013-08-27 12:23:34 【问题描述】:

我有一个包含多列的 pandas 数据框。我想从行中的值和另一个列向量数据框 weight 中创建一个新列 weighted_sum

weighted_sum 应具有以下值:

row[weighted_sum] = row[col0]*weight[0] + row[col1]*weight[1] + row[col2]*weight[2] + ...

我找到了函数sum(axis=1),但它不允许我与weight 相乘。

编辑: 我改变了一些东西。

weight 看起来像这样:

     0
col1 0.5
col2 0.3
col3 0.2

df 看起来像这样:

col1 col2 col3
1.0  2.2  3.5
6.1  0.4  1.2

df*weight 返回一个包含 Nan 值的数据框。

【问题讨论】:

你能展示一些你的DataFrameweights吗?目前尚不清楚为什么您在执行此操作时遇到问题。如果您只想要weights 的行值的点积,请使用ndarray.dot 方法:row.values.dot(weights.values) 【参考方案1】:

问题在于,您将帧与具有不同行索引的不同大小的帧相乘。这是解决方案:

In [121]: df = DataFrame([[1,2.2,3.5],[6.1,0.4,1.2]], columns=list('abc'))

In [122]: weight = DataFrame(Series([0.5, 0.3, 0.2], index=list('abc'), name=0))

In [123]: df
Out[123]:
           a          b          c
0       1.00       2.20       3.50
1       6.10       0.40       1.20

In [124]: weight
Out[124]:
           0
a       0.50
b       0.30
c       0.20

In [125]: df * weight
Out[125]:
           0          a          b          c
0        nan        nan        nan        nan
1        nan        nan        nan        nan
a        nan        nan        nan        nan
b        nan        nan        nan        nan
c        nan        nan        nan        nan

您可以访问该列:

In [126]: df * weight[0]
Out[126]:
           a          b          c
0       0.50       0.66       0.70
1       3.05       0.12       0.24

In [128]: (df * weight[0]).sum(1)
Out[128]:
0         1.86
1         3.41
dtype: float64

或者使用dot找回另一个DataFrame

In [127]: df.dot(weight)
Out[127]:
           0
0       1.86
1       3.41

将所有内容整合在一起:

In [130]: df['weighted_sum'] = df.dot(weight)

In [131]: df
Out[131]:
           a          b          c  weighted_sum
0       1.00       2.20       3.50          1.86
1       6.10       0.40       1.20          3.41

这里是每个方法的timeits,使用更大的DataFrame

In [145]: df = DataFrame(randn(10000000, 3), columns=list('abc'))
weight
In [146]: weight = DataFrame(Series([0.5, 0.3, 0.2], index=list('abc'), name=0))

In [147]: timeit df.dot(weight)
10 loops, best of 3: 57.5 ms per loop

In [148]: timeit (df * weight[0]).sum(1)
10 loops, best of 3: 125 ms per loop

对于一个广泛的DataFrame

In [162]: df = DataFrame(randn(10000, 1000))

In [163]: weight = DataFrame(randn(1000, 1))

In [164]: timeit df.dot(weight)
100 loops, best of 3: 5.14 ms per loop

In [165]: timeit (df * weight[0]).sum(1)
10 loops, best of 3: 41.8 ms per loop

所以,dot 更快,更易读。

注意:如果您的任何数据包含NaNs,那么您不应该使用dot,您应该使用乘加法。 dot 无法处理 NaNs,因为它只是 numpy.dot() 的一个薄包装(它不能处理 NaNs)。

【讨论】:

我对这种速度提升感到非常惊讶,但实际上我不确定 dot 会产生相同的结果。和df.mul(weight).sum(1) 似乎差不多(如果慢一点)。 df.dot(weight) 如果dfweight 都是DataFrames,则将产生DataFrame,如果其中一个是Series,则产生Series,如果两者都是@987654347,则产生一个标量@。在数值上,它们是等价的。 加速可能是因为*操作创建的临时。 dot 不需要这样的临时 :) 原来dot 的作用与numpyNaNs 的作用相同:立即向你吐槽。 (df * weight).sum(1).head() != df.dot(weight).head() ?【参考方案2】:

假设权重是每列的一系列权重,您可以乘以求和:

In [11]: df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=['a', 'b', 'c'])

In [12]: weights = pd.Series([7, 8, 9], index=['a', 'b', 'c'])

In [13]: (df * weights)
Out[13]: 
    a   b   c
0   7  16  27
1  28  40  54

In [14]: (df * weights).sum(1)
Out[14]: 
0     50
1    122
dtype: int64

这种方法的好处是它可以处理您不想称重的列:

In [21]: weights = pd.Series([7, 8], index=['a', 'b'])

In [22]: (df * weights)
Out[22]: 
    a   b   c
0   7  16 NaN
1  28  40 NaN

In [23]: (df * weights).sum(1)
Out[23]: 
0    23
1    68
dtype: float64

【讨论】:

以上是关于如何计算熊猫中一行中所有元素的加权和?的主要内容,如果未能解决你的问题,请参考以下文章

如何计算熊猫系列列表中每个元素的出现次数?

如何使用带有询价和出价的熊猫数据框计算体积加权平均价格(VWAP)?

熊猫计算列中的元素并以重复的方式显示

熊猫数据框每一行的加权平均值

如何在嵌套字典中按元素访问熊猫多索引?

opencv图像操作