Pandas GroupBy与Where条件连续
Pandas GroupBy Consecutive with Where Condition
我试图在某些条件匹配的情况下“合并”连续的类似数据行,而我尝试的所有操作都是抛出错误或以意想不到的方式将数据放在一起。
数据:
open high low close volume datetime
0 257.31 259.04 255.63 257.86 335889185 1510552800000
1 258.14 260.48 257.86 260.36 190142219 1511157600000
2 260.41 266.05 260.00 264.46 521044032 1511762400000
3 266.31 266.80 262.71 265.51 401716112 1512367200000
4 265.58 267.56 265.39 266.51 516455674 1512972000000
.. ... ... ... ... ... ...
151 336.06 347.35 334.38 346.85 297612670 1601874000000
152 349.59 354.02 343.13 347.29 361462322 1602478800000
153 348.65 349.33 340.65 345.78 296595696 1603083600000
154 342.13 342.98 322.60 326.54 495607791 1603688400000
155 330.20 352.19 327.24 350.16 463334913 1604296800000
我想合并 open > close
和 close > open
的连续行,这样我就可以用一根大蜡烛(这是股票数据)来表示连续的相同蜡烛。
最初我开始制作一列来表示它是哪种类型的行(可能不需要并且可以在行合并期间在一行中进行比较?):
def green_or_red(self, row):
if row['open'] > row['close']:
val = 'R'
elif row['open'] < row['close']:
val = 'G'
else:
val = 'N'
return val
df['candle_is'] = df.apply(green_or_red, axis=1)
哪个分配正确,但是连续行的合并是我遇到问题的地方:
# merge the consecutive same types of candles
g = df['candle_is'].ne(df['candle_is'].shift()).cumsum()
dfn = df.groupby(['candle_is', g], sort=False).agg({'open': max, 'close': min, 'high': max, 'low': min, 'volume': sum})
产生:
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() 的工作方式有点不同,因为 open/close 值应该在 min/max 之间交换每种类型:
# 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
示例数据的输出(注意第 2 R
组中的值):
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
我试图在某些条件匹配的情况下“合并”连续的类似数据行,而我尝试的所有操作都是抛出错误或以意想不到的方式将数据放在一起。
数据:
open high low close volume datetime
0 257.31 259.04 255.63 257.86 335889185 1510552800000
1 258.14 260.48 257.86 260.36 190142219 1511157600000
2 260.41 266.05 260.00 264.46 521044032 1511762400000
3 266.31 266.80 262.71 265.51 401716112 1512367200000
4 265.58 267.56 265.39 266.51 516455674 1512972000000
.. ... ... ... ... ... ...
151 336.06 347.35 334.38 346.85 297612670 1601874000000
152 349.59 354.02 343.13 347.29 361462322 1602478800000
153 348.65 349.33 340.65 345.78 296595696 1603083600000
154 342.13 342.98 322.60 326.54 495607791 1603688400000
155 330.20 352.19 327.24 350.16 463334913 1604296800000
我想合并 open > close
和 close > open
的连续行,这样我就可以用一根大蜡烛(这是股票数据)来表示连续的相同蜡烛。
最初我开始制作一列来表示它是哪种类型的行(可能不需要并且可以在行合并期间在一行中进行比较?):
def green_or_red(self, row):
if row['open'] > row['close']:
val = 'R'
elif row['open'] < row['close']:
val = 'G'
else:
val = 'N'
return val
df['candle_is'] = df.apply(green_or_red, axis=1)
哪个分配正确,但是连续行的合并是我遇到问题的地方:
# merge the consecutive same types of candles
g = df['candle_is'].ne(df['candle_is'].shift()).cumsum()
dfn = df.groupby(['candle_is', g], sort=False).agg({'open': max, 'close': min, 'high': max, 'low': min, 'volume': sum})
产生:
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() 的工作方式有点不同,因为 open/close 值应该在 min/max 之间交换每种类型:
# 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
示例数据的输出(注意第 2 R
组中的值):
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