#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
. Проверьте мой ответ. 14. Хорошо @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