сложение данных в колонке и агрегация

пытаюсь сгруппировать данные в колонке price, что бы разница была не 0.01 а 0.02 и сгруппированные price положить в кортеж, также в колонке vol суммировать данные по сгруппированным price.Думал реализовать через кумулятивную сумму остатков price поделив их нацело // 0.02, и потом сгруппировать, но разница в price в результате плавает от 0.01 до 0.03.Так же я подумал что проблема в числах флоат,и домножал price на 100 и делил на // 2 что бы получить int в исходных данных, но этот тоже не дало результата Мой код:

price = [str(i / 100) for i in range(20)]
vol = [random.randint(100, 300) for i in range(20)]
price.reverse()
data = ({'vol': vol, 'price': price})
df = (pd.DataFrame(data).astype({'price': 'float'})
      .eval('diffs=price.diff().fillna(0).abs().cumsum().round(2)// 0.02')
      .groupby('diffs')
      .agg(vol=('vol', 'sum'), price=('price', 'min'), tags=('price', tuple)))
print(df)

результат должен быть такой:

vol  price                tags
                              
295   0.18        (0.19, 0.18)
455   0.16        (0.17, 0.16)
655   0.14        (0.15, 0.14)
284   0.12         (0.13,0.12)
549   0.10        (0.11, 0.10)
770   0.08        (0.09, 0.08)
199   0.06         (0.70,0.06)
552   0.04        (0.05, 0.04)
708   0.02        (0.03, 0.02)
171   0.00         (0.10, 0.00)

p.s в vol сумма должна быть тех цен которые в tags, количество знаков после запятой должно везде быть 2 даже если число к примеру 0.70.И в колонке price шаг цен должен оставаться всегда 0.02 не зависимо от четности количества строк


Ответы (1 шт):

Автор решения: Алексей Р
import random

price = reversed([i / 100 for i in range(20)])
vol = [random.randint(100, 300) for i in range(20)]

df = pd.DataFrame({'vol': vol, 'price': price})
df['price00'] = df.price.map("{0:.2f}".format)
df = df.groupby(df.price.mul(100).mod(2).astype(int).cumsum()).agg(vol=('vol', 'sum'), price=('price', 'min'), tags=('price00', tuple))
print(df)
       vol  price          tags
price                          
1      552   0.18  (0.19, 0.18)
2      364   0.16  (0.17, 0.16)
3      434   0.14  (0.15, 0.14)
4      472   0.12  (0.13, 0.12)
5      377   0.10  (0.11, 0.10)
6      333   0.08  (0.09, 0.08)
7      314   0.06  (0.07, 0.06)
8      405   0.04  (0.05, 0.04)
9      430   0.02  (0.03, 0.02)
10     367   0.00  (0.01, 0.00)

Если преобразования производить в целых и только в конце поделить на 100 и отформатировать

import random

price = reversed([i for i in range(50)])
vol = [random.randint(100, 300) for i in range(50)]

df = pd.DataFrame({'vol': vol, 'price': price})
df['price00'] = df.price.div(100).map("{0:.2f}".format)
df = df.groupby(df.price.mod(2).astype(int).cumsum()).agg(vol=('vol', 'sum'), price=('price', 'min'), tags=('price00', tuple))
df['price'] = df.price.div(100).map("{0:.2f}".format)
print(df)
→ Ссылка