複数の列を持つ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
値でいっぱいのデータフレームを返します。
問題は、フレームに、異なる行インデックスを持つ異なるサイズのフレームを乗算していることです。解決策は次のとおりです。
_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
を使用した、各メソッドのDataFrame
sを次に示します。
_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
はnumpy.dot()
(NaN
sを処理しない)の単なる薄いラッパーであるため、NaN
sを処理できません。
重みが各列の一連の重みであると仮定すると、乗算して合計を行うことができます。
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