панды: групповые и переменные веса

У меня есть набор данных с весами для каждого наблюдения, и я хочу подготовить взвешенные сводки, используя groupby, но не знаю, как лучше всего это сделать. Я думаю, это подразумевает пользовательскую функцию агрегации. Моя проблема заключается в том, как правильно обращаться с данными не по элементам, а по группам. Возможно, это означает, что лучше делать это поэтапно, а не за один раз.

В псевдокоде я ищу

#first, calculate weighted value
for each row:
  weighted jobs = weight * jobs
#then, for each city, sum these weights and divide by the count (sum of weights)
for each city:
  sum(weighted jobs)/sum(weight)

Я не уверен, как использовать часть «для каждого города» в настраиваемой агрегатной функции и получить доступ к сводкам на уровне группы.

Макетные данные:

import pandas as pd
import numpy as np
np.random.seed(43)

## prep mock data
N = 100
industry = ['utilities','sales','real estate','finance']
city = ['sf','san mateo','oakland']
weight = np.random.randint(low=5,high=40,size=N)
jobs = np.random.randint(low=1,high=20,size=N)
ind = np.random.choice(industry, N)
cty = np.random.choice(city, N)
df_city =pd.DataFrame({'industry':ind,'city':cty,'weight':weight,'jobs':jobs})

person ako    schedule 22.01.2014    source источник


Ответы (1)


Просто умножьте два столбца:

In [11]: df_city['weighted_jobs'] = df_city['weight'] * df_city['jobs']

Теперь можно сгруппировать по городам (и взять сумму):

In [12]: df_city_sums = df_city.groupby('city').sum()

In [13]: df_city_sums
Out[13]: 
           jobs  weight  weighted_jobs
city                                  
oakland     362     690           7958
san mateo   367    1017           9026
sf          253     638           6209

[3 rows x 3 columns]

Теперь вы можете разделить две суммы, чтобы получить желаемый результат:

In [14]: df_city_sums['weighted_jobs'] / df_city_sums['jobs']
Out[14]: 
city
oakland      21.983425
san mateo    24.594005
sf           24.541502
dtype: float64
person Andy Hayden    schedule 22.01.2014
comment
определенно работает - отлично! Я буду выполнять взвешивание для многих переменных и хотел бы объединить их в группу по функциям, которые я мог бы вызывать на лету; варьировать уровни группировки и т. д. В любом случае это можно сделать за один шаг (т.е. в вызове groupby, передать пользовательскую функцию с уровнем группировки, переменную для взвешивания в качестве аргументов?) - person ako; 23.01.2014
comment
Например. вы можете использовать groupby apply с def f(x): return (1. * x['weight'] * x['jobs']).sum() / x['jobs'].sum(), но это, вероятно, будет менее эффективно, чем приведенное выше. - person Andy Hayden; 23.01.2014