#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. Это намного лучше!