Группировка: Получение «Количества» и «Процента» В Одной таблице

#python #pandas #dataframe #group-by

Вопрос:

Я работаю над tips набором данных:

 # Load the data
tips = sns.load_dataset("tips")
tips.head()

total_bill  tip     sex  smoker day  time  size
0   16.99   1.01    Female  No  Sun Dinner  2
1   10.34   1.66    Male    No  Sun Dinner  3
2   21.01   3.50    Male    No  Sun Dinner  3
3   23.68   3.31    Male    No  Sun Dinner  2
4   24.59   3.61    Female  No  Sun Dinner  4
 

Я хочу groupby перейти к time столбцам smoker и, а затем подсчитать количество курильщиков в каждой группе (включая их процент). Я пытаюсь достичь этого в 2 этапа:

Шаг 1:

 # Count by groups
tips.groupby(['time', 'smoker']).agg({'smoker': 'count'})
               smoker
time    smoker  
Lunch    Yes    23
         No     45
Dinner   Yes    70
         No    106

 

Шаг 2:

 # Count with percentage
tips.groupby(['time', 'smoker']).agg({'smoker': 'count'}).transform(lambda x: x/x.sum()*100)
                 smoker
time    smoker  
Lunch    Yes    9.426230
          No    18.442623
Dinner   Yes    28.688525
          No    43.442623
 

Я получаю результаты в 2 отдельных таблицах. Я хочу получить то count же percentage самое, что и в той же таблице.

Желаемый результат:

                count   percentage
time    smoker  
Lunch    Yes    23     9.426230
         No     45     18.442623
Dinner   Yes    70     28.688525
         No    106     43.442623
 

Есть ли какой-нибудь лучший способ сделать это? Любые предложения будут оценены по достоинству. Спасибо!

Комментарии:

1. Можете ли вы расширить свой образец df , чтобы мы могли сопоставить ваши результаты? В приведенном вами примере в столбце «время» нет слова «Обед». В противном случае измените свой вывод в соответствии с вашим примером.

2. @not_speshal, «Обед» и «Ужин» — это классы для time колонки.

3. Попался! Я заново создал фиктивный набор данных и смог сопоставить ваши требуемые выходные данные

Ответ №1:

Вы можете выполнить несколько агрегаций для одного и того же столбца, используя именованную агрегацию:

 output = df.groupby(['time', 'smoker'])["smoker"].agg(Count="count", Percentage=lambda x: x.count()/df.shape[0]*100)

>>>                Count  Percentage
time   smoker                   
Dinner No        106   43.442623
       Yes        70   28.688525
Lunch  No         45   18.442623
       Yes        23    9.426230
 
Вход df:
 import random
df = pd.DataFrame({"time": ["Lunch"]*68 ["Dinner"]*176,
                   "smoker": ["Yes"]*23 ["No"]*45 ["Yes"]*70 ["No"]*106,
                   "sex": random.choices(["Male","Female"],k=100)})
 

Комментарии:

1. Потрясающе @not_speshal. Это прекрасно. Вы можете напрямую загрузить данные из seaborn . Спасибо!

2. Рад помочь @Roy ! ^_^

Ответ №2:

Вы можете использовать transform его для вычисления процента в другой инструкции и сохранения результата в другом столбце.

 tips_grouped = tips.groupby(['time', 'smoker']).agg({'smoker': 'count'}).to_frame()
tips_grouped["percentage"] = tips_grouped["count"].transform(lambda x: x/x.sum()*100)
 

Комментарии:

1. Большое вам спасибо @sergio-penafiel. Это намного лучше!