У меня есть фрейм данных со столбцом весов и одним из значений.Мне нужно:
- до дискретных весов и, для каждого интервала весов, построить средневзвешенное значение , затем
- , чтобы расширить ту же логикук другой переменной: дискретизируйте z, и для каждого интервала выведите средневзвешенное значение, взвешенное по весам
Есть ли простой способ добиться этого? Я нашел способ, но, похоже,Немного громоздко:
- Я делаю дискретный кадр данных с помощью pandas.cut ()
- , делаю сгруппированную и вычисляю средневзвешенное значение
- строит среднее значение каждого бина противсредневзвешенное значение
- Я также пытался сгладить кривую с помощью сплайна, но это мало что дает
В основном я ищу лучший способ получения более сглаженногокривая.
Мой вывод выглядит следующим образом:
и мой код с некоторыми случайными данными:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.interpolate import make_interp_spline, BSpline
n=int(1e3)
df=pd.DataFrame()
np.random.seed(10)
df['w']=np.arange(0,n)
df['v']=np.random.randn(n)
df['ranges']=pd.cut(df.w, bins=50)
df['one']=1.
def func(x, df):
# func() gets called within a lambda function; x is the row, df is the entire table
b1= x['one'].sum()
b2 = x['w'].mean()
b3 = x['v'].mean()
b4=( x['w'] * x['v']).sum() / x['w'].sum() if x['w'].sum() >0 else np.nan
cols=['# items','avg w','avg v','weighted avg v']
return pd.Series( [b1, b2, b3, b4], index=cols )
summary = df.groupby('ranges').apply(lambda x: func(x,df))
sns.set(style='darkgrid')
fig,ax=plt.subplots(2)
sns.lineplot(summary['avg w'], summary['weighted avg v'], ax=ax[0])
ax[0].set_title('line plot')
xnew = np.linspace(summary['avg w'].min(), summary['avg w'].max(),100)
spl = make_interp_spline(summary['avg w'], summary['weighted avg v'], k=5) #BSpline object
power_smooth = spl(xnew)
sns.lineplot(xnew, power_smooth, ax=ax[1])
ax[1].set_title('not-so-interpolated plot')