【问题标题】:Pandas read_csv: parsing time field correctlyPandas read_csv:正确解析时间字段
【发布时间】: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 感到困惑。

谢谢, 大厅

【问题讨论】:

    标签: python pandas


    【解决方案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】:
    1. 没有聚合影响,但你会失去时间部分。
    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。问候,大堂
    猜你喜欢
    • 2021-10-02
    • 2017-07-19
    • 2017-03-06
    • 2023-03-17
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多