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】:
    没有聚合影响,但你会失去时间部分。 不,大部分时间你可以通过.dtaccessor访问时间部分。
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 以获取日期时间和布尔值

Python Pandas read_csv 函数不允许将解析日期更改为所需格式

Pandas read_csv 用字符串“nan”填充空值,而不是解析日期