【问题标题】:How to plot data with gaps into subplots如何将有间隙的数据绘制到子图中
【发布时间】:2021-01-04 22:28:55
【问题描述】:

我有一个有间隙的数据框

                                    temperature 
    data                                                        
    2016-01-01 01:00:00              -8.2 
    2016-01-01 02:00:00              -8.3  
    2016-01-01 03:00:00              -9.1 
    2016-01-01 04:00:00              -9.1  
    2016-01-01 05:00:00              -9.6 
        ...                           ...     
    2020-02-29 20:00:00               5.9   
    2020-02-29 21:00:00               5.4   
    2020-02-29 22:00:00               4.7 
    2020-02-29 23:00:00               4.3 
    2020-03-01 00:00:00               4.3

这是一些示例数据的代码,与我的不同,但概念相同:

def tworzeniedaty():
    import pandas as pd
    rng1 = list(pd.date_range(start='2016-01-01', end='2016-02-29', freq='D'))
    rng2 = list(pd.date_range(start='2016-12-15', end='2017-02-28', freq='D'))
    rng3 = list(pd.date_range(start='2017-12-15', end='2018-02-28', freq='D'))
    rng4 = list(pd.date_range(start='2018-12-15', end='2019-02-28', freq='D'))
    rng5 = list(pd.date_range(start='2019-12-15', end='2020-02-29', freq='D'))
    return rng1 + rng2 + rng3 + rng4 + rng5


import random
import pandas as pd

lista = [random.randrange(1, 10, 1) for i in range(len(tworzeniedaty()))]
df = pd.DataFrame({'Date': tworzeniedaty(), 'temperature': lista})
df['Date'] = pd.to_datetime(df['Date'], format="%Y/%m/%d")

当我绘制数据时,我得到一个非常混乱的图。

相反,我想得到:

这和How to plot only specific months in a time series of several years? 是同一个问题,但我想用python 做,不能破译R 代码。

【问题讨论】:

  • 您想要数据组的子图,还是只想摆脱该图中的连接线?在这两种情况下,您都应该定义什么是“组”或“间隙”。查看图表,似乎将其定义为“至少三个月没有数据”是可接受的差距定义。但它适用于您的所有数据吗?
  • 我想做子图,是的,我的数据有 3 个月的休息时间。我添加了一些示例数据,日期与我的匹配。

标签: python pandas matplotlib


【解决方案1】:

我们可以通过计算日期之间的差异并检查它是否超过三个月的限制来对数据进行分组:

from matplotlib import pyplot as plt
import random
import pandas as pd

def tworzeniedaty():
    rng1 = list(pd.date_range(start='2016-01-01', end='2016-02-29', freq='D'))
    rng2 = list(pd.date_range(start='2016-12-15', end='2017-02-28', freq='D'))
    rng3 = list(pd.date_range(start='2017-12-15', end='2018-02-28', freq='D'))
    rng4 = list(pd.date_range(start='2018-12-15', end='2019-02-28', freq='D'))
    rng5 = list(pd.date_range(start='2019-12-15', end='2020-02-29', freq='D'))
    return rng1 + rng2 + rng3 + rng4 + rng5

lista = [random.randrange(1, 10, 1) for i in range(len(tworzeniedaty()))]
df = pd.DataFrame({'Date': tworzeniedaty(), 'temperature': lista})


#assuming that the df is sorted by date, we look for gaps of more than 3 months
#then we label the groups with consecutive numbers
df["groups"] = (df["Date"].dt.month.diff() > 3).cumsum()
n = 1 + df["groups"].max()

#creating the desired number of subplots
fig, axes = plt.subplots(1, n, figsize=(15, 5), sharey=True)

#plotting each group into a subplot
for (i, group_df), ax in zip(df.groupby("groups"), axes.flat):
    ax.plot(group_df["Date"], group_df["temperature"])
      
fig.autofmt_xdate(rotation=45)    
plt.tight_layout()
plt.show()

样本输出:

显然,如果应该存在更多组,则需要进行一些微调。在这种情况下,网格将是合适的 - 可以create a subplot grid and remove unnecessary subplots like in this matplotlib example。 x-labels 可能还需要使用a matplotlib Locator and Formatter 进行一些调整以获得更好的外观。其中一些可以使用hue in seaborn 的分组变量自动完成;但是,这可能会导致一系列不同的问题。

【讨论】:

    【解决方案2】:

    我认为最好的方法是过滤掉六月/七月/八月的数据,就像在 R 代码中所做的那样。这应该会有所帮助:

    def tworzeniedaty():
        import pandas as pd
        rng1 = list(pd.date_range(start='2016-01-01', end='2016-02-29', freq='D'))
        rng2 = list(pd.date_range(start='2016-12-15', end='2017-02-28', freq='D'))
        rng3 = list(pd.date_range(start='2017-12-15', end='2018-02-28', freq='D'))
        rng4 = list(pd.date_range(start='2018-12-15', end='2019-02-28', freq='D'))
        rng5 = list(pd.date_range(start='2019-12-15', end='2020-02-29', freq='D'))
        return rng1 + rng2 + rng3 + rng4 + rng5
    
    
    import random
    import pandas as pd
    
    import matplotlib.pyplot as plt
    
    lista = [random.randrange(1, 10, 1) for i in range(len(tworzeniedaty()))]
    df = pd.DataFrame({'Date': tworzeniedaty(), 'temperature': lista})
    df['Date'] = pd.to_datetime(df['Date'], format="%Y/%m/%d")
    
    years = list(set(df.Date.dt.year))
    
    
    fig, ax = plt.subplots(1, len(years))
    for i in years:
            df_set =  df[df.Date.dt.year == i]
            df_set.set_index("Date", inplace = True)
            df_set.index = df_set.index.map(str)
            ax[years.index(i)].plot(df_set)
            ax[years.index(i)].title.set_text(i)
    
    plt.show()
    

    【讨论】:

    • 你能显示数据吗?我的意思是创建此示例数据框的代码,以便我可以相应地更新答案。 @Mr.T.据我了解,与此问题附带的 R 解决方案相比,数据应该是这样的。
    • 我添加了一个示例数据。
    • @wychen 那里是常量数据,还有字符串中的日期,而不是日期时间格式。
    • 对不起,我修好了。
    • 更新了答案,请查看@wychen
    猜你喜欢
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    相关资源
    最近更新 更多