【问题标题】:Efficiently replace part of value from one column with value from another column in pandas using regex?使用正则表达式有效地将一列中的部分值替换为熊猫中另一列的值?
【发布时间】:2018-11-08 01:04:19
【问题描述】:

我有一个熊猫数据框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,或者是否有其他更有效的方法来执行此操作?

【问题讨论】:

    标签: python pandas vectorization


    【解决方案1】:

    一个想法是:

    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)
    

    【讨论】:

    • 第二种方法看起来最好,如果我们想要可解释性和“代码高尔夫”风格。哪种方法最快,你知道吗?谢谢
    • @killerT2333 - 给我一些时间安排:)
    【解决方案2】:

    另一种方法是

    df.Date2 = df.Date1.str[:].values + df.Date2.str[10:].values
    

    df.Date1.str[:].values 将获得 Date1 字段作为 numpy 数组,同样获得 Date2 字段。

    str[10:] 用于提取Date2 的时间部分,该部分附加到Date1 的日期之后。

    时间: 2.26 ms ± 82.2 µs

    %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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-04
      • 2020-11-15
      • 2021-08-31
      • 2020-01-21
      • 2018-04-11
      • 1970-01-01
      • 2022-01-27
      相关资源
      最近更新 更多