如何计算熊猫中一行中所有元素的加权和?
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
值的数据框。
【问题讨论】:
你能展示一些你的DataFrame
和weights
吗?目前尚不清楚为什么您在执行此操作时遇到问题。如果您只想要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
这里是每个方法的timeit
s,使用更大的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
更快,更易读。
注意:如果您的任何数据包含NaN
s,那么您不应该使用dot
,您应该使用乘加法。 dot
无法处理 NaN
s,因为它只是 numpy.dot()
的一个薄包装(它不能处理 NaN
s)。
【讨论】:
我对这种速度提升感到非常惊讶,但实际上我不确定 dot 会产生相同的结果。和df.mul(weight).sum(1)
似乎差不多(如果慢一点)。
df.dot(weight)
如果df
和weight
都是DataFrames
,则将产生DataFrame
,如果其中一个是Series
,则产生Series
,如果两者都是@987654347,则产生一个标量@。在数值上,它们是等价的。
加速可能是因为*
操作创建的临时。 dot
不需要这样的临时 :)
原来dot
的作用与numpy
对NaN
s 的作用相同:立即向你吐槽。
(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
【讨论】:
以上是关于如何计算熊猫中一行中所有元素的加权和?的主要内容,如果未能解决你的问题,请参考以下文章