我有一个这样的数据框:
index value idxmin idxmax
0 300 nan nan
1 200 nan nan
2 100 nan nan
3 200 0 2
4 300 1 2
5 400 1 3
6 500 2 5
7 600 4 5
8 700 4 7
9 800 5 8
10 900 5 8
11 800 7 9
12 700 8 10
13 600 10 12
14 500 12 13
15 400 12 14
16 500 12 15
17 400 13 15
18 500 13 16
19 600 15 17
20 700 15 19
我想创建一个新列(最大值),该列将返回行范围的“值”列的最大值。 示例:对于第9行,第5到8行的“值”最大值为800。
我编写了这段代码,该代码实际上正在运行,但是效率不高
df['maxvalue'] = df.apply(lambda x : (df['value'].loc[x['idxmin']:x['idxmax']].max(), axis=1)
您是否有更有效的代码来执行该功能?
我期望的结果(最后一栏):
index value idxmin idxmax maxvalue
0 300 nan nan nan
1 200 nan nan nan
2 100 nan nan nan
3 200 0 2 300
4 300 1 2 200
5 400 1 3 200
6 500 2 5 400
7 600 4 5 400
8 700 4 7 600
9 800 5 8 700
10 900 5 8 700
11 800 7 9 800
12 700 8 10 900
13 600 10 12 900
14 500 12 13 700
15 400 12 14 700
16 500 12 15 700
17 400 13 15 600
18 500 13 16 600
19 600 15 17 500
20 700 15 19 600
非常感谢您的帮助!
答案 0 :(得分:4)
此操作本质上难以向量化,因为未对数组进行排序,并且索引似乎无法表示大小相等的范围。我可以建议将其转变为列表理解,以规避apply
的开销,但是那之后您要靠自己了。
df['maxvalue'] = [
df['value'].values[int(s):int(e)].max() if pd.notna([s,e]).all()
else np.nan for s, e in zip(df['idxmin'], df['idxmax'])
]
df.head()
index value idxmin idxmax maxvalue
0 0 300 NaN NaN NaN
1 1 200 NaN NaN NaN
2 2 100 NaN NaN NaN
3 3 200 0.0 2.0 300.0
4 4 300 1.0 2.0 200.0
为了充分利用这一点,有必要将尽可能多的繁重工作从熊猫转移到numpy。在只有1000行的小型DataFrame上,我的计算机的速度提高了15倍。
df_ = df
df = pd.concat([df_] * 1000, ignore_index=True)
%timeit df.apply(
lambda x: df['value'].loc[x['idxmin']:x['idxmax']].max(), axis=1)
%%timeit
[
df['value'].values[int(s):int(e)].max() if pd.notna([s,e]).all()
else np.nan for s, e in zip(df['idxmin'], df['idxmax'])
]
4.79 s ± 68.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
268 ms ± 3.74 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)