【问题标题】:Convert "informal" month-day index to a datetime index将“非正式”月日索引转换为日期时间索引
【发布时间】:2017-08-27 23:22:15
【问题描述】:

我有一个索引为月日格式的系列。它不是正式的日期时间索引。此外,该系列包含一年中每一天的一个数据:

       Data_Value
01-01         156
01-02         139
01-03         133
01-04         106
01-05         128
01-06         189

我的目标是制作一个线图,其中 y 轴为“Data_Value”,x 轴为十二个月。但我想绘制 365 个数据,而不是将它们汇总为 12 个月。像这样的:

无论如何,我的第一步是绘制 365 数据,忽略将月份名称放在 x 轴上的事实:

s = np.array(s)
plt.figure()
plt.plot(s, '-o')

但在最后一个命令中,我收到错误“ValueError:无法将字符串转换为浮点数:'12-31'”。

有人如何将“非正式”月日索引转换为省略年份的日期时间索引?或任何其他解决方案来达到我绘制系列的最终目标?谢谢。

【问题讨论】:

    标签: python pandas matplotlib plot


    【解决方案1】:

    你可以使用:

    np.random.seed(100)
    rng = pd.date_range('2017-01-01', periods=365).strftime('%m-%d')
    df = pd.DataFrame({ 'Data_value': np.random.randint(1000, size=365)}, index=rng)  
    #print (df)
    
    d = {'01':'Jan', '02':'Feb', '03':'Mar','04': 'Apr', '05':'May','06': 'Jun', 
         '07':'Jul', '08':'Aug','09': 'Sep','10': 'Oct', '11':'Nov','12': 'Dec'}
    
    #add _for match only first value of string to dict
    d = {'_' + k:v for k, v in d.items()}
    
    #add _ to index
    df.index = '_' + df.index
    #split values by - to MultiIndex
    df.index = df.index.str.split('-', expand=True) 
    
    #reshape and replace NaN to 0
    df = df['Data_value'].unstack(fill_value=0)
    #rename index values by dict
    df = df.rename(index=d)
    
    print (df)
          01   02   03   04   05   06   07   08   09   10 ...    22   23   24  \
    Jan  520  792  835  871  855   79  944  906  350  948 ...   316  570  912   
    Feb  900  415  897  141  757  723  612    4  603  955 ...     2  889  617   
    Mar  181  283  824  238  369  926  944  303  679  877 ...   618   30   17   
    Apr  693  846    0   13  185  460  362  131  582  643 ...   811   36  773   
    May  852   95  626  749  631   76  801  314  102  938 ...   419  407  765   
    Jun  677  870  122  628  186  295  619  734  819  286 ...    16  524  854   
    Jul  138  776  473  712  414  908  658  349  887  604 ...   389  435  346   
    Aug  385   14  883  289  148  168  536  477  442  796 ...   730  250  477   
    Sep   82  998  401  906  653  593  885  793  194  655 ...   944  754  506   
    Oct  144  819  182  183   83  502  356  554  957  760 ...    70  309  994   
    Nov  674  131  870  139  305  797  804  861  451  922 ...   723  119   71   
    Dec  781  304  466  544  294  296  497  693   93  398 ...   915  716  322   
    
          25   26   27   28   29   30   31  
    Jan  507  649   93   86  386  667  876  
    Feb  478  403  994   63    0    0    0  
    Mar   53   68  946  488  347  475  979  
    Apr  839   38  214   94  738  170    0  
    May  521  944  496  789  409  438  262  
    Jun  466  621   67  220  223  788    0  
    Jul   34  451  862  974  694   77  212  
    Aug  736   74  437  798   67  668  933  
    Sep  693  657  705  298  861  172    0  
    Oct  736  943  944  905  689  821  879  
    Nov  829   93  498  804  123  554    0  
    Dec  141   87   65  324  182  640  343  
    
    [12 rows x 31 columns]
    

    最后DataFrame.plot

    df.plot()
    

    【讨论】:

    • 我需要一个月和几天,而不仅仅是几个月。但我想要水平轴上的月份名称。我编辑了我之前的帖子以添加一个清晰的概念图。顺便说一句,忘记两条线和阴影区域。我只画了一条线。
    • 你能解释更多吗?我在索引、列中按月和天创建数据框。现在我不明白如何创建一行。还有左轴40,0,-30是什么?
    • 好的,所以获取 2 个数据帧 - 一个用于最小值,另一个用于最大值。但是现在如何在没有聚合的情况下绘制它?有很多值,似乎day 信息不像edit 那样是必需的。还是缺少什​​么?
    • 对不起。让我们添加一些上下文。 “Data_Value”包含以°F 为单位的温度。在我的概念图中,从左 y 轴(-30 到 40)的范围只是转换为°C 的附加信息。此外,我必须绘制 2005-2014 年期间一年中的最高和最低温度。但为了使其更具样本性,我为“Data_Value”列提供了高温值(但我还有另一个低温值)。这就是为什么绘图显示两条线的原因。因此,我的高温系列“s”的长度为 365。
    【解决方案2】:

    这就是我所做的,正如jezrael 建议的那样:

    在索引中添加一个随机年份以将其转换为日期时间索引:

    s.index = '2014-' + s.index.astype(str)
    s.index = pd.to_datetime(s.index)
    days_s = s.index
    days_s = np.array(days_s)
    

    然后设置并绘制情节:

    plt.figure()
    plt.plot(days_s, s, '-o')
    

    并使用 mdates.DateFormatter 将 x 轴从 %y-%m-%d 更改为 %m 格式:

    import matplotlib.dates as mdates
    monthsFmt = mdates.DateFormatter('%m')
    plt.gca().xaxis.set_major_formatter(monthsFmt)
    

    最后,渲染情节:

    plt.show()
    

    我不知道这个解决方案是否有点草率,但它确实有效。

    【讨论】:

      猜你喜欢
      • 2016-10-05
      • 2019-06-02
      • 2020-10-05
      • 2017-07-11
      • 2020-10-18
      • 2018-10-30
      • 2018-01-24
      • 1970-01-01
      相关资源
      最近更新 更多