有没有一种方法可以向量化 pandas 的 DataFrame 行操作,以仅使用前一行数据进行计算,而不使用 python 级别的迭代?
我正在尝试计算每行上给定分布的分位数,但我想避免数据泄漏。
因此,对于每一行,我想计算
sequence[:current_row]
的分位数。
import pandas as pd
import numpy as np
test_df = pd.DataFrame({'column_1':np.random.random(10)})
qtls = pd.DataFrame({'q1':[],
'q2':[],
'q3':[],
'q4':[],
'q5':[],
'q6':[],
'q7':[],
'q8':[],
'q9':[]})
for i in range(1,len(test_df)+1):
qtls = pd.concat([qtls, pd.DataFrame({k:[v] for k,v in zip(['q'+str(j) for j in range(1, 10)], np.quantile(test_df['column_1'].iloc[:i], np.arange(0.1,1.0,0.1)))})])
qtls = qtls.reset_index(drop=True)
test_df = pd.concat([test_df, qtls], axis=1)
test_df
这就是 for 循环的暴力实现。
这是预期的结果:
索引 | 第_1栏 | q1 | q2 | q3 | q4 | q5 | q6 | q7 | q8 | q9 |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.913871 | 0.913871 | 0.913871 | 0.913871 | 0.913871 | 0.913871 | 0.913871 | 0.913871 | 0.913871 | 0.913871 |
1 | 0.374344 | 0.428297 | 0.482249 | 0.536202 | 0.590155 | 0.644107 | 0.698060 | 0.752013 | 0.805966 | 0.859918 |
2 | 0.886332 | 0.476741 | 0.579139 | 0.681536 | 0.783934 | 0.886332 | 0.891840 | 0.897347 | 0.902855 | 0.908363 |
3 | 0.499623 | 0.411928 | 0.449511 | 0.487095 | 0.576965 | 0.692977 | 0.808990 | 0.889086 | 0.897347 | 0.905609 |
4 | 0.516991 | 0.424455 | 0.474567 | 0.503097 | 0.510044 | 0.516991 | 0.664727 | 0.812463 | 0.891840 | 0.902855 |
5 | 0.788121 | 0.436983 | 0.499623 | 0.508307 | 0.516991 | 0.652556 | 0.788121 | 0.837226 | 0.886332 | 0.900101 |
6 | 0.180458 | 0.296789 | 0.399400 | 0.474567 | 0.506570 | 0.516991 | 0.679669 | 0.807763 | 0.866689 | 0.897347 |
7 | 0.726476 | 0.316178 | 0.424455 | 0.501360 | 0.513517 | 0.621734 | 0.738805 | 0.781956 | 0.847047 | 0.894593 |
8 | 0.142783 | 0.172923 | 0.296789 | 0.424455 | 0.503097 | 0.516991 | 0.684579 | 0.763463 | 0.827405 | 0.891840 |
9 | 0.844354 | 0.176690 | 0.335567 | 0.462039 | 0.510044 | 0.621734 | 0.751134 | 0.804991 | 0.852750 | 0.889086 |
怎样才能高效地做到这一点?
如果有一个
df['some_column'] = df['another_column'].cumquantile()
不是很容易吗?
我认为你不能真正对其进行矢量化,但你可以将你的代码简化为:
np.random.seed(0)
test_df = pd.DataFrame({'column_1':np.random.random(10)})
q = test_df['column_1'].expanding().quantile
out = test_df.join(pd.DataFrame({f'q{i}': q(x) for i, x in
enumerate(np.arange(0.1,1.0,0.1), start=1)}))
但是应该会更快,因为它不再循环运行
concat
。
输出:
column_1 q1 q2 q3 q4 q5 q6 q7 q8 q9
0 0.548814 0.548814 0.548814 0.548814 0.548814 0.548814 0.548814 0.548814 0.548814 0.548814
1 0.715189 0.565451 0.582089 0.598726 0.615364 0.632001 0.648639 0.665277 0.681914 0.698552
2 0.602763 0.559603 0.570393 0.581183 0.591973 0.602763 0.625249 0.647734 0.670219 0.692704
3 0.544883 0.546062 0.547241 0.548420 0.559603 0.575788 0.591973 0.614006 0.647734 0.681462
4 0.423655 0.472146 0.520638 0.545669 0.547241 0.548814 0.570393 0.591973 0.625249 0.670219
5 0.645894 0.484269 0.544883 0.546848 0.548814 0.575788 0.602763 0.624329 0.645894 0.680542
6 0.437587 0.432014 0.459046 0.523424 0.546455 0.548814 0.581183 0.611390 0.637268 0.673612
7 0.891773 0.433407 0.480506 0.545276 0.548027 0.575788 0.611390 0.641581 0.687471 0.768164
8 0.963663 0.434801 0.501965 0.546455 0.559603 0.602763 0.637268 0.687471 0.785823 0.906151
9 0.383442 0.419633 0.434801 0.512694 0.547241 0.575788 0.620016 0.666683 0.750506 0.898962