• 52_Pandas处理日期和时间列(字符串转换、日期提取等)


    52_Pandas处理日期和时间列(字符串转换、日期提取等)

    将解释如何操作表示 pandas.DataFrame 的日期和时间(日期和时间)的列。字符串与 datetime64[ns] 类型的相互转换,将日期和时间提取为数字的方法等。

    以下内容进行说明。

    将字符串转换为 datetime64[ns] 类型(时间戳类型):to_datetime()

    时间戳类型属性/方法

    使用 dt 访问器批量处理整个列

    提取日期、星期几等。

    将日期时间转换为任何格式的字符串

    转换为 Python 数据帧类型,NumPy datetime64[ns] 类型数组

    对于 dt 中未提供的方法

    对于日期时间索引

    从文件读取时将字符串转换为 datetime64[ns] 类型

    如何将 datetime64[ns] 类型指定为索引并将其处理为时序数据以及如何使用,请参考以下文章。

    以带有以下 csv 文件的 pandas.DataFrame 为例。

    import pandas as pd
    import datetime
    
    df = pd.read_csv('./data/sample_datetime_multi.csv')
    
    print(df)
    #                  A                   B
    #0  2017-11-01 12:24   2017年11月1日 12时24分
    #1  2017-11-18 23:00  2017年11月18日 23时00分
    #2   2017-12-05 5:05    2017年12月5日 5时05分
    #3   2017-12-22 8:54   2017年12月22日 8时54分
    #4  2018-01-08 14:20    2018年1月8日 14时20分
    #5  2018-01-19 20:01   2018年1月19日 20时01分
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    将字符串转换为 datetime64[ns] 类型(时间戳类型):to_datetime()

    使用 pandas.to_datetime() 函数,您可以将表示日期和时间的字符串列 pandas.Series 转换为 datetime64[ns] 类型。

    print(pd.to_datetime(df['A']))
    # 0   2017-11-01 12:24:00
    # 1   2017-11-18 23:00:00
    # 2   2017-12-05 05:05:00
    # 3   2017-12-22 08:54:00
    # 4   2018-01-08 14:20:00
    # 5   2018-01-19 20:01:00
    # Name: A, dtype: datetime64[ns]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果格式不标准,请在参数格式中指定格式字符串。

    print(pd.to_datetime(df['B'], format='%Y年%m月%d日 %H时%M分'))
    # 0   2017-11-01 12:24:00
    # 1   2017-11-18 23:00:00
    # 2   2017-12-05 05:05:00
    # 3   2017-12-22 08:54:00
    # 4   2018-01-08 14:20:00
    # 5   2018-01-19 20:01:00
    # Name: B, dtype: datetime64[ns]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    即使原始格式不同,如果指示的日期和时间相同,则 datetime64[ns] 类型值是等价的。

    print(pd.to_datetime(df['A']) == pd.to_datetime(df['B'], format='%Y年%m月%d日 %H时%M分'))
    # 0    True
    # 1    True
    # 2    True
    # 3    True
    # 4    True
    # 5    True
    # dtype: bool
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果要将转换为 datetime64[ns] 类型的列作为新列添加到 pandas.DataFrame,请指定新列名并分配它。如果您指定原始列名,它将被覆盖。

    df['X'] = pd.to_datetime(df['A'])
    
    print(df)
    #                   A                   B                   X
    #0  2017-11-01 12:24   2017年11月1日 12时24分 2017-11-01 12:24:00
    #1  2017-11-18 23:00  2017年11月18日 23时00分 2017-11-18 23:00:00
    #2   2017-12-05 5:05    2017年12月5日 5时05分 2017-12-05 05:05:00
    #3   2017-12-22 8:54   2017年12月22日 8时54分 2017-12-22 08:54:00
    #4  2018-01-08 14:20    2018年1月8日 14时20分 2018-01-08 14:20:00
    #5  2018-01-19 20:01   2018年1月19日 20时01分 2018-01-19 20:01:00
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    时间戳类型属性/方法

    pandas.to_datetime() 函数转换的列的dtype是datetime64[ns]类型,每个元素都是Timestamp类型。

    print(df)
    #                   A                   B                   X
    # 0  2017-11-01 12:24   2017年11月1日 12时24分 2017-11-01 12:24:00
    # 1  2017-11-18 23:00  2017年11月18日 23时00分 2017-11-18 23:00:00
    # 2   2017-12-05 5:05    2017年12月5日 5时05分 2017-12-05 05:05:00
    # 3   2017-12-22 8:54   2017年12月22日 8时54分 2017-12-22 08:54:00
    # 4  2018-01-08 14:20    2018年1月8日 14时20分 2018-01-08 14:20:00
    # 5  2018-01-19 20:01   2018年1月19日 20时01分 2018-01-19 20:01:00
    
    print(df.dtypes)
    # A            object
    # B            object
    # X    datetime64[ns]
    # dtype: object
    
    print(df['X'][0])
    # 2017-11-01 12:24:00
    
    print(type(df['X'][0]))
    # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Timestamp 类型继承并扩展了 Python 标准库 datetime 的 datetime 类型。

    print(issubclass(pd.Timestamp, datetime.datetime))
    # True
    
    • 1
    • 2

    可以获取年、月、日(年、月、日)、时、分、秒(时、分、秒)、星期几(字符串:weekday_name,数字:dayofweek)等作为属性。

    print(df['X'][0].year)
    # 2017
    
    print(df['X'][0].weekday_name)
    # Wednesday
    
    • 1
    • 2
    • 3
    • 4
    • 5

    还可以使用 to_pydatetime() 转换为 Python 标准库 datetime 类型,使用 to_datetime64() 转换为 NumPy datetime64[ns] 类型。

    py_dt = df['X'][0].to_pydatetime()
    print(type(py_dt))
    # 
    
    dt64 = df['X'][0].to_datetime64()
    print(type(dt64))
    # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    timestamp() 是一种以浮点浮点类型返回 UNIX 时间(纪元秒 = 自 1970 年 1 月 1 日 00:00:00 以来的秒数)的方法。如果需要整数,请使用 int()。

    print(df['X'][0].timestamp())
    # 1509539040.0
    
    print(pd.to_datetime('1970-01-01 00:00:00').timestamp())
    # 0.0
    
    print(int(df['X'][0].timestamp()))
    # 1509539040
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    与 Python 标准库中的 datetime 类型一样,strftime() 可用于转换为任何格式的字符串。请参阅下文,了解如何将其应用于列的所有元素。

    print(df['X'][0].strftime('%Y/%m/%d'))
    # 2017/11/01
    
    • 1
    • 2

    使用 dt 访问器批量处理整个列

    有一个 str 访问器将字符串处理应用于整个 pandas.Series。

    提取日期、星期几。

    与Timestamp类型一样,年、月、日(年、月、日)、时、分、秒(时、分、秒)、星期几(字符串:weekday_name,数字:dayofweek)等都可以作为属性获得。 在 dt 之后写下每个属性名称。 pandas.Series 的每个元素都被处理并返回 pandas.Series。

    print(df['X'].dt.year)
    # 0    2017
    # 1    2017
    # 2    2017
    # 3    2017
    # 4    2018
    # 5    2018
    # Name: X, dtype: int64
    
    print(df['X'].dt.hour)
    # 0    12
    # 1    23
    # 2     5
    # 3     8
    # 4    14
    # 5    20
    # Name: X, dtype: int64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    也可以使用 dayofweek(星期一为 0,星期日为 6)仅提取一周中特定日期的行。

    print(df['X'].dt.dayofweek)
    # 0    2
    # 1    5
    # 2    1
    # 3    4
    # 4    0
    # 5    4
    # Name: X, dtype: int64
    
    print(df[df['X'].dt.dayofweek == 4])
    #                   A                  B                   X
    # 3   2017-12-22 8:54  2017年12月22日 8时54分 2017-12-22 08:54:00
    # 5  2018-01-19 20:01  2018年1月19日 20时01分 2018-01-19 20:01:00
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    将日期时间转换为任何格式的字符串

    当使用 astype() 方法将 datetime64[ns] 类型的列转换为字符串 str 类型时,它会转换为标准格式的字符串。

    print(df['X'].astype(str))
    # 0    2017-11-01 12:24:00
    # 1    2017-11-18 23:00:00
    # 2    2017-12-05 05:05:00
    # 3    2017-12-22 08:54:00
    # 4    2018-01-08 14:20:00
    # 5    2018-01-19 20:01:00
    # Name: X, dtype: object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    dt.strftime() 可用于一次将列转换为任何格式的字符串。也可以使其成为仅具有日期或仅具有时间的字符串。

    print(df['X'].dt.strftime('%A, %B %d, %Y'))
    # 0    Wednesday, November 01, 2017
    # 1     Saturday, November 18, 2017
    # 2      Tuesday, December 05, 2017
    # 3       Friday, December 22, 2017
    # 4        Monday, January 08, 2018
    # 5        Friday, January 19, 2018
    # Name: X, dtype: object
    
    print(df['X'].dt.strftime('%Y年%m月%d日'))
    # 0    2017年11月01日
    # 1    2017年11月18日
    # 2    2017年12月05日
    # 3    2017年12月22日
    # 4    2018年01月08日
    # 5    2018年01月19日
    # Name: X, dtype: object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    如果要将转换为字符串的列作为新列添加到 pandas.DataFrame,请指定新列名并分配它。如果您指定原始列名,它将被覆盖。

    df['en'] = df['X'].dt.strftime('%A, %B %d, %Y')
    df['cn'] = df['X'].dt.strftime('%Y年%m月%d日')
    
    print(df)
    #                   A                   B                   X  \
    # 0  2017-11-01 12:24   2017年11月1日 12时24分 2017-11-01 12:24:00   
    # 1  2017-11-18 23:00  2017年11月18日 23时00分 2017-11-18 23:00:00   
    # 2   2017-12-05 5:05    2017年12月5日 5时05分 2017-12-05 05:05:00   
    # 3   2017-12-22 8:54   2017年12月22日 8时54分 2017-12-22 08:54:00   
    # 4  2018-01-08 14:20    2018年1月8日 14时20分 2018-01-08 14:20:00   
    # 5  2018-01-19 20:01   2018年1月19日 20时01分 2018-01-19 20:01:00   
    #                              en           cn
    # 0  Wednesday, November 01, 2017  2017年11月01日  
    # 1   Saturday, November 18, 2017  2017年11月18日  
    # 2    Tuesday, December 05, 2017  2017年12月05日  
    # 3     Friday, December 22, 2017  2017年12月22日  
    # 4      Monday, January 08, 2018  2018年01月08日  
    # 5      Friday, January 19, 2018  2018年01月19日  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    转换为 Python 数据帧类型,NumPy datetime64[ns] 类型数组

    可以使用 dt.to_pydatetime() 获得一个 NumPy 数组 ndarray,其元素是 Python 标准库的日期时间类型对象。

    print(df['X'].dt.to_pydatetime())
    # [datetime.datetime(2017, 11, 1, 12, 24)
    #  datetime.datetime(2017, 11, 18, 23, 0)
    #  datetime.datetime(2017, 12, 5, 5, 5)
    #  datetime.datetime(2017, 12, 22, 8, 54)
    #  datetime.datetime(2018, 1, 8, 14, 20)
    #  datetime.datetime(2018, 1, 19, 20, 1)]
    
    print(type(df['X'].dt.to_pydatetime()))
    print(type(df['X'].dt.to_pydatetime()[0]))
    # 
    # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    NumPy的datetime64[ns]类型数组可以用values属性代替方法获取。

    print(df['X'].values)
    # ['2017-11-01T12:24:00.000000000' '2017-11-18T23:00:00.000000000'
    #  '2017-12-05T05:05:00.000000000' '2017-12-22T08:54:00.000000000'
    #  '2018-01-08T14:20:00.000000000' '2018-01-19T20:01:00.000000000']
    
    print(type(df['X'].values))
    print(type(df['X'].values[0]))
    # 
    # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    对于 dt 中未提供的方法

    例如,Timestamp 类型有一个返回 UNIX 时间(秒)的方法 (timestamp()),但 dt 访问器没有。在这种情况下,使用 map() 即可。

    print(df['X'].map(pd.Timestamp.timestamp))
    # 0    1.509539e+09
    # 1    1.511046e+09
    # 2    1.512450e+09
    # 3    1.513933e+09
    # 4    1.515421e+09
    # 5    1.516392e+09
    # Name: X, dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果要转换为整数 int 类型,请使用 astype() 方法。

    print(df['X'].map(pd.Timestamp.timestamp).astype(int))
    # 0    1509539040
    # 1    1511046000
    # 2    1512450300
    # 3    1513932840
    # 4    1515421200
    # 5    1516392060
    # Name: X, dtype: int64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    对于日期时间索引

    在处理时间序列数据时非常有用。有关详细信息,请参阅下面的文章。

    在示例中,set_index() 用于将现有列指定为索引,为方便起见,使用 drop() 方法删除多余的列。

    df_i = df.set_index('X').drop(['en', 'cn'], axis=1)
    
    print(df_i)
    #                                     A                   B
    # X                                                        
    # 2017-11-01 12:24:00  2017-11-01 12:24   2017年11月1日 12时24分
    # 2017-11-18 23:00:00  2017-11-18 23:00  2017年11月18日 23时00分
    # 2017-12-05 05:05:00   2017-12-05 5:05    2017年12月5日 5时05分
    # 2017-12-22 08:54:00   2017-12-22 8:54   2017年12月22日 8时54分
    # 2018-01-08 14:20:00  2018-01-08 14:20    2018年1月8日 14时20分
    # 2018-01-19 20:01:00  2018-01-19 20:01   2018年1月19日 20时01分
    
    print(df_i.index)
    # DatetimeIndex(['2017-11-01 12:24:00', '2017-11-18 23:00:00',
    #                '2017-12-05 05:05:00', '2017-12-22 08:54:00',
    #                '2018-01-08 14:20:00', '2018-01-19 20:01:00'],
    #               dtype='datetime64[ns]', name='X', freq=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    DatetimeIndex 类型索引具有年、月、日(年、月、日)、时、分、秒(时、分、秒)、星期几(字符串:weekday_name,数字:dayofweek)等属性,以及方法如由于提供了 strftime(),因此可以一次处理所有索引元素,而无需通过 dt 属性。

    返回类型因属性和方法而异,不是pandas.Series,但如果要在pandas.DataFrame中添加新列,可以指定新列名并分配。

    print(df_i.index.minute)
    # Int64Index([24, 0, 5, 54, 20, 1], dtype='int64', name='X')
    
    print(df_i.index.strftime('%y/%m/%d'))
    # ['17/11/01' '17/11/18' '17/12/05' '17/12/22' '18/01/08' '18/01/19']
    
    df_i['min'] = df_i.index.minute
    df_i['str'] = df_i.index.strftime('%y/%m/%d')
    
    print(df_i)
    #                                     A                   B  min       str
    # X
    # 2017-11-01 12:24:00  2017-11-01 12:24   2017年11月1日 12时24分   24  17/11/01
    # 2017-11-18 23:00:00  2017-11-18 23:00  2017年11月18日 23时00分    0  17/11/18
    # 2017-12-05 05:05:00   2017-12-05 5:05    2017年12月5日 5时05分    5  17/12/05
    # 2017-12-22 08:54:00   2017-12-22 8:54   2017年12月22日 8时54分   54  17/12/22
    # 2018-01-08 14:20:00  2018-01-08 14:20    2018年1月8日 14时20分   20  18/01/08
    # 2018-01-19 20:01:00  2018-01-19 20:01   2018年1月19日 20时01分    1  18/01/19
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    从文件读取时将字符串转换为 datetime64[ns] 类型

    从文件中读取数据时,可以在读取时将字符串转换为 datetime64[ns] 类型。 对于 pandas.read_csv() 函数,在参数 parse_dates 中指定要转换为 datetime64[ns] 类型的列号列表。请注意,即使只有一个,也必须列出。

    df_csv = pd.read_csv('data/sample_datetime_multi.csv', parse_dates=[0])
    
    print(df_csv)
    #                     A                   B
    # 0 2017-11-01 12:24:00   2017年11月1日 12时24分
    # 1 2017-11-18 23:00:00  2017年11月18日 23时00分
    # 2 2017-12-05 05:05:00    2017年12月5日 5时05分
    # 3 2017-12-22 08:54:00   2017年12月22日 8时54分
    # 4 2018-01-08 14:20:00    2018年1月8日 14时20分
    # 5 2018-01-19 20:01:00   2018年1月19日 20时01分
    
    print(df_csv.dtypes)
    # A    datetime64[ns]
    # B            object
    # dtype: object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    df_csv_jp = pd.read_csv('./data/sample_datetime_multi.csv',
                            parse_dates=[1],
                            date_parser=lambda date: pd.to_datetime(date, format='%Y年%m月%d日 %H时%M分'))
    
    print(df_csv_jp)
    #                   A                   B
    # 0  2017-11-01 12:24 2017-11-01 12:24:00
    # 1  2017-11-18 23:00 2017-11-18 23:00:00
    # 2   2017-12-05 5:05 2017-12-05 05:05:00
    # 3   2017-12-22 8:54 2017-12-22 08:54:00
    # 4  2018-01-08 14:20 2018-01-08 14:20:00
    # 5  2018-01-19 20:01 2018-01-19 20:01:00
    
    print(df_csv_jp.dtypes)
    # A            object
    # B    datetime64[ns]
    # dtype: object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    可以使用参数 index_col 指定要索引的列。

    在这种情况下,如果参数 parse_dates=True,索引列将被转换为 datetime64[ns] 类型。

    df_csv_jp_i = pd.read_csv('./data/sample_datetime_multi.csv',
                              index_col=1,
                              parse_dates=True,
                              date_parser=lambda date: pd.to_datetime(date, format='%Y年%m月%d日 %H时%M分'))
    
    print(df_csv_jp_i)
    #                                     A
    # B                                    
    # 2017-11-01 12:24:00  2017-11-01 12:24
    # 2017-11-18 23:00:00  2017-11-18 23:00
    # 2017-12-05 05:05:00   2017-12-05 5:05
    # 2017-12-22 08:54:00   2017-12-22 8:54
    # 2018-01-08 14:20:00  2018-01-08 14:20
    # 2018-01-19 20:01:00  2018-01-19 20:01
    
    print(df_csv_jp_i.index)
    # DatetimeIndex(['2017-11-01 12:24:00', '2017-11-18 23:00:00',
    #                '2017-12-05 05:05:00', '2017-12-22 08:54:00',
    #                '2018-01-08 14:20:00', '2018-01-19 20:01:00'],
    #               dtype='datetime64[ns]', name='B', freq=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    读取 Excel 文件的 pandas.read_excel() 函数也有参数 parse_dates、date_parser 和 index_col,因此在读取时也可以进行类似的转换。有关 pandas.read_excel() 函数的信息,请参阅以下文章。

  • 相关阅读:
    如何读取照片的GPS信息?—最好的语言Java实现起来就这么简单【手把手教程+完整代码】
    看完这篇 教你玩转渗透测试靶机Vulnhub——Hacksudo: Aliens
    (附源码)ssm产品裂变管理系统 毕业设计 100953
    课程:如何高效掌控你的时间
    Spring常见问题解决 - 自定义ApplicationEnvironmentPreparedEvent监听器失效了?
    Android Studio Gradle插件版本与Gradle 版本对应关系
    http2分片流内容整合呈现方法
    软件耦合的分类及解决方法
    在达梦数据库上使用密码设备上的国密算法详细操作指南
    linux 中的根文件系统
  • 原文地址:https://blog.csdn.net/qq_18351157/article/details/127703926