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 个回答
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