Pandas read_csv:正确解析时间字段
Posted
技术标签:
【中文标题】Pandas read_csv:正确解析时间字段【英文标题】:Pandas read_csv: parsing time field correctly 【发布时间】:2016-04-27 00:36:16 【问题描述】:我有以下原始数据,
TranID,TranDate,TranTime,TranAmt
A123456,20160427,02:18,9999.53
B123457,20160426,02:48,26070.33
C123458,20160425,03:18,13779.56
A123459,20160424,03:18,18157.26
B123460,20160423,04:18,215868.15
C123461,20160422,04:18,23695.25
A123462,20160421,05:18,57
B123463,20160420,05:18,64594.24
C123464,20160419,06:18,47890.91
A123465,20160427,06:18,14119.74
B123466,20160426,07:18,2649.6
C123467,20160425,07:18,16757.38
A123468,20160424,08:18,8864.78
B123469,20160423,08:18,26254.69
C123470,20160422,09:18,13206.98
A123471,20160421,09:18,15872.45
B123472,20160420,10:18,197621.18
C123473,20160419,10:18,21048.72
我尝试使用 pd read_csv 导入原始数据,
试试1
import numpy as np
import pandas as pd
df = pd.read_csv('MyTest.csv', sep=',', header=0, parse_dates=['TranDate'],
usecols=['TranID','TranDate','TranTime','TranAmt'],
engine='python')
print(df.dtypes)
df[:5]
输出1
TranID object
TranDate datetime64[ns]
TranTime object
TranAmt float64
dtype: object
Out[12]:
TranID TranDate TranTime TranAmt
0 A123456 2016-04-27 02:18 9999.53
1 B123457 2016-04-26 02:48 26070.33
2 C123458 2016-04-25 03:18 13779.56
3 A123459 2016-04-24 03:18 18157.26
4 B123460 2016-04-23 04:18 215868.15
试试2
import numpy as np
import pandas as pd
df = pd.read_csv('MyTest.csv', sep=',', header=0, parse_dates=['TranDate', 'TranTime'],
usecols=['TranID','TranDate','TranTime','TranAmt'],
engine='python')
print(df.dtypes)
df[:5]
输出2
TranID object
TranDate datetime64[ns]
TranTime datetime64[ns]
TranAmt float64
dtype: object
Out[13]:
TranID TranDate TranTime TranAmt
0 A123456 2016-04-27 2016-04-27 02:18:00 9999.53
1 B123457 2016-04-26 2016-04-27 02:48:00 26070.33
2 C123458 2016-04-25 2016-04-27 03:18:00 13779.56
3 A123459 2016-04-24 2016-04-27 03:18:00 18157.26
4 B123460 2016-04-23 2016-04-27 04:18:00 215868.15
我对 TranTime 专栏感到困惑。在 Try1 中,它显示正确,但 dtype 是对象。在 Try2 中,pd 将当前日期添加到时间,dtype 为 datetime。
我希望将此 TranTime 列视为 Time,并希望使用 pd 的 groupby 或 pivot_table 执行聚合。 如果我使用 Try1 方法,对象 dtype 会影响我的聚合吗? 如果我使用 Try2 方法,是否需要去掉 Date 部分才能使用 Time 部分?
我精通 SAS,其中 SAS 具有日期、时间和日期时间信息以及基础数据类型只是数字的格式。因此我对 Python 的 object 和 datetime dtypes 感到困惑。
谢谢, 大厅
【问题讨论】:
【参考方案1】:在 Python 中,日期时间通常表示为 datetime.datetime 对象。这些不是很有效,这就是 Pandas 使用数字时间戳的原因。
读取数据(注意parse_dates
参数周围的双括号):
df = pd.read_csv(filename, parse_dates=[['TranDate', 'TranTime']])
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 18 entries, 0 to 17
Data columns (total 3 columns):
TranDate_TranTime 18 non-null datetime64[ns]
TranID 18 non-null object
TranAmt 18 non-null float64
dtypes: datetime64[ns](1), float64(1), object(1)
>>> df.head()
TranDate_TranTime TranID TranAmt
0 2016-04-27 02:18:00 A123456 9999.53
1 2016-04-26 02:48:00 B123457 26070.33
2 2016-04-25 03:18:00 C123458 13779.56
3 2016-04-24 03:18:00 A123459 18157.26
4 2016-04-23 04:18:00 B123460 215868.15
日期和时间列仅连接到一列。一旦你有了这个时间戳,就很容易使用dt
访问器访问它的属性,例如
>>> df.groupby(df.TranDate_TranTime.dt.hour).TranAmt.sum().head()
TranDate_TranTime
2 36069.86
3 31936.82
4 239563.40
5 64651.24
6 62010.65
Name: TranAmt, dtype: float64
>>> df.groupby(df.TranDate_TranTime.dt.day).TranAmt.sum().head()
TranDate_TranTime
19 68939.63
20 262215.42
21 15929.45
22 36902.23
23 242122.84
Name: TranAmt, dtype: float64
有关 Pandas date functionality 的更多信息,请参阅 Pandas 文档。
【讨论】:
非常感谢您的详细回答。一切都好,我今天学到了一些新东西。问候,大堂【参考方案2】:没有聚合影响,但你会失去时间部分。 不,大部分时间你可以通过
.dt
accessor访问时间部分。
import pandas as pd
df = pd.read_csv('MyTest.csv', parse_dates=[['TranDate', 'TranTime']])
print df
TranDate_TranTime TranID TranAmt
0 2016-04-27 02:18:00 A123456 9999.53
1 2016-04-26 02:48:00 B123457 26070.33
2 2016-04-25 03:18:00 C123458 13779.56
3 2016-04-24 03:18:00 A123459 18157.26
4 2016-04-23 04:18:00 B123460 215868.15
5 2016-04-22 04:18:00 C123461 23695.25
6 2016-04-21 05:18:00 A123462 57.00
7 2016-04-20 05:18:00 B123463 64594.24
8 2016-04-19 06:18:00 C123464 47890.91
9 2016-04-27 06:18:00 A123465 14119.74
10 2016-04-26 07:18:00 B123466 2649.60
11 2016-04-25 07:18:00 C123467 16757.38
12 2016-04-24 08:18:00 A123468 8864.78
13 2016-04-23 08:18:00 B123469 26254.69
14 2016-04-22 09:18:00 C123470 13206.98
15 2016-04-21 09:18:00 A123471 15872.45
16 2016-04-20 10:18:00 B123472 197621.18
17 2016-04-19 10:18:00 C123473 21048.72
使用嵌套括号parse_dates=[[]]
,尽可能将日期/时间作为一列进行解析和管理。
print df.groupby(df.TranDate_TranTime.dt.hour).sum()
TranAmt
2 36069.86
3 31936.82
4 239563.40
5 64651.24
6 62010.65
7 19406.98
8 35119.47
9 29079.43
10 218669.90
print df.groupby(df.TranDate_TranTime.dt.minute).sum()
TranAmt
18 710437.42
48 26070.33
像上面那样得到你想要的。
你仍然可以在resampling 之后进行分组,如下所示。
df2 = df.set_index('TranDate_TranTime').resample('60s').sum().dropna()
print df2
TranAmt
TranDate_TranTime
2016-04-19 06:18:00 47890.91
2016-04-19 10:18:00 21048.72
2016-04-20 05:18:00 64594.24
2016-04-20 10:18:00 197621.18
2016-04-21 05:18:00 57.00
2016-04-21 09:18:00 15872.45
2016-04-22 04:18:00 23695.25
2016-04-22 09:18:00 13206.98
2016-04-23 04:18:00 215868.15
2016-04-23 08:18:00 26254.69
2016-04-24 03:18:00 18157.26
2016-04-24 08:18:00 8864.78
2016-04-25 03:18:00 13779.56
2016-04-25 07:18:00 16757.38
2016-04-26 02:48:00 26070.33
2016-04-26 07:18:00 2649.60
2016-04-27 02:18:00 9999.53
2016-04-27 06:18:00 14119.74
print df2.groupby(df2.index.day).sum()
TranAmt
19 68939.63
20 262215.42
21 15929.45
22 36902.23
23 242122.84
24 27022.04
25 30536.94
26 28719.93
27 24119.27
【讨论】:
您好,但是如果我想按 TranTime 分组并对 TranAmt 求和,我不能按照您的建议执行此操作吗?谢谢。 @Lobbie 你仍然可以像上面编辑的代码一样分组。 您好,感谢您的帮助。 Alexander 还展示了使用 dt.accessor。问候,大堂以上是关于Pandas read_csv:正确解析时间字段的主要内容,如果未能解决你的问题,请参考以下文章
pandas read_csv 和使用 usecols 过滤列
pandas.read_csv 不在分号分隔符处对数据进行分区
pandas使用read_csv函数读取文件并解析日期数据列(parse dates)pandas使用read_csv函数读取文件并将缺失值转化为空字符串
为 pandas.read_csv 指定正确的 dtypes 以获取日期时间和布尔值