#python #pandas
#python #pandas
Вопрос:
Поэтому я стараюсь избегать использования цикла при вычислении среднего значения взвешенных оценок в каждом из этих курсов.
Я просто не могу понять, что делать. Я предполагаю, что могу использовать groupby и выполнить соответствующие вычисления?
Это фрейм данных:
data =
mark weight course_id
78 10 1
87 40 1
15 50 1
78 90 3
40 10 3
Это желаемый результат:
result=
course_id course_average
1 50.1
3 74.2
Ответ №1:
Если числа не всегда складываются до 100 для каждой группы, то вы можете рассчитать пропорцию weight
для каждой строки каждой группы и умножить на mark
.
(data.assign(wa = data['mark'] * data['weight'] /
data.groupby('course_id')['weight'].transform('sum'))
.groupby('course_id')['wa'].sum())
Out[1]:
course_id
1 50.1
3 74.2
Name: wa, dtype: float64
Если веса составляют до 100 для каждой группы, тогда вычисление упрощается:
data.assign(wa = data['mark'] * data['weight'] / 100).groupby('course_id')['wa'].sum()
Out[2]:
course_id
1 50.1
3 74.2
Name: wa, dtype: float64
Комментарии:
1. Да, я забыл упомянуть, что данные гарантированно складываются до 100.
Ответ №2:
Это один из способов сделать это :
(df.assign(course_average=df.mark * df.weight)
.groupby("course_id")
.pipe(lambda x: x.course_average.sum().div(x.weight.sum()))
.reset_index(name="course_average"))
course_id course_average
0 1 50.1
1 3 74.2
Ответ №3:
Вы можете сделать это с помощью простой строки 1, используя groupby
и lambda
для средневзвешенного значения следующим образом —
df.groupby(['course_id']).apply(lambda x: sum(x['mark']*x['weight'])/sum(x['weight']))
course_id
1 50.1
3 74.2
dtype: float64
Комментарии:
1. Было бы более эффективно избегать apply и использовать assign, как это делал Дэвид Эриксон? Я думаю, что оба решения здесь в любом случае создадут новый фрейм данных в памяти.