Панды — Найти среднее значение на основе значения нескольких столбцов

#python #pandas

#питон #панды

Вопрос:

Цель состоит в том, чтобы получить среднее значение(целое число) marks столбца на основе name значения. Если id name столбец и отображается с одним и тем же значением более одного раза, то marks соответствующий name с будет рассмотрен один раз. Для, например, среднего значения x = (33 14 3)/3 = 16

Образец кадра данных:

 id name marks 0 1 x 33 1 1 x 33 2 2 y 9 3 3 x 14 4 4 y 55 5 4 y 55 6 5 x 3 7 6 z 31  

Ожидаемый результат:

 id name marks avg 0 1 x 33 16 1 1 x 33 16 2 2 y 9 32 3 3 x 14 16 4 4 y 55 32 5 4 y 55 32 6 5 x 3 16 7 6 z 31 31  

Я пытался:

 df["avg"] = df.groupby("name")["marks"].mean()  

Ответ №1:

Попробуйте это:

 df = df.set_index('name').assign(avg=df.drop_duplicates(['name', 'marks']).groupby('name')['marks'].mean()).reset_index()  

Выход:

 gt;gt;gt; df  name id marks avg 0 x 1 33 16.666667 1 x 1 33 16.666667 2 y 2 9 32.000000 3 x 3 14 16.666667 4 y 4 55 32.000000 5 y 4 55 32.000000 6 x 5 3 16.666667 7 z 6 31 31.000000  

Если вам нужно, чтобы он округлился, цепочка .astype(int) к .mean() :

 df = df.set_index('name').assign(avg=df.drop_duplicates(['name', 'marks']).groupby('name')['marks'].mean().astype(int)).reset_index()  

Выход:

 gt;gt;gt; df  name id marks avg 0 x 1 33 16 1 x 1 33 16 2 y 2 9 32 3 x 3 14 16 4 y 4 55 32 5 y 4 55 32 6 x 5 3 16 7 z 6 31 31  

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

1. Хороший ответ. Кроме того, это можно упростить df[~df.set_index(['name', 'marks']).index.duplicated()] df.drop_duplicates(['name', 'marks']) , и все равно получается тот же результат.

2. Спасибо @Nick. Это упрощение аккуратно реализовано! 🙂

3. В следующий раз, если тебе придется воспользоваться set_index этим reset_index , не забудь map . Проверьте мой ответ. 1

4. Хорошо @Corralien, это отличный совет. Я запомню! 🙂

Ответ №2:

Вычислите среднее значение для каждого name после удаления дубликатов (id, name) и сопоставьте значение результата по name столбцу:

 df['avg'] = df['name'].map(df.drop_duplicates(['id', 'name']).groupby('name')['marks'].mean()) print(df)  # Output:  id name marks avg 0 1 x 33 16.666667 1 1 x 33 16.666667 2 2 y 9 32.000000 3 3 x 14 16.666667 4 4 y 55 32.000000 5 4 y 55 32.000000 6 5 x 3 16.666667 7 6 z 31 31.000000  

Ответ №3:

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

 df.assign(avg = df.name.map(df.drop_duplicates().pivot('name', 'id', 'marks').mean(1)))    id name marks avg 0 1 x 33 16.666667 1 1 x 33 16.666667 2 2 y 9 32.000000 3 3 x 14 16.666667 4 4 y 55 32.000000 5 4 y 55 32.000000 6 5 x 3 16.666667 7 6 z 31 31.000000