我想根据每行值(不包括NaN)在排序值列表中的位置来分配每个值的位置。我无法弄清楚如何用大熊猫的优雅方式来做到这一点。Python熊猫:根据每行排序值(不包括NaN)分配标签
我觉得它更容易在一个例子来解释:
A B C D
Date
2002-02-28 -0.051272 -0.005851 -0.012669 NaN
2002-03-29 0.103416 0.050121 0.050203 0.5
2002-04-30 -0.090579 -0.042308 0.019293 0.03
2002-05-31 0.160239 -0.078983 0.047319 0.66
的每一行,我要做到以下几点:
- 排除NaN的
- 计算中值的位置在该行中排序值的列表并分配该数字(位置1是最小(负)数且位置N是最大正数)
其结果将是:
A B C D
Date
2002-02-28 1 3 2 NaN
2002-03-29 3 1 2 4
2002-04-30 1 2 3 4
2002-05-31 3 1 2 4
在第二步骤中,我比想使一个3行每列的“滚动”的功能,它检查当前行是否和一个式柱内的2行之前是小于某个阈值X,如果是,则显示这3个值的平均值,否则只记下NaN。如果这三个值中的任何一个都是NaN,那么只记下NaN。只能从2002-04-30进行计算,因为需要至少3个值。对于D列,这将在2002-04-30行中产生“NaN”,因为事先只有两个数值。对于D列和2002-05-31行,它也会产生“NaN”,因为3个值分别是4,4和4,其中4个大于阈值。
假设阈值X = 3。 (我离开了列d,因为我的解释使数据以宽):
例如为:
A B C
Date
2002-02-28 NaN NaN NaN
2002-03-29 NaN NaN NaN
2002-04-30 Avg(1,3,1) Avg(3,1,2) Avg(2+2+3)
2002-05-31 Avg(3,1,3) Avg(1,2,1) Avg(2+3+2)
编辑: 我觉得我有两个步骤自己。能否请您评价是否正确和明智的?:
import numpy as np
import pandas as pd
df = pd.DataFrame(data={'X': [0.1, 0.2, 0.3, 0.4], 'Y': [0.5, -0.2, np.NaN, -1], 'Z': [np.NaN, -0.21, -5, 10]})
df.apply(lambda row: [sorted([y for y in row if not np.isnan(y)]).index(x)+1 if not np.isnan(x) else np.NaN for x in row], axis=1)
df:
X Y Z
0 0.1 0.5 NaN
1 0.2 -0.2 -0.21
2 0.3 NaN -5.00
3 0.4 -1.0 10.00
After .apply:
X Y Z
0 1.0 2.0 NaN
1 3.0 2.0 1.0
2 2.0 NaN 1.0
3 2.0 1.0 3.0
# Step 2 with new examplatory data and only one column
df = pd.DataFrame(data={'A': [1,2,3,np.NaN,3,1,3,4,3,np.NaN,2,2,1,2]})
threshold = 3
df['A_rolling'] = df['A'].rolling(window=3, min_periods=3).apply(lambda x: x.mean() if all([val <= threshold for val in x]) else np.NaN)
A A_rolling
0 1.0 NaN
1 2.0 NaN
2 3.0 2.000000
3 NaN NaN
4 3.0 NaN
5 1.0 NaN
6 3.0 2.333333
7 4.0 NaN
8 3.0 NaN
9 NaN NaN
10 2.0 NaN
11 2.0 NaN
12 1.0 1.666667
13 2.0 1.666667
因此,只有总得来说它现在所有列:)
任何想法? 感谢
真的很好的解决方案。如果您在步骤2中删除最后一个'D'列,会很好。 – Dark
@Bharath谢蒂:不需要,因为这只是试验;我想避免在上面的数据框中显示线条:)我会稍后看看你的例子,但现在看起来非常好,非常清晰,比我更优雅:) – tim
很好,谢谢那真棒解决方案! – tim