Python 按Where条件连续分组
我试图在某些条件匹配的情况下“组合”连续的相似数据行,我所做的一切都是抛出错误或以意外的方式将数据组合在一起 数据: 我想将Python 按Where条件连续分组,python,pandas,quantitative-finance,Python,Pandas,Quantitative Finance,我试图在某些条件匹配的情况下“组合”连续的相似数据行,我所做的一切都是抛出错误或以意外的方式将数据组合在一起 数据: 我想将open>close和close>open的连续行组合在一起,这样我就可以拥有一个大蜡烛(这是股票数据),用于连续的相同蜡烛 最初,我开始制作一个列来表示它是哪种类型的行(可能不需要,并且在行合并期间可以在一行中进行比较?) 产生: open close high low volume candl
open>close
和close>open
的连续行组合在一起,这样我就可以拥有一个大蜡烛(这是股票数据),用于连续的相同蜡烛
最初,我开始制作一个列来表示它是哪种类型的行(可能不需要,并且在行合并期间可以在一行中进行比较?)
产生:
open close high low volume
candle_is candle_is
G 1 260.41 257.86 266.0500 255.63 1047075436
R 2 266.31 265.51 266.8000 262.71 401716112
G 3 265.58 266.51 267.5600 265.39 516455674
R 4 268.10 266.86 268.6000 266.64 632660142
G 5 280.17 273.42 286.6285 267.40 1655227273
... ... ... ... ... ...
73 342.12 326.52 350.7200 319.64 1280999271
R 74 350.35 330.65 358.7500 327.97 1257122392
G 75 336.06 328.73 347.3500 319.80 1099865805
R 76 349.59 326.54 354.0200 322.60 1153665809
G 77 330.20 350.16 352.1900 327.24 463334913
但是我需要将红色(R)和绿色(G)蜡烛之间的逻辑分开,这样agg()的工作方式就有点不同,因为对于每种类型,打开/关闭值应该在最小/最大值之间交换:
# green
df.groupby(['candle_is', g], sort=False).agg({'open': max, 'close': min, 'high': max, 'low': min, 'volume': sum})
# red
df.groupby(['candle_is', g], sort=False).agg({'open': min, 'close': max, 'high': max, 'low': min, 'volume': sum})
但是,我找不到一种方法来利用
g
或df['candle_is']='g'
专门针对这些目标,而不会产生大量错误,因为一旦我过滤了数据,大小就不匹配了。如何才能理智地做到这一点?谢谢 如果您想交换min/max
,可能更容易注意到max(-array)=-min(array)
。因此,我们可以将数据乘以-1
,然后再乘以:
# use this instead of `apply`, which is not vectorized
candles = np.select([df['open']>df['close'], df['open']<df['close']],
['R','G'], 'N')
# turn candles into series
candles =pd.Series(candles, index=df.index)
g = candles.ne(candles.shift()).cumsum()
# change sign of `red` candles so min becomes max and so on
multipliers = np.where(candles=='R', -1, 1)
# groupby as usual
# note that `'max'` is vectorize while `max` is not
ret = (df.mul(multipliers, axis='rows')
.groupby([candles, g], sort=False)
.agg({'open': 'max', 'close': 'min',
'high': 'max', 'low': 'min',
'volume': 'sum'})
)
# multiply the red candles by `-1`
# Since we are working with MultiIndex, we slice by the level values
ret.loc[ret.index.get_level_values(0)=='R'] *= -1
首先,哇,我真不敢相信你这么快就想到了什么。我已经尝试了两天不同的东西(但我对python和熊猫都是新手),所以谢谢你们!使用此解决方案,我从python 3.9.0中的
g=candicts.ne(candicts.shift()).cumsum()
行中得到一个错误“AttributeError:'numpy.ndarray'对象没有属性“ne”。这是什么版本的?啊,对不起。通过环绕pd.series(np.select(…),index=df.index)
将其转换为系列。请参阅更新的答案谢谢!现在我必须阅读你在这里所做的一切来了解发生了什么以及你是如何做到的!非常感谢你!事实上,对于任何发现这一点的人来说,由于红烛乘以-1,它是稍微偏离的,因为红烛的最终高值和低值是不正确的,因为它现在选择了连续组中的“最高低值”。因此,现在我们似乎处于类似的情况,我以前无法发现,我们需要选择哪一行(匹配“R”)要将高位和低位列重新乘以-1(或者不首先这样做),以获得正确的数据
open close high low volume
candle_is candle_is
G 1 260.41 257.86 266.0500 255.63 1047075436
R 2 266.31 265.51 266.8000 262.71 401716112
G 3 265.58 266.51 267.5600 265.39 516455674
R 4 268.10 266.86 268.6000 266.64 632660142
G 5 280.17 273.42 286.6285 267.40 1655227273
... ... ... ... ... ...
73 342.12 326.52 350.7200 319.64 1280999271
R 74 350.35 330.65 358.7500 327.97 1257122392
G 75 336.06 328.73 347.3500 319.80 1099865805
R 76 349.59 326.54 354.0200 322.60 1153665809
G 77 330.20 350.16 352.1900 327.24 463334913
# green
df.groupby(['candle_is', g], sort=False).agg({'open': max, 'close': min, 'high': max, 'low': min, 'volume': sum})
# red
df.groupby(['candle_is', g], sort=False).agg({'open': min, 'close': max, 'high': max, 'low': min, 'volume': sum})
# use this instead of `apply`, which is not vectorized
candles = np.select([df['open']>df['close'], df['open']<df['close']],
['R','G'], 'N')
# turn candles into series
candles =pd.Series(candles, index=df.index)
g = candles.ne(candles.shift()).cumsum()
# change sign of `red` candles so min becomes max and so on
multipliers = np.where(candles=='R', -1, 1)
# groupby as usual
# note that `'max'` is vectorize while `max` is not
ret = (df.mul(multipliers, axis='rows')
.groupby([candles, g], sort=False)
.agg({'open': 'max', 'close': 'min',
'high': 'max', 'low': 'min',
'volume': 'sum'})
)
# multiply the red candles by `-1`
# Since we are working with MultiIndex, we slice by the level values
ret.loc[ret.index.get_level_values(0)=='R'] *= -1
open close high low volume
candle_is
G 1 260.41 257.86 266.05 255.63 1047075436
R 2 266.31 265.51 266.80 262.71 401716112
G 3 336.06 266.51 347.35 265.39 814068344
R 4 342.13 347.29 342.98 343.13 1153665809
G 5 330.20 350.16 352.19 327.24 463334913