我有一个温度数据的数据框,用这样的列列出:
MONTH YEAR VALUE1 FLAGA1 FLAGB1 ... VALUE31 FLAGA31 FLAGB31
VALUE和FLAG指的是一个月中的某一天,这样VALUE1是该月第一天的值,第二天是VALUE2,依此类推。
显然,这是一个时间序列,具有时髦的格式(它对于处理几个月的部分实际上很有用,这就是为什么它就像这样)。我想最终得到这样的东西:
DATE YEAR VALUE FLAGA FLAGB
(是的,DATE和YEAR是多余的,但对过滤很有用)。
我真的不知道怎么开始这个。我的自然倾向是迭代源帧并创建一个新结构,但我甚至不知道如何迭代源帧中的值。我还怀疑Pandas / Numpy方式不是单独迭代。
答案 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
(我删除了month
和year
,并将date
列为行索引。您会明白原因。)
接下来,我们需要创建一个MultiIndex
对象来表示存储在列中的当前信息。我们现在列数为三个:Value
,FlagA
和FlagB
。那么我们有多少列?
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_cols
和range(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