Python 如何在matplotlib中制作不同y轴的叠层折线图?

Python 如何在matplotlib中制作不同y轴的叠层折线图?,python,pandas,matplotlib,seaborn,Python,Pandas,Matplotlib,Seaborn,我想知道我应该如何制作堆叠折线图,它将在matplotlib中采用不同的列。关键是当我们进行聚合时,我需要在两个不同的列上进行数据聚合,我想我需要制作一个用于绘图的大数据帧。我没有在熊猫身上找到更漂亮、更方便的方法,matplotlib。有人能提出一些可能的调整吗?有什么想法吗 我的尝试 这是我需要做的第一个聚合: import pandas as pd import matplotlib.pyplot as plt url = "https://gist.githubusercon

我想知道我应该如何制作堆叠折线图,它将在matplotlib中采用不同的列。关键是当我们进行聚合时,我需要在两个不同的列上进行数据聚合,我想我需要制作一个用于绘图的大数据帧。我没有在熊猫身上找到更漂亮、更方便的方法,matplotlib。有人能提出一些可能的调整吗?有什么想法吗

我的尝试

这是我需要做的第一个聚合:

import pandas as pd
import matplotlib.pyplot as plt

url = "https://gist.githubusercontent.com/adamFlyn/4657714653398e9269263a7c8ad4bb8a/raw/fa6709a0c41888503509e569ace63606d2e5c2ff/mydf.csv"
df = pd.read_csv(url, parse_dates=['date'])

df_re = df[df['retail_item'].str.contains("GROUND BEEF")]
df_rei = df_re.groupby(['date', 'retail_item']).agg({'number_of_ads': 'sum'})
df_rei = df_rei.reset_index(level=[0,1])
df_rei['week'] = pd.DatetimeIndex(df_rei['date']).week
df_rei['year'] = pd.DatetimeIndex(df_rei['date']).year
df_rei['week'] = df_rei['date'].dt.strftime('%W').astype('uint8')

df_ret_df1 = df_rei.groupby(['retail_item', 'week'])['number_of_ads'].agg([max, min, 'mean']).stack().reset_index(level=[2]).rename(columns={'level_2': 'mm', 0: 'vals'}).reset_index()
这是我需要做的第二个聚合,与第一个聚合类似,只是我现在选择了不同的列:

df_re['price_gap'] = df_re['high_price'] - df_re['low_price']
dff_rei1 = df_re.groupby(['date', 'retail_item']).agg({'price_gap': 'mean'})
dff_rei1 = dff_rei1.reset_index(level=[0,1])
dff_rei1['week'] = pd.DatetimeIndex(dff_rei1['date']).week
dff_rei1['year'] = pd.DatetimeIndex(dff_rei1['date']).year
dff_rei1['week'] = dff_rei1['date'].dt.strftime('%W').astype('uint8')

dff_ret_df2 = dff_rei1.groupby(['retail_item', 'week'])['price_gap'].agg([max, min, 'mean']).stack().reset_index(level=[2]).rename(columns={'level_2': 'mm', 0: 'vals'}).reset_index()
现在,我正在努力将第一次、第二次聚合的输出合并到一个数据帧中,以制作堆叠折线图。这样做可能吗

目标

我想制作堆叠的折线图,其中y轴采用不同的列,如y轴应显示广告数量和价格范围,而x轴显示52周期间。这是我试图制作折线图的部分代码:

for g, d in df_ret_df1.groupby('retail_item'):
    fig, ax = plt.subplots(figsize=(7, 4), dpi=144)
    sns.lineplot(x='week', y='vals', hue='mm', data=d,alpha=.8)
    y1 = d[d.mm == 'max']
    y2 = d[d.mm == 'min']
    plt.fill_between(x=y1.week, y1=y1.vals, y2=y2.vals)
    
    for year in df['year'].unique():
        data = df_rei[(df_rei.date.dt.year == year) & (df_rei.retail_item == g)]
        sns.lineplot(x='week', y='price_gap', ci=None, data=data,label=year,alpha=.8)
有没有什么优雅的方法可以让我们构建绘图数据,从而可以轻松地在不同的列上进行数据聚合?有没有其他方法可以实现这一点?有什么想法吗

所需输出

以下是我想要得到的期望输出:


我应该如何制作绘图数据以获得所需的绘图?有什么想法吗?

Pandas groupby功能非常通用,您可以大大减少代码行,以获得用于打印的最终数据帧

plotdf = df_re.groupby([ 'retail_item',df_re['date'].dt.year,df_re['date'].dt.week]).agg({'number_of_ads':'sum','price_gap':'mean'}).unstack().T
以正确的方式完成聚合后,使用for循环在不同的绘图中显示所需的每个度量值。使用pandas Descripte功能绘制阴影范围,以计算动态的最小值和最大值:

f,axs = plt.subplots(2,1,figsize=(20,14))
axs=axs.ravel()

for i,x in enumerate(['number_of_ads','price_gap']):
    plotdf.loc[x].plot(rot=90,grid=True,ax=axs[i])
    plotdf.loc[x].T.describe().T[['min','max']].plot(kind='area',color=['w','grey'],alpha=0.3,ax=axs[i],title= x)

使用更新的代码进行编辑:

plotdf = df_re.groupby(['retail_item',df_re['date'].dt.year,df_re['date'].dt.week]).agg({'number_of_ads':'sum','weighted_avg':'mean'}).unstack().T
f,axs = plt.subplots(3,2,figsize=(20,14))
axs=axs.ravel()
i=0
for col in plotdf.columns.get_level_values(0).unique():
    for x in ['number_of_ads','weighted_avg']:
        plotdf.loc[x,col].plot(rot=90,grid=True,ax=axs[i]);
      plotdf.loc[x,col].T.describe().T[['min','max']].plot(kind='area',color=['w','grey'],alpha=0.3,ax=axs[i],title= col+', '+x)
        i+=1

缺少答案的一个原因可能是,我们必须重新设计您试图通过两个聚合实现的目标。我建议添加对这些步骤的描述,以及最终图形应该显示的内容。我还有一些错误消息,如
NameError:name'cmap'未定义
@Mr.T我附加了我最终想要的绘图并修复了错误。我回答了这个问题,你对这个问题有更好的看法吗?非常感谢。我现在没有时间调查这个问题。也许本周晚些时候,但我想到时候会有人解决你的问题。对我来说,这个问题看起来像是一个重复的问题。最好是澄清你以前的问题,而不是发布一个新的问题。我将根据您现在提供的所需输出查看如何编辑以提供解决方案。@T先生,在对上一个问题的回答中,包括我自己的回答中,这个问题已经得到了很大程度的回答。我可以在接下来的几天内抽出时间编辑我的答案,但我不确定是应该在这里发布新答案,还是根据新信息编辑我的现有答案。为什么在第17周到第45周之间没有显示数据?我知道情节的结构看起来是对的,但情节本身是不对的。您可以进行任何可能的更新吗?我们可以使用y轴上的加权平均值,而不是使用价格范围,在这种情况下,可能的输出是什么?有更新吗?谢谢源数据已更改-不再包含2019数据。如果你更新它,它会显示出来。至于加权平均值,是的,可以得到任何你想要的度量,你只需要写一个聚合函数,而不是第一行的“平均值”:“价格差距”:“平均值”当我对加权平均值进行聚合时,它得到了错误。如果我们想在加权平均值上进行聚合,您介意添加代码行吗?此外,我们是否可以按年份划分子地块,例如2020年、2021年在一个堆叠地块中的每个零售项目?我们是否可以使用for循环按零售项目进行迭代,其中每个堆叠图显示2020年、2021年的特定项目广告和价格范围数据?我们怎么能像我在期望的情节中所展示的那样呢?有什么想法吗?ThanksI能够使用加权平均值而不是价格差来运行它。请检查您的密码。上面编辑的代码生成6个图表,每个产品2个。如果您的所有原始问题都已解决,请标记为答案。我们能否在y轴上汇总高、低和重量平均价格,同时保持您在更新尝试中显示的格式完全相同?这可行吗?你介意告诉我我们该怎么做吗?我肯定会接受答案,但这个问题一直萦绕着我。再次感谢你的帮助!