Подсчитайте значение столбца, если оно больше 0 в результате groupby

#python #pandas #pandas-groupby

#python #pandas #pandas-groupby

Вопрос:

У меня есть массив groupby, в котором мне нужно сгруппировать по A, затем показать количество экземпляров B, разделенных B1 и B2, и, наконец, процент тех экземпляров, которые > 0,1, поэтому я сделал это, чтобы получить первые 2:

     A   B       C   
id                                      
118 a1  B1      0
119 a1  B1      0
120 a1  B1      101.1   
121 a1  B1      106.67  
122 a1  B2      103.33  
237 a1  B2      100 

df = pd.DataFrame(df.groupby(
    ['A', 'B'])['B'].aggregate('count')).unstack(level=1)
  

к которому я правильно понял первую часть:

                    B
B                  B1   B2
A
a1                  4   2
a2                  7   9
a3                  9   17
a4                  8   8
a5                  7   8
  

Но затем, когда мне нужно получить процент от количества, которое равно > 0

 prcnt_complete = df[['A', 'B', 'C']]
prcnt_complete['passed'] = prcnt_complete['C'].apply(lambda x: (float(x) > 1))
prcnt_complete = prcnt_complete.groupby(['A', 'B', 'passed']).count()
  

Я получаю странные значения, которые не имеют смысла, иногда сумма между True и False даже не складывается. Я пытаюсь понять, что в порядке вещей я делаю неправильно, чтобы я мог понять это.

Результат, который я ищу, выглядит примерно так:

                    B         passed
B                  B1   B2   B1   B2
A
a1                  4   2    2    2
a2                  7   9    7    6
a3                  9   17   9    5
  

Спасибо,

Ответ №1:

Вы можете сделать:

 (df['C'].gt(1).groupby([df['A'],df['B']])
    .agg(['size','sum'])
    .rename(columns={'size':'B','sum':'passed'})
    .unstack('B')
)
  

Вывод (из образца данных):

        B    passed   
B  B1 B2     B1 B2
A                 
a1  4  2      2  2
  

Ответ №2:

Работая над вашей проблемой, я также хотел посмотреть, смогу ли я получить средний процент для B (игнорируя 0s). Я также смог выполнить это при получении подсчетов.

Фрейм данных для этого упражнения:

      A   B       C
0   a1  B1    0.00
1   a1  B1    0.00
2   a1  B1   98.87
3   a1  B1  101.10
4   a1  B2  106.67
5   a1  B2  103.00
6   a2  B1    0.00
7   a2  B1    0.00
8   a2  B1   33.00
9   a2  B1  100.00
10  a2  B2   80.00
11  a3  B1   90.00
12  a3  B2   99.00
  

Усредняет, исключая нули

для этого мне пришлось добавить .replace(0, np.nan) перед функцией groupby.

 A = ['a1','a1','a1','a1','a1','a1','a2','a2','a2','a2','a2','a3','a3']
B = ['B1','B1','B1','B1','B2','B2','B1','B1','B1','B1','B2','B1','B2']
C = [0,0,98.87,101.1,106.67,103,0,0,33,100,80,90,99]
import pandas as pd
import numpy as np
df = pd.DataFrame({'A':A,'B':B,'C':C})

df = pd.DataFrame(df.replace(0, np.nan)
                    .groupby(['A', 'B'])
                    .agg({'B':'size','C':['count','mean']})
                    .rename(columns={'size':'Count','count':'Passed','mean':'Avg Score'})).unstack(level=1)
df.columns = df.columns.droplevel(0)

   Count    Passed    Avg Score         
B     B1 B2     B1 B2        B1       B2
A                                       
a1     4  2      2  2    99.985  104.835
a2     4  1      2  1    66.500   80.000
a3     1  1      1  1    90.000   99.000