замените значения условием после группы по

#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