【问题标题】:Plotting multiple time series after a groupby in pandas在 pandas 中的 groupby 之后绘制多个时间序列
【发布时间】:2015-09-05 17:00:58
【问题描述】:

假设我在 valgdata DataFrame 上创建了一个 groupby,如下所示:

grouped_valgdata = valgdata.groupby(['news_site','dato_uden_tid']).mean()

现在我明白了:

                                  sentiment
news_site          dato_uden_tid           
dr.dk              2015-06-15     54.777183
                   2015-06-16     54.703167
                   2015-06-17     54.948775
                   2015-06-18     54.424881
                   2015-06-19     53.290554
eb.dk              2015-06-15     53.279251
                   2015-06-16     53.285643
                   2015-06-17     53.558753
                   2015-06-18     52.854750
                   2015-06-19     54.415988
jp.dk              2015-06-15     56.590428
                   2015-06-16     55.313752
                   2015-06-17     53.771377
                   2015-06-18     53.218408
                   2015-06-19     54.392638
pol.dk             2015-06-15     54.759532
                   2015-06-16     55.182641
                   2015-06-17     55.001800
                   2015-06-18     56.004326
                   2015-06-19     54.649052

现在我想为每个 news_site 创建一个时间序列,其中 dato_uden_tid 在 X 轴上,而情绪在 Y 轴上。

实现这一目标的最佳和最简单的方法是什么?

谢谢!

【问题讨论】:

    标签: python pandas group-by time-series


    【解决方案1】:

    (有点好笑,因为这个问题让我做了同样的事情。)

    你可以这样做

    valgdata\
        .groupby([valgdata.dato_uden_tid.name, valgdata.news_site.name])\
        .mean()\
        .unstack()
    

    这会

    • 反向分组

    • 将新站点取消堆叠为列

    要绘图,只需执行前面的 sn-p 紧跟 .plot():

    valgdata\
        .groupby([valgdata.dato_uden_tid.name, valgdata.news_site.name])\
        .mean()\
        .unstack()\
        .plot()
    

    【讨论】:

    • 谢谢!正是我想要的!
    【解决方案2】:

    这是一个使用 Pandas 和 Matplotlib 进行更细粒度控制的解决方案。

    首先,我在下面提供了一个生成随机数据帧进行测试的函数。重要的是,它创建了三个列来概括更抽象的问题:

    • my_timestamp 是一个包含时间戳的 datetime
    • my_series 是要应用 groupby 的字符串标签
    • my_value 是在 my_timestamp 时间为 my_series 记录的数值

    用您拥有的任何数据框替换列名。

    def generate_random_data(N=100):
        '''
        Returns a dataframe with N rows of random data.
        '''
        list_of_lists = []
        labels = ['foo', 'bar', 'baz']
        epoch = 1515617110
        for _ in range(N):
            key = random.choice(labels)
            value = 0
            if key == 'foo':
                value = random.randint(1, 10)
            elif key == 'bar':
                value = random.randint(50, 60)
            else:
                value = random.randint(80, 90)
            epoch += random.randint(5000, 30000)
            row = [key, epoch, value]
            list_of_lists.append(row)
        df = pd.DataFrame(list_of_lists, columns=['my_series', 'epoch', 'my_value'])
        df['my_timestamp'] = pd.to_datetime(df['epoch'], unit='s')
        df = df[['my_timestamp', 'my_series', 'my_value']]
        #df.set_index('ts', inplace=True)
        return df
    

    这是生成的一些示例数据:

    现在,以下代码将运行 groupby 并绘制一个漂亮的时间序列图。

    def plot_gb_time_series(df, ts_name, gb_name, value_name, figsize=(20,7), title=None):
        '''
        Runs groupby on Pandas dataframe and produces a time series chart.
    
        Parameters:
        ----------
        df : Pandas dataframe
        ts_name : string
            The name of the df column that has the datetime timestamp x-axis values.
        gb_name : string
            The name of the df column to perform group-by.
        value_name : string
            The name of the df column for the y-axis.
        figsize : tuple of two integers
            Figure size of the resulting plot, e.g. (20, 7)
        title : string
            Optional title
        '''
        xtick_locator = DayLocator(interval=1)
        xtick_dateformatter = DateFormatter('%m/%d/%Y')
        fig, ax = plt.subplots(figsize=figsize)
        for key, grp in df.groupby([gb_name]):
            ax = grp.plot(ax=ax, kind='line', x=ts_name, y=value_name, label=key, marker='o')
        ax.xaxis.set_major_locator(xtick_locator)
        ax.xaxis.set_major_formatter(xtick_dateformatter)
        ax.autoscale_view()
        ax.legend(loc='upper left')
        _ = plt.xticks(rotation=90, )
        _ = plt.grid()
        _ = plt.xlabel('')
        _ = plt.ylim(0, df[value_name].max() * 1.25)
        _ = plt.ylabel(value_name)
        if title is not None:
            _ = plt.title(title)
        _ = plt.show()
    

    这是一个调用示例:

    df = generate_random_data()
    
    plot_gb_time_series(df, 'my_timestamp', 'my_series', 'my_value',
                        figsize=(10, 5), title="Random data")
    

    这是生成的时间序列图:

    【讨论】:

      猜你喜欢
      • 2017-03-07
      • 2018-09-26
      • 1970-01-01
      • 2022-01-06
      • 2017-01-28
      • 1970-01-01
      • 2016-02-09
      • 2019-12-27
      • 2016-11-06
      相关资源
      最近更新 更多