如何平滑和绘制 x 与 y 加权平均数, 加权 x?

我有一个数据框, 其中包含一列权重和一个值。我需要:

  • 离散权重, 并为每个权重间隔绘制值的加权平均值, 然后
  • 将相同的逻辑扩展到另一个变量: 离散 z, 并为每个间隔绘制值的加权平均值, 按权重加权

是否有一个简单的方法来实现这一点?我已经找到了一个方法, 但它似乎有点麻烦:

  • 我用熊猫离散数据框。
  • 做一个小组和计算加权平均
  • 绘制每个纸盒的平均值与加权平均数
  • 我也试图用样条来平滑曲线, 但它没有做太多

基本上, 我正在寻找一个更好的方法来产生一个更平滑的曲线。

我的输出如下所示:enter image description here

我的代码, 一些随机数据, 是:

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')
第1个答案

如果我理解正确, 你是想重新创造一个滚动的平均值。

这已经是熊猫数据框的功能, 使用的 rolling 功能:

dataframe.rolling(n).mean()

其中 n , 平均值的 "窗口" 或 "bin" 中使用的相邻点的数量, 因此您可以对其进行调整, 以获得不同程度的平滑度。

您可以在这里找到示例:

第2个答案

你的问题的第一部分是相当容易做到的。

我不知道你对第二部分是什么意思。您是想要 (简化) 复制您的代码还是希望采用更适合您需要的新方法?

无论如何, 我不得不看看你的代码, 以了解你的意思是加权的值。我想人们通常会期待一些与这个词不同的东西 (只是一个警告)。

以下是您的方法的简化版本:

df['prod_v_w'] = df['v']*df['w']
weighted_avg_v = df.groupby(pd.cut(df.w, bins=50))[['prod_v_w','w']].sum()\
                   .eval('prod_v_w/w')
print(np.allclose(weighted_avg_v, summary['weighted avg v']))
Out[18]: True
第3个答案

我认为这是解决你所寻求的问题的办法。它按照其他人的建议使用滚动窗口。需要做更多的工作才能使其正常工作。

df["w*v"] = df["w"] * df["v"]

def rolling_smooth(df,N):
    df_roll = df.rolling(N).agg({"w":["sum","mean"],"v":["mean"],"w*v":["sum"]})
    df_roll.columns = [' '.join(col).strip() for col in df_roll.columns.values]
    df_roll['weighted avg v'] = np.nan
    cond = df_roll['w sum'] > 0
    df_roll.loc[cond,'weighted avg v'] = df_roll.loc[cond,'w*v sum'] / df_roll.loc[cond,'w sum']
    return df_roll

df_roll_100 = rolling_smooth(df,100)
df_roll_200 = rolling_smooth(df,200)

plt.plot(summary['avg w'], summary['weighted avg v'],label='original')
plt.plot(df_roll_100["w mean"],df_roll_100["weighted avg v"],label='rolling N=100')
plt.plot(df_roll_200["w mean"],df_roll_200["weighted avg v"],label='rolling N=200')
plt.legend()

enter image description here

相关问题

通过随机抽样其他列数据创建新列 如何使用熊猫获得包括每一个组合的计数 如何有效地展开矩阵的值与小块? 如何破坏 Python 对象并释放内存 将具有特殊格式的文本文档转换为熊猫数据框架 用两本字典绘制一只熊猫专栏图 如何平滑和绘制 x 与 y 加权平均数, 加权 x? 安装 Matplotlib 时出错: 致命错误 C1083 根据选择的值总结和绘制 ndarray 列表 根据给定条件过滤数据框并添加新列 动态列名的 Pandas 聚合 如果我使用 pandas 为同一项目同时具有 True 和 False 行,则获取 True 行。 计算加权平均值的 STL/ranges 算法