#python #python-3.x #pandas
Вопрос:
У меня есть следующий фрейм данных:
df = pd.DataFrame({"marks": [40, 60, 90, 20, 100, 10, 30, 70 ], "students":
["Jack", "Jack", "Jack", "Jack", "John", "John", "John", "John"]}
)
marks students
0 40 Jack
1 60 Jack
2 90 Jack
3 20 Jack
4 100 John
5 10 John
6 30 John
7 70 John
Я пытаюсь присвоить среднюю оценку студента его отметкам ниже 40 (среднее значение будет включать самую низкую отметку).
Я знаю о назначении отметки на основе < 40
условия (в этом случае я присвоил самую низкую отметку df всем отметкам ниже 40), примерно так:
df.loc[df["marks"] < 40, "marks"] = df["marks"].min()
Но я не понимаю, как потенциально применить лямбда-функцию к уникальным student
именам. Любая помощь будет признательна.
Ответ №1:
Попробуйте с np.where
df['marks'] = np.where(df['marks'] <40,
df.groupby('students')['marks'].transform('mean'),
df['marks'])
df
Out[18]:
marks students
0 40.0 Jack
1 60.0 Jack
2 90.0 Jack
3 52.5 Jack
4 100.0 John
5 52.5 John
6 52.5 John
7 70.0 John
Комментарии:
1. разве это не более или менее то же самое, что и мой ответ? 😉
2. @mozway , если ты так думаешь, я могу удалить
3. Нет, для меня это не имеет значения, я просто немного подумал, не упустил ли я какой-нибудь хитрый трюк 😉
Ответ №2:
Вы можете объединить a groupby
и where
:
df['corrected_marks'] = df['marks'].where(df['marks']>=40,
(df.groupby('students')
['marks']
.transform('mean'))
)
выход:
marks students corrected_marks
0 40 Jack 40.0
1 60 Jack 60.0
2 90 Jack 90.0
3 20 Jack 52.5
4 100 John 100.0
5 10 John 52.5
6 30 John 52.5
7 70 John 70.0
Ответ №3:
@mozway ответ правильный. Вы могли бы сделать это за два шага:
df['mean'] = df.groupby('students')['marks'].transform('mean')
df['final_marks'] = df.apply(lambda x: x['mean'] if (x['marks'] < 40) else x['marks'], axis=1)
print(df)
выход:
marks students mean final_marks
0 40 Jack 52.5 40.0
1 60 Jack 52.5 60.0
2 90 Jack 52.5 90.0
3 20 Jack 52.5 52.5
4 100 John 52.5 100.0
5 10 John 52.5 52.5
6 30 John 52.5 52.5
7 70 John 52.5 70.0
Ответ №4:
Чтобы применить свою логику к уникальным student
именам, вы можете сгруппировать их по student
именам .groupby()
и получить среднее значение по каждому студенту (каждой группе) transform()
'mean'
. Затем вы можете присвоить средние значения marks
, используя тот же механизм в коде, который вы пробовали, как показано ниже:
df.loc[df["marks"] < 40, "marks"] = df.groupby('students')['marks'].transform('mean')
Результат:
print(df)
marks students
0 40.0 Jack
1 60.0 Jack
2 90.0 Jack
3 52.5 Jack
4 100.0 John
5 52.5 John
6 52.5 John
7 70.0 John
Если вы действительно хотите присвоить самую низкую отметку (вместо «средней» отметки) каждой student
из них всем отметкам ниже 40 для этого учащегося, вы можете использовать transform()
'min'
вместо этого:
df.loc[df["marks"] < 40, "marks"] = df.groupby('students')['marks'].transform('min')
Результат:
print(df)
marks students
0 40 Jack
1 60 Jack
2 90 Jack
3 20 Jack
4 100 John
5 10 John
6 10 John
7 70 John
Комментарии:
1. Спасибо вам за дополнительную информацию @SeaBean.