【问题标题】:Pandas: Convert a DataFrame into a Series when index is Year-Month and columns are DayPandas:当索引为年月且列为日时,将 DataFrame 转换为系列
【发布时间】:2017-11-16 15:10:12
【问题描述】:

我有一个类似于以下内容的数据框:

df = pd.DataFrame({'Y_M':['201710','201711','201712'],'1':[1,5,9],'2':[2,6,10],'3':[3,7,11],'4':[4,8,12]})
df = df.set_index('Y_M')

这会创建一个如下所示的数据框:

        1  2  3   4
Y_M                
201711  1  2  3  4
201712  5  6  7  8
201713  9  10 11 12

这些列是一个月中的哪一天。它们向右延伸,一直到 31。(2 月的第 29、30 和 31 列将填充 NaN)。 该索引包含年份和月份(例如 201711 指的是 2017 年 11 月)

我的问题是:如何将年/月/日组合成一个系列?我的输出如下:

Y_M                
20171001    1
20171002    2
20171003    3
20171004    4
20171101    5  
20171102    6
20171103    7
20171104    8
20171201    9
20171202   10
20171203   11
20171204   12

索引可以转换为日期时间。事实上,我认为这会更容易。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    stack 用于Series,然后将datetimes by to_datetimetimedeltas by to_timedelta:

    df = df.stack()
    df.index = pd.to_datetime(df.index.get_level_values(0), format='%Y%m') + \
               pd.to_timedelta(df.index.get_level_values(1).astype(int) - 1, unit='D') 
    print (df)
    2017-10-01     1
    2017-10-02     2
    2017-10-03     3
    2017-10-04     4
    2017-11-01     5
    2017-11-02     6
    2017-11-03     7
    2017-11-04     8
    2017-12-01     9
    2017-12-02    10
    2017-12-03    11
    2017-12-04    12
    dtype: int64
    
    print (df.index)
    DatetimeIndex(['2017-10-01', '2017-10-02', '2017-10-03', '2017-10-04',
                   '2017-11-01', '2017-11-02', '2017-11-03', '2017-11-04',
                   '2017-12-01', '2017-12-02', '2017-12-03', '2017-12-04'],
                  dtype='datetime64[ns]', freq=None)
    

    如有必要,在index 中添加strings(不是DatetimeIndex)添加DatetimeIndex.strftime

    df.index = df.index.strftime('%Y%m%d')
    print (df)
    20171001     1
    20171002     2
    20171003     3
    20171004     4
    20171101     5
    20171102     6
    20171103     7
    20171104     8
    20171201     9
    20171202    10
    20171203    11
    20171204    12
    dtype: int64
    
    print (df.index)
    Index(['20171001', '20171002', '20171003', '20171004', '20171101', '20171102',
           '20171103', '20171104', '20171201', '20171202', '20171203', '20171204'],
          dtype='object')
    

    【讨论】:

    • Stack 正是我需要的功能!谢谢@jezrael!
    【解决方案2】:

    不带date

    s = df.stack()
    s.index = s.index.map('{0[0]}{0[1]:>02s}'.format)
    s
    
    20171001     1
    20171002     2
    20171003     3
    20171004     4
    20171101     5
    20171102     6
    20171103     7
    20171104     8
    20171201     9
    20171202    10
    20171203    11
    20171204    12
    dtype: int64
    

    【讨论】:

    • 哇。这是一个很好的方法!也允许使用非日期值执行此操作。不过我不太明白。在index.map() 中,您向它传递一个字符串,该字符串指示它映射的内容。它访问层次索引“0”、0 级和 1 级。但我不知道 :>02s 是什么,以及为什么这也适用于原始“日”列中的 2 位值。
    • pd.Index.map 接受一个可调用对象并将每个索引值传递给它。在这种情况下,索引是多索引。因此,传递给可调用对象的每个值都是一个元组。知道了这一点,我编写了一个处理它的字符串格式化调用。你可以用字符串格式做很多时髦的事情,我不能在这里全部介绍,但我所做的是说我想要元组{0[0]}的第一个元素在前面,元组的第二个元素{0[1]}在后面。但是,我给它添加了一些对齐魔法。 {0[1]:>02s} 表示将字符串右对齐,缓冲区为 2,并用 0 填充。
    • 感谢您的详尽解释!这太棒了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 2017-04-06
    • 1970-01-01
    • 2019-11-28
    • 2015-08-08
    相关资源
    最近更新 更多