在python数据帧中旋转/解压缩时间序列数据

时间:2014-01-05 16:41:44

标签: python numpy pandas

我有一个温度数据的数据框,用这样的列列出:

MONTH YEAR VALUE1 FLAGA1 FLAGB1 ... VALUE31 FLAGA31 FLAGB31

VALUE和FLAG指的是一个月中的某一天,这样VALUE1是该月第一天的值,第二天是VALUE2,依此类推。

显然,这是一个时间序列,具有时髦的格式(它对于处理几个月的部分实际上很有用,这就是为什么它就像这样)。我想最终得到这样的东西:

DATE YEAR VALUE FLAGA FLAGB

(是的,DATE和YEAR是多余的,但对过滤很有用)。

我真的不知道怎么开始这个。我的自然倾向是迭代源帧并创建一个新结构,但我甚至不知道如何迭代源帧中的值。我还怀疑Pandas / Numpy方式不是单独迭代。

1 个答案:

答案 0 :(得分:1)

好的,我想我为你找到了一些东西。这是一个玩具数据集:

import numpy as np
import pandas
import StringIO
from  itertools import product

csvstring = StringIO.StringIO("""\
month,year,val1,flagA1,flagB1,val2,flagA2,flagB2,val3,flagA3,flagB3
12,2011,1,a1,b1,2,a2,b2,3,a3,b3
1,2012,4,a4,b4,5,a5,b5,6,a6,b6
2,2012,7,a7,b7,8,a8,b8,9,a9,b9
""")

df = pandas.read_csv(csvstring)
df['date'] = df.apply(lambda row: datetime.datetime(row['year'], row['month'], 1), axis=1)
df = df.set_index('date').drop(['month', 'year'], axis=1)
print(df.to_string())

            val1 flagA1 flagB1  val2 flagA2 flagB2  val3 flagA3 flagB3
date                                                                  
2011-12-01     1     a1     b1     2     a2     b2     3     a3     b3
2012-01-01     4     a4     b4     5     a5     b5     6     a6     b6
2012-02-01     7     a7     b7     8     a8     b8     9     a9     b9

(我删除了monthyear,并将date列为行索引。您会明白原因。)

接下来,我们需要创建一个MultiIndex对象来表示存储在列中的当前信息。我们现在列数为三个:ValueFlagAFlagB。那么我们有多少列?

base_cols = ['value', 'FlagA', 'FlagB']  # the basic set we want
num_sets = df.columns.shape[0] / len(base_cols)  # number of sets we currently have

我们需要创建的层次结构索引是base_colsrange(1, num_sets+1)的乘积。

newcols = pandas.MultiIndex.from_tuples([p for p in product(range(1, num_sets+1), base_cols)])

给了我们:

MultiIndex
[(1, u'value'), (1, u'FlagA'), (1, u'FlagB'), (2, u'value'), (2, u'FlagA'), (2, u'FlagB'), (3, u'value'), (3, u'FlagA'), (3, u'FlagB')]

现在只需将这些新列分配给DataFrame:

df.columns = newcols
df.columns.names = ['set', 'results']
print(df.to_string())
set             1     1     1      2     2     2      3     3     3
results     value FlagA FlagB  value FlagA FlagB  value FlagA FlagB
date                                                               
2011-12-01      1    a1    b1      2    a2    b2      3    a3    b3
2012-01-01      4    a4    b4      5    a5    b5      6    a6    b6
2012-02-01      7    a7    b7      8    a8    b8      9    a9    b9

然后,如果你stack数据框,你得到这个:

stacked = df.stack(level='set')
print(stacked.to_string())

results        FlagA FlagB  value
date       set                   
2011-12-01 1      a1    b1      1
           2      a2    b2      2
           3      a3    b3      3
2012-01-01 1      a4    b4      4
           2      a5    b5      5
           3      a6    b6      6
2012-02-01 1      a7    b7      7
           2      a8    b8      8
           3      a9    b9      9

此时,认为你已经完成了。如果需要,可以重新添加year列(stacked['year'] = stacked.apply(lambda row: row.name[0].year, axis=1))但是使用pandas,您根本不需要这样做。日期时间索引处理非常强大,如下所示:Pandas DataFrame slicing by day/hour/minute