假設我有以下形式的資料(作為 Pandas 的資料框):
| 指數 | ID | 價值 | 分割因子 | 加權和 |
|---|---|---|---|---|
| 1 | 1 | 2 | 1 | |
| 2 | 1 | 3 | 2 | |
| 3 | 2 | 6 | 1 | |
| 4 | 1 | 1 | 3 | |
| 5 | 2 | 3 | 2 | |
| 6 | 2 | 9 | 3 | |
| 7 | 2 | 8 | 4 | |
| 8 | 3 | 5 | 1 | |
| 9 | 3 | 6 | 2 | |
| 10 | 1 | 8 | 4 | |
| 11 | 3 | 2 | 3 | |
| 12 | 3 | 7 | 4 |
我想計算列Weighted Sum如下(對于 $i$ -th 行):
- 查看從第 1 行到 的所有值
i。 ID根據每行的值按組對值求和。所以我們有k總和值,其中k是從第 1 行到第 1 行的唯一ID值的數量i。- 將每個總和(有
k總和值)除以組中的元素數。 - 將這些
k值相加并除以k(平均值的平均值)。
例如,讓我們執行第 1、7 和 12 行:
第 1 行
因為i = 1我們只有一個值,因此總和為 2,單個組的平均值為 2,所有組的平均值為 2。
第 7 行
因為i = 7我們ID上面只有 2 個唯一值:1 和 2。
對于ID = 1我們有的組:(1 3 2) / 3 = 2。
對于ID = 2我們有的組:(8 9 3 6) / 4 = 6.5。
那么平均值的平均值為 (2 6.5) / 2 = 4.25。
第 12 行
因為i = 12我們ID在 rows 上有 3 個唯一值1:12。
對于ID = 1我們有的組:(8 1 3 2) / 4 = 3.5。
對于ID = 2我們有的組:(8 9 3 6) / 4 = 6.5。
對于ID = 3我們有的組:(7 2 6 5) / 4 = 5。
那么平均值的平均值是 (3.5 6.5 5) / 3 = 5。
使用回圈很容易做到,但對于大量行,它是低效的。有沒有一種有效的方法來做到這一點?也許使用apply()or transform()?
備注1e7:該方法對于 ~行和 ~1e6唯一 ID 的情況應該是可行的。
uj5u.com熱心網友回復:
這應該可以滿足您的要求:
df1 = df[['ID', 'Value']].set_index('ID', append=True).unstack(-1)
df2 = df1.fillna(0).cumsum() / df1.notnull().astype(int).cumsum()
df['Weighted Sum'] = df2.mean(axis=1)
(根據@Accumulation 的評論簡化最后一行。)
輸出:
Index ID Value Div Factor Weighted Sum
0 1 1 2 1 2.000000
1 2 1 3 2 2.500000
2 3 2 6 1 4.250000
3 4 1 1 3 4.000000
4 5 2 3 2 3.250000
5 6 2 9 3 4.000000
6 7 2 8 4 4.250000
7 8 3 5 1 4.500000
8 9 3 6 2 4.666667
9 10 1 8 4 5.166667
10 11 3 2 3 4.777778
11 12 3 7 4 5.000000
解釋:
- 用于
unstack()透視,將唯一的ID列值轉換為列標簽級別,列Value中的每一行的條目與原始資料框的值匹配ID,而在所有其他位置為 NaN - 使用
fillna(0)和cumsum()將每列替換為其累積總和 - 使用
notnull().astype(int)andcumsum()將每列替換為其累積計數(其中 NaN 計為 0) - 取累計和與累計計數的比值;
Value這是每個唯一的每個連續行的累積平均值ID - 對于每一行,取所有唯一值的非 NaN 累積平均值的平均值
ID。這是問題中描述的結果。
詳細的中間結果:
Index ID Value Div Factor
0 1 1 2 1
1 2 1 3 2
2 3 2 6 1
3 4 1 1 3
4 5 2 3 2
5 6 2 9 3
6 7 2 8 4
7 8 3 5 1
8 9 3 6 2
9 10 1 8 4
10 11 3 2 3
11 12 3 7 4
df[['ID', 'Value']].set_index('ID', append=True).unstack(-1)
Value
ID 1 2 3
0 2.0 NaN NaN
1 3.0 NaN NaN
2 NaN 6.0 NaN
3 1.0 NaN NaN
4 NaN 3.0 NaN
5 NaN 9.0 NaN
6 NaN 8.0 NaN
7 NaN NaN 5.0
8 NaN NaN 6.0
9 8.0 NaN NaN
10 NaN NaN 2.0
11 NaN NaN 7.0
df1.fillna(0).cumsum()
Value
ID 1 2 3
0 2.0 0.0 0.0
1 5.0 0.0 0.0
2 5.0 6.0 0.0
3 6.0 6.0 0.0
4 6.0 9.0 0.0
5 6.0 18.0 0.0
6 6.0 26.0 0.0
7 6.0 26.0 5.0
8 6.0 26.0 11.0
9 14.0 26.0 11.0
10 14.0 26.0 13.0
11 14.0 26.0 20.0
df1.notnull().astype(int).cumsum()
Value
ID 1 2 3
0 1 0 0
1 2 0 0
2 2 1 0
3 3 1 0
4 3 2 0
5 3 3 0
6 3 4 0
7 3 4 1
8 3 4 2
9 4 4 2
10 4 4 3
11 4 4 4
df2 = df1.fillna(0).cumsum() / df1.notnull().astype(int).cumsum()
Value
ID 1 2 3
0 2.0 NaN NaN
1 2.5 NaN NaN
2 2.5 6.0 NaN
3 2.0 6.0 NaN
4 2.0 4.5 NaN
5 2.0 6.0 NaN
6 2.0 6.5 NaN
7 2.0 6.5 5.000000
8 2.0 6.5 5.500000
9 3.5 6.5 5.500000
10 3.5 6.5 4.333333
11 3.5 6.5 5.000000
result with df['Weighted Sum'] = df2.mean(axis=1)
Index ID Value Div Factor Weighted Sum
0 1 1 2 1 2.000000
1 2 1 3 2 2.500000
2 3 2 6 1 4.250000
3 4 1 1 3 4.000000
4 5 2 3 2 3.250000
5 6 2 9 3 4.000000
6 7 2 8 4 4.250000
7 8 3 5 1 4.500000
8 9 3 6 2 4.666667
9 10 1 8 4 5.166667
10 11 3 2 3 4.777778
11 12 3 7 4 5.000000
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/497578.html
