#python #pandas #dataframe #group-by #pandas-groupby
Вопрос:
Итак, у меня есть фрейм данных, подобный приведенному ниже.
dff = pd.DataFrame({'id':[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3], 'categ':['A','A','A','B','C','A','A','A','B','C','A','A','A','B','C'],'cost':[3,1,1,3,10,1,2,3,4,10,2,2,2,4,13] })
dff
id categ cost
0 1 A 3
1 1 A 1
2 1 A 1
3 1 B 3
4 1 C 10
5 2 A 1
6 2 A 2
7 2 A 3
8 2 B 4
9 2 C 10
10 3 A 2
11 3 A 2
12 3 A 2
13 3 B 4
14 3 C 13
Теперь я хочу создать новый фрейм данных, сгруппированный по идентификатору, и создать новый столбец, в котором, если сумма категорий A = 50% и B = 30% от стоимости C, затем вернет True, в противном случае false. Мой желаемый результат приведен ниже.
new
id
1 True
2 False
3 False
Я пробовал кое-что, но не могу заставить это работать. Есть идеи о том, как получить желаемый результат? Спасибо
Комментарии:
1. Ибо
id = 1
B-это 33,3% от C , а не 30% ?2. да, верно, я только что изменил его.
Ответ №1:
Сначала попробуйте сводный фрейм данных, а затем проверьте , удовлетворяют ли столбцы A
, B
, C
условию:
import numpy as np
dff.pivot_table('cost', 'id', 'categ', aggfunc='sum')
.assign(new = lambda df: np.isclose(df.A, 0.5 * df.C) amp; np.isclose(df.B, 0.3 * df.C))
categ A B C new
id
1 5 3 10 True
2 6 4 10 False
3 6 4 13 False
Ответ №2:
Попробуйте pd.crosstab
с normalize
помощью , а затем примените немного математики. Обратите внимание : здесь мы не можем использовать equal из-за поплавка, нам нужно np.isclose
s = pd.crosstab(df['id'], df['categ'], df['cost'],aggfunc='sum',normalize = 'index')
s['new'] = np.isclose(s.values.tolist(),[0.5/1.8,0.3/1.8,1/1.8],atol=0.0001).all(1)
s
Out[341]:
categ A B C new
id
1 0.277778 0.166667 0.555556 True
2 0.300000 0.200000 0.500000 False
3 0.260870 0.173913 0.565217 False