在查询pandas DataFrame之后,我想在查询中获取所选索引之前的3个条目。
下面的代码有效,但我觉得它很脏而且效率不高,我只能想象有一种更好的方法可以用Pandas来做。
有人可以帮助我吗?
import pandas as pd
import numpy as np
dates = pd.date_range('1/1/2015', periods=50)
df = pd.DataFrame(np.random.randn(50, 4), index=dates, columns=['A', 'B', 'C', 'D'])
x = (df['B'] > df['A']) & \
((df['B'].shift(+1) > df['A'].shift(+1)) == False) & \
(df['B'].shift(+2) > df['A'].shift(+2)) & \
(df['C'] < df['C'].shift(+2)) & \
(df['D'] < df['D'].shift(+1))
for d in df[x].index.values:
idx = df.index.get_loc(d)
print df.iloc[idx - 3:idx]
以上代码的示例输出:
A B C D
2015-01-02 -0.600371 -1.088227 -1.213046 -0.000058
2015-01-03 -2.373683 -0.455126 -0.852127 0.311744
2015-01-04 0.240301 -1.957885 0.184642 0.690865
A B C D
2015-01-05 -0.833244 -0.787022 -1.490983 -0.540114
2015-01-06 0.569680 1.798457 1.253075 0.835848
2015-01-07 -0.245731 -0.365678 1.452985 2.007146
Process finished with exit code 0
我的另一个问题是,如果可以在查询中使用“Pandas Language”的“shift”,而不是使用Python。
感谢您的帮助!
答案 0 :(得分:0)
AFAIK,query()方法不接受可应用于列的函数和方法 - 至少我无法使其正常工作
您可以使用eval()方法 - 它看起来会更好一点:
In [168]: %paste
mask = (df.eval('B > A')
& df.shift(1).eval('B <= A')
& df.shift(2).eval('B > A')
& (df.C < df.C.shift(2))
& (df.D < df.D.shift(1)))
df.ix[np.concatenate([np.arange(i-2, i+1) for i in mask.reset_index(name='bool').query('bool').index])]
## -- End pasted text --
Out[168]:
A B C D
2015-01-03 0.027326 1.896523 1.052508 0.279496
2015-01-04 -0.226720 -1.465787 2.459746 0.089118
2015-01-05 0.323047 1.707117 -1.760567 -0.066462
2015-01-31 -1.059314 1.991725 0.819225 -1.212651
2015-02-01 1.372391 0.247049 0.408600 0.908394
2015-02-02 -0.777752 -0.326590 -0.062228 -0.226803
2015-02-16 -0.192333 0.562463 0.126509 -0.342867
2015-02-17 -0.363513 -1.582659 -0.903556 0.973706
2015-02-18 -0.796225 -0.575127 0.078172 -2.182067
说明:
In [162]: mask.reset_index(name='bool').query('bool')
Out[162]:
index bool
4 2015-01-05 True
32 2015-02-02 True
48 2015-02-18 True
In [163]: mask.reset_index(name='bool').query('bool').index
Out[163]: Int64Index([4, 32, 48], dtype='int64')
In [164]: [np.arange(i-2, i+1) for i in mask.reset_index(name='bool').query('bool').index]
Out[164]:
[array([2, 3, 4], dtype=int64),
array([30, 31, 32], dtype=int64),
array([46, 47, 48], dtype=int64)]
In [165]: np.concatenate([np.arange(i-2, i+1) for i in mask.reset_index(name='bool').query('bool').index])
Out[165]: array([ 2, 3, 4, 30, 31, 32, 46, 47, 48], dtype=int64)