Pandas数据框 - 如何将日期转换为布尔列?

0 投票
1 回答
879 浏览
提问于 2025-04-18 18:19

我在一个简单的数据转换上卡了很久,希望大家能帮帮我。

假设我有一个用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 个回答

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  

撰写回答