панды сгруппировали средневзвешенное значение с весами из записей и значениями из имен столбцов

Я хочу вычислить сгруппированное средневзвешенное значение, где веса представлены в виде строк, а значение для усреднения представлено в виде имени столбца:

df_dict= {1: {0: 10, 1: 15, 2: 50, 3: 10, 4: 44},
 4: {0: 12, 1: 15, 2: 48, 3: 12, 4: 63},
 7.5: {0: 17, 1: 23, 2: 99, 3: 20, 4: 66},
 90: {0: 25, 1: 18, 2: 102, 3: 17, 4: 10},
 'grouping': {0: '38', 1: '38', 2: '38', 3: '86', 4: '48'}}

df = pd.DataFrame(df_dict)
display(df)

df.groupby(['grouping']).sum().reset_index()

дает: введите здесь описание изображения

Но я не уверен, как эффективно вычислить средневзвешенное значение. Вариантом может быть использование numpy средневзвешенного значения с использованием numpy.average. Но это означало бы, что df.apply пользовательская функция плохо оптимизирована.

Есть ли способ лучше?

редактировать

т.е. есть ли лучший способ загара, используя:

df = df.groupby(['grouping']).sum().reset_index()
display(df)

def wavg(x):
    values = x.drop('grouping')
    values = values.reset_index()
    values.columns = ['value', 'weight']
    return np.average(list(values.value),
                      weights=list(values.weight))
df['wavg_location'] = df.apply(wavg, axis=1)

person Georg Heiler    schedule 27.08.2019    source источник


Ответы (1)


reset_index() здесь не требуется.

df_raw = df.groupby(['grouping']).sum()

И мы можем сделать взвешенную сумму, не вызывая np.average()

df = df_raw.copy()
df['wavg_location'] = (df * df.columns).sum(axis=1) / df.sum(axis=1)

Я рассчитал два разных подхода в блокноте Jupyter:

for i in range(100):
    df = df_raw.reset_index()
    df['wavg_location'] = df.apply(wavg, axis=1)

выполняется за 712 мс

for i in range(100):
    df = df_raw.copy()
    df['wavg_location'] = (df * df.columns).sum(axis=1) / df.sum(axis=1)

выполняется за 293 мс

person Hongpei    schedule 27.08.2019