Pandas Dataframe - 如何将日期转换为布尔列?

时间:2014-08-23 23:50:07

标签: python pandas

我在一次简单的数据转换中被困了一段时间,我希望蜂巢的头脑可以提供帮助。

假设我有一个用于机器学习的Python Pandas数据框,如下所示:

>> trainingDF.ix[0:3,'temp']

Index                   temp
2011-01-01 00:00:00     9.84
2011-01-01 01:00:00     9.02
2011-01-01 02:00:00     9.02

我们看到索引是一个pandas数据时间序列,而奇异数据列是温度。

我想在此数据框中添加12个要素列,每个要素列指示样本(例如行)是否为给定月份。换句话说,它应该如下所示:

Index                   temp     isJan isFeb isMar isApr isMay etc.
2011-01-01 00:00:00     9.84     1     0     0     0     0     etc.
2011-01-01 01:00:00     9.02     1     0     0     0     0     etc.
2011-01-01 02:00:00     9.02     1     0     0     0     0     etc.

不幸的是,尽管有许多不同的尝试,我似乎无法确定一种优雅的方法来实现这一目标。

任何指针都会非常感激。

1 个答案:

答案 0 :(得分:6)

您可以使用get_dummies来完成艰苦的工作。像

这样的东西
target = pd.DataFrame(0, index=df.index, columns=range(1,13))
dm = pd.get_dummies(df.index.month).set_index(df.index)
target = (target + dm).fillna(0)
target.columns = ['is'+x.capitalize() for x in pd.datetools.MONTHS]
pd.concat([df, target], axis=1)

产生

                temp  isJan  isFeb  isMar  isApr  isMay  isJun  isJul  isAug  \
2011-01-01  0.419860      1      0      0      0      0      0      0      0   
2011-03-22  0.479502      0      0      1      0      0      0      0      0   
2011-06-10  0.687352      0      0      0      0      0      1      0      0   
2011-08-29  0.377993      0      0      0      0      0      0      0      1   
2011-11-17  0.877410      0      0      0      0      0      0      0      0   

            isSep  isOct  isNov  isDec  
2011-01-01      0      0      0      0  
2011-03-22      0      0      0      0  
2011-06-10      0      0      0      0  
2011-08-29      0      0      0      0  
2011-11-17      0      0      1      0  

接下来是一些解释。

首先,让我们制作一个测试框架:

>>> index = pd.date_range("2011-01-01", periods=5, freq="80d")
>>> df = pd.DataFrame({"temp": np.random.random(5)}, index=index)
>>> df
                temp
2011-01-01  0.566277
2011-03-22  0.965421
2011-06-10  0.854030
2011-08-29  0.780752
2011-11-17  0.148783

现在让我们制作出符合我们想要的东西(我们不应该假设我们每个月都会看到,毕竟;我们的测试示例只有5个月的非零值):

>>> target = pd.DataFrame(0, index=df.index, columns=range(1,13))
>>> target
            1   2   3   4   5   6   7   8   9   10  11  12
2011-01-01   0   0   0   0   0   0   0   0   0   0   0   0
2011-03-22   0   0   0   0   0   0   0   0   0   0   0   0
2011-06-10   0   0   0   0   0   0   0   0   0   0   0   0
2011-08-29   0   0   0   0   0   0   0   0   0   0   0   0
2011-11-17   0   0   0   0   0   0   0   0   0   0   0   0

get_dummies将生成一个指标矩阵:

>>> dm = pd.get_dummies(df.index.month).set_index(df.index)
>>> dm
            1   3   6   8   11
2011-01-01   1   0   0   0   0
2011-03-22   0   1   0   0   0
2011-06-10   0   0   1   0   0
2011-08-29   0   0   0   1   0
2011-11-17   0   0   0   0   1

(现在你可以看到为什么我们想在某个地方找到缺少的列。)我们可以将这两个列加在一起:

>>> target = (target + dm).fillna(0)
>>> target
            1   2   3   4   5   6   7   8   9   10  11  12
2011-01-01   1   0   0   0   0   0   0   0   0   0   0   0
2011-03-22   0   0   1   0   0   0   0   0   0   0   0   0
2011-06-10   0   0   0   0   0   1   0   0   0   0   0   0
2011-08-29   0   0   0   0   0   0   0   1   0   0   0   0
2011-11-17   0   0   0   0   0   0   0   0   0   0   1   0

除了让它看起来漂亮外,我们都完成了。有很多方法可以获得月份名称;让我们随机选择一个:

>>> pd.datetools.MONTHS
['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
>>> target.columns = ['is'+x.capitalize() for x in pd.datetools.MONTHS]

现在这些列按照您的意愿命名。剩下的就是结合一切:

>>> pd.concat([df, target], axis=1)
                temp  isJan  isFeb  isMar  isApr  isMay  isJun  isJul  isAug  \
2011-01-01  0.566277      1      0      0      0      0      0      0      0   
2011-03-22  0.965421      0      0      1      0      0      0      0      0   
2011-06-10  0.854030      0      0      0      0      0      1      0      0   
2011-08-29  0.780752      0      0      0      0      0      0      0      1   
2011-11-17  0.148783      0      0      0      0      0      0      0      0   

            isSep  isOct  isNov  isDec  
2011-01-01      0      0      0      0  
2011-03-22      0      0      0      0  
2011-06-10      0      0      0      0  
2011-08-29      0      0      0      0  
2011-11-17      0      0      1      0