使用正则表达式有效地用pandas中另一列的值替换一列中的部分值?

时间:2018-05-29 11:29:39

标签: python pandas vectorization

我有一个pandas数据帧df,日期为字符串:

Date1        Date2
2017-08-31   1970-01-01 17:35:00
2017-10-31   1970-01-01 15:00:00
2017-11-30   1970-01-01 16:30:00
2017-10-31   1970-01-01 16:00:00
2017-10-31   1970-01-01 16:12:00

我想要做的是将Date2列中的每个日期部分替换为Date1中的相应日期,但保持时间不变,因此输出为:

Date1        Date2
2017-08-31   2017-08-31 17:35:00
2017-10-31   2017-10-31 15:00:00
2017-11-30   2017-11-30 16:30:00
2017-10-31   2017-10-31 16:00:00
2017-10-31   2017-10-31 16:12:00

我使用pandas replace和正则表达式

实现了这一目标
import re
date_reg = re.compile(r"([0-9]{4}\-[0-9]{2}\-[0-9]{2})")
df['Market Close Time'].replace(to_replace=date_reg, value=df['Date1'], inplace=True)

但对于只有150k行的数据帧,这种方法非常慢(> 10分钟)。

来自this post的解决方案实现了numpy np.where,速度要快得多 - 如何在此示例中使用np.where,还是有另一种更有效的方法来执行此操作?< / p>

2 个答案:

答案 0 :(得分:3)

一个想法是:

df['Date3'] =  ['{} {}'.format(a, b.split()[1]) for a, b in zip(df['Date1'], df['Date2'])]

或者:

df['Date3'] = df['Date1'] + ' ' + df['Date2'].str.split().str[1]
print (df)
        Date1                Date2                Date3
0  2017-08-31  1970-01-01 17:35:00  2017-08-31 17:35:00
1  2017-10-31  1970-01-01 15:00:00  2017-10-31 15:00:00
2  2017-11-30  1970-01-01 16:30:00  2017-11-30 16:30:00
3  2017-10-31  1970-01-01 16:00:00  2017-10-31 16:00:00
4  2017-10-31  1970-01-01 16:12:00  2017-10-31 16:12:00

或者:

df['Date3'] = pd.to_datetime(df['Date1']) + pd.to_timedelta(df['Date2'].str.split().str[1])
print (df)
        Date1                Date2               Date3
0  2017-08-31  1970-01-01 17:35:00 2017-08-31 17:35:00
1  2017-10-31  1970-01-01 15:00:00 2017-10-31 15:00:00
2  2017-11-30  1970-01-01 16:30:00 2017-11-30 16:30:00
3  2017-10-31  1970-01-01 16:00:00 2017-10-31 16:00:00
4  2017-10-31  1970-01-01 16:12:00 2017-10-31 16:12:00

<强>计时

In [302]: %timeit df['Date3'] =  ['{} {}'.format(a, b.split()[1]) for a, b in zip(df['Date1'], df['Date2'])]
30.2 ms ± 137 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [303]: %timeit df['Date3'] = df['Date1'] + ' ' + df['Date2'].str.split().str[1]
66.4 ms ± 3.18 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

答案 1 :(得分:2)

另一种方式是

df.Date1.str[:].values

Date1会将Date2字段设为numpy数组,同样使用str[10:]字段。

Date2用于提取从Date1附加到日期的%timeit df.d2 = df.d1.str[:].values + df.d2.str[10:].values 2.26 ms ± 82.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 的时间部分。

计时: 2.26 ms±82.2μs

{{1}}