Я попытался расширить этот вопрос, чтобы обобщить его на случай, когда кто-то хочет перенести сумму весов в средневзвешенное значение, чтобы можно было добавить к результирующим данным кадры неопределенностей на средневзвешенных значениях, которые 1 / (sqrt(sum_of_weights))
Рассмотрим примерный кадр данных
import pandas as pd
import numpy as np
df5 = pd.DataFrame.from_dict({'Lab': ['Lab1','Lab1','Lab1','Lab2','Lab2','Lab2','Lab3','Lab3','Lab3'],
'test_type': ['a','a','b','b','c','c','a','a','a'],
'HVL' : [1.4,1.4,1.4,1.3,1.3,1.3,1.35,1.35,1.35],
'measurements': [2.1,2.0,2.5,1.7,1.7,1.9,2.8,2.8,2.7],
'unc': [0.4,0.4,0.1,0.2,0.3,0.3,0.15,0.15,0.15]},
)
, суммирующий измерения нескольких Labs
по трем различным test_types
, на которых Lab
' Методы измерения имеют различную точность, отраженную в различных значениях в их заявленных неопределенностях unc
. Давайте рассмотрим следующую функцию для вычисления взвешенного среднего и переноса весов для оценки неопределенностей:
def wgt_average(x):
'''
wgt_average: calculates the weighted average on a particular column
of a groupby object. To be applied to the groupby object via .apply(wgt_average)
Parameters
----------
x : the groupby object
Returns
-------
dataframe
averages: the weighted averages
unc : their uncertainties obtained from the square root of the sum of the
weights
'''
if (x['unc'] > 0).all() & (x['measurements'] > 0).all():
weights = 1 / (x['unc'])**2
avg = np.average(x['measurements'],
weights=weights,
axis=0,
returned = True) # will return a tuple that needs further work
df = pd.DataFrame.from_records(np.vstack(avg).T,
columns=['averages','weights_sum'])
uncertainties = 1/np.sqrt(df['weights_sum'])
df = pd.concat([df.drop(columns=['weights_sum']), uncertainties],
axis=1)
df.columns = ['averages', 'unc']
return df
else:
return 0
. Может применяться как
df5_ave = (df5.groupby(['test_type']).apply(wgt_average))
, но это приводит к многоиндексированному кадру данных.
averages unc
test_type
a 0 2.705238 0.082808
b 0 2.340000 0.089443
c 0 1.800000 0.212132
, который можно устранить, опустив последний уровень индекса (будет улучшено)
df5_ave.index = df5_ave.index.droplevel(-1)
Это также работает для немного более продвинутых объектов groupby:
df5_ave = (df5.groupby(['test_type', 'HVL']).apply(wgt_average))
df5_ave.index = df5_ave.index.droplevel(-1)
print(df5_ave)
averages unc
test_type HVL
a 1.35 2.766667 0.086603
1.40 2.050000 0.282843
b 1.30 1.700000 0.200000
1.40 2.500000 0.100000
c 1.30 1.800000 0.212132
Проблемы, возникающие с образцом набора данных Seaborn
Однако в этом подходе должно быть что-то не так, как будто я пытаюсь применить его к другим фреймам данных, и получаю ошибки. Загрузка набора данных seaborn
planets
, например:
import numpy as np
import pandas as pd
import seaborn as sns
planets = sns.load_dataset('planets')
# planets.groupby(by=['year', 'method']).mean()
def wgt_average(x):
'''
wgt_average: calculates the weighted average on a particular column
of a groupby object. To be applied to the groupby object via .apply(wgt_average)
Parameters
----------
x : the groupby object
Returns
-------
dataframe
averages: the weighted averages
unc : their uncertainties obtained from the square root of the sum of the
weights
'''
if (x['mass'] > 0).all() & (x['orbital_period'] > 0).all():
weights = 1 / (x['mass'])**2
avg = np.average(x['orbital_period'],
weights=weights,
axis=0,
returned = True) # will return a tuple that needs further work
df = pd.DataFrame.from_records(np.vstack(avg).T,
columns=['averages','weights_sum'])
uncertainties = 1/np.sqrt(df['weights_sum'])
df = pd.concat([df.drop(columns=['weights_sum']), uncertainties],
axis=1)
df.columns = ['averages', 'unc']
return df
else:
return 0
orbitals_avg = (planets.groupby(by=['year', 'method'])).apply(wgt_average)
, приводит к:
File "/anaconda3/lib/python3.7/site-packages/ pandas / core / groupby / groupby.py ", строка 958, в reset_identity ax = v._get_axis (self.axis)
AttributeError: у объекта int нет атрибута _get_axis
Это связано с тем, как я определил метод среднего взвешивания?