使用pandas合并日期和时间列

206

我有一个带有以下列的pandas数据框:

data = {'Date': ['01-06-2013', '02-06-2013', '02-06-2013', '02-06-2013', '02-06-2013', '03-06-2013', '03-06-2013', '03-06-2013', '03-06-2013', '04-06-2013'],
        'Time': ['23:00:00', '01:00:00', '21:00:00', '22:00:00', '23:00:00', '01:00:00', '21:00:00', '22:00:00', '23:00:00', '01:00:00']}
df = pd.DataFrame(data)

         Date      Time
0  01-06-2013  23:00:00
1  02-06-2013  01:00:00
2  02-06-2013  21:00:00
3  02-06-2013  22:00:00
4  02-06-2013  23:00:00
5  03-06-2013  01:00:00
6  03-06-2013  21:00:00
7  03-06-2013  22:00:00
8  03-06-2013  23:00:00
9  04-06-2013  01:00:00

我该如何将data['Date'] 和 data['Time'] 结合起来以获得以下结果?是否可以使用 pd.to_datetime 实现?

Date
01-06-2013 23:00:00
02-06-2013 01:00:00
02-06-2013 21:00:00
02-06-2013 22:00:00
02-06-2013 23:00:00
03-06-2013 01:00:00
03-06-2013 21:00:00
03-06-2013 22:00:00
03-06-2013 23:00:00
04-06-2013 01:00:00
13个回答

291

值得一提的是,你可能已经可以直接阅读这个内容,例如如果你正在使用read_csv, 并使用parse_dates=[['Date', 'Time']]

假设这些只是字符串,你可以简单地将它们加在一起(用空格分隔),这样就可以使用to_datetime,而无需指定format=参数。

In [11]: df['Date'] + ' ' + df['Time']
Out[11]:
0    01-06-2013 23:00:00
1    02-06-2013 01:00:00
2    02-06-2013 21:00:00
3    02-06-2013 22:00:00
4    02-06-2013 23:00:00
5    03-06-2013 01:00:00
6    03-06-2013 21:00:00
7    03-06-2013 22:00:00
8    03-06-2013 23:00:00
9    04-06-2013 01:00:00
dtype: object

In [12]: pd.to_datetime(df['Date'] + ' ' + df['Time'])
Out[12]:
0   2013-01-06 23:00:00
1   2013-02-06 01:00:00
2   2013-02-06 21:00:00
3   2013-02-06 22:00:00
4   2013-02-06 23:00:00
5   2013-03-06 01:00:00
6   2013-03-06 21:00:00
7   2013-03-06 22:00:00
8   2013-03-06 23:00:00
9   2013-04-06 01:00:00
dtype: datetime64[ns]

或者,不使用+ ' ',而是必须使用format=参数。此外,Pandas很擅长推断要转换为datetime的格式,但指定确切的格式会更快。

pd.to_datetime(df['Date'] + df['Time'], format='%m-%d-%Y%H:%M:%S')

注意:出人意料的是,这对将NaN转换为NaT效果很好,但值得担心的是,转换时可能会使用raise参数。

%%timeit

# sample dataframe with 10000000 rows using df from the OP
df = pd.concat([df for _ in range(1000000)]).reset_index(drop=True)

%%timeit
pd.to_datetime(df['Date'] + ' ' + df['Time'])
[result]:
1.73 s ± 10.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
pd.to_datetime(df['Date'] + df['Time'], format='%m-%d-%Y%H:%M:%S')
[result]:
1.33 s ± 9.88 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

62

被接受的答案适用于数据类型为 string 的列。为了完整起见:当列的数据类型是日期和时间时,我在搜索如何执行此操作时遇到了这个问题。

df.apply(lambda r : pd.datetime.combine(r['date_column_name'],r['time_column_name']),1)

2
我在pandas中找不到关于“time”数据类型的任何信息。我有一个“timedelta”(和一个“datetime”),在这种情况下,您只需要将它们相加,请参见我的答案 - toto_tico
当我使用'pd.read_excel'读取Excel中被标识为“时间”的列时,pandas会自动将其识别为“时间”,无需任何解析参数。感谢这个解决方案。+1 - Saeed
6
注意,从pandas 1.0.0开始,pd.datetime已经被弃用(详见此链接),建议直接显式导入datetime模块。 - CopOnTheRun
这种方法对于大型数据集来说太慢了。更快的方法是将两列转换为字符串,连接它们并使用 to_datetime - Mykola Zotko

38

如果类型不同(datetimetimestampstr),请转换列并使用to_datetime

df.loc[:,'Date'] = pd.to_datetime(df.Date.astype(str)+' '+df.Time.astype(str))

结果:

0   2013-01-06 23:00:00
1   2013-02-06 01:00:00
2   2013-02-06 21:00:00
3   2013-02-06 22:00:00
4   2013-02-06 23:00:00
5   2013-03-06 01:00:00
6   2013-03-06 21:00:00
7   2013-03-06 22:00:00
8   2013-03-06 23:00:00
9   2013-04-06 01:00:00

最好的祝福,


这是我能找到的唯一与Python datetime模块类型兼容的选项。但现在我已经将这个报告转换为datetime64[ns],这会导致其他地方出现混合类型,这绝不是一个好事情。 - xtian
1
被接受的答案相比,此选项效率较低,因为这两列已经是字符串。因此,使用.astype(str)是不必要的(鉴于OP)。此外,df['Date'] =就足够了;不需要.loc(例如,df.loc[:,'Date'] =)。 - Trenton McKinney

22
您可以使用此方法将日期和时间合并到数据框的同一列中。
import pandas as pd    
data_file = 'data.csv' #path of your file

使用合并列Date_Time读取.csv文件:

data = pd.read_csv(data_file, parse_dates=[['Date', 'Time']]) 

你可以使用这行来保持其他两列不变。

data.set_index(['Date', 'Time'], drop=False)

1
你也可以使用自定义的 date_parser,例如 parser = lambda date: pd.datetime.strptime(date, '%d-%b-%y %H:%M:%S') - Serendipity

15
您还可以使用to_datetimeto_timedelta来进行转换为datetime,而无需使用字符串拼接。这两个函数分别创建datetimetimedelta对象。再加上pd.DataFrame.pop,您可以同时删除源Series。
df['DateTime'] = pd.to_datetime(df.pop('Date')) + pd.to_timedelta(df.pop('Time'))

print(df)

             DateTime
0 2013-01-06 23:00:00
1 2013-02-06 01:00:00
2 2013-02-06 21:00:00
3 2013-02-06 22:00:00
4 2013-02-06 23:00:00
5 2013-03-06 01:00:00
6 2013-03-06 21:00:00
7 2013-03-06 22:00:00
8 2013-03-06 23:00:00
9 2013-04-06 01:00:00

print(df.dtypes)

DateTime    datetime64[ns]
dtype: object

3
很棒的通用解决方案!我原本有一个datetime日期类型和一个str字符串类型的时间,使用这个方法很有效。 - sparrow
2
实际上,这比被接受的答案要快得多,特别是如果日期列已经是 pd.Timestamp 类型。 - L. Francis Cong

12

首先确保拥有正确的数据类型:

df["Date"] = pd.to_datetime(df["Date"])
df["Time"] = pd.to_timedelta(df["Time"])

然后您可以轻松地将它们组合起来:

df["DateTime"] = df["Date"] + df["Time"]

12

我声望不够,在jka.ne的页面上无法进行评论,所以:

为了让它起作用,我必须修改jka.ne的代码

df.apply(lambda r : pd.datetime.combine(r['date_column_name'],r['time_column_name']).time(),1)

这可能对其他人有所帮助。

此外,我尝试了另一种方法,使用replace而不是combine

def combine_date_time(df, datecol, timecol):
    return df.apply(lambda row: row[datecol].replace(
                                hour=row[timecol].hour,
                                minute=row[timecol].minute),
                    axis=1)
在OP的情况下,这将是:
combine_date_time(df, 'Date', 'Time')

我已经对一个相对较大的数据集(>500,000行)进行了两种方法的时间测试,它们的运行时间相似,但使用 combine 更快( replace 为59秒,而 combine 为50秒)。


6

答案取决于您的列类型是什么。在我的情况下,我有datetimetimedelta

> df[['Date','Time']].dtypes
Date     datetime64[ns]
Time    timedelta64[ns]

如果您遇到这种情况,您只需要添加列:
> df['Date'] + df['Time']

被接受的答案假设这些是字符串:*"假设这些只是字符串,你可以简单地将它们加在一起(用一个空格)"。* 我的答案是针对 datetimetimedelta 的。主要的答案不知何故确定了这些列是字符串,或者可能只是适用于发布问题的人的答案。 - toto_tico

4
使用combine函数:
datetime.datetime.combine(date, time)

4

这里是一行代码,可以实现此操作。你只需在每列中使用一个空格" "将两个字符串连接起来即可。

假设df是你的数据框(dataframe),列名分别为'Time'和'Date',那么你的新列名应该是DateAndTime。

df['DateAndTime'] = df['Date'].str.cat(df['Time'],sep=" ")

如果您还希望处理像日期时间对象之类的条目,您可以这样做。您可以根据自己的需求微调格式。

df['DateAndTime'] = pd.to_datetime(df['DateAndTime'], format="%m/%d/%Y %I:%M:%S %p")

干杯!!愉快的数据处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接