关于python:如何有效地将两列组合成一列/组合字符串?

How to efficiently combine two columns into one column/ combine strings?

我有两列(A和日期),如下所示,需要将它们组合成一列(C列)。这个数据集有超过90万行。enter image description here

然后我遇到了两个主要问题。

  • "Date"列的数据类型为timestamp,当我将它们与字符串类型组合时,会导致错误:
  • TypeError: unsupported operand type(s) for +: 'Timestamp' and 'str'.

  • 代码太费时了。我编写了一个for循环来进行组合,如下所示:

    对于范围(0911462)内的I:df['combine'][i]=df['date'][i]+df['a'][i]

  • 我想这是因为使用for循环是一行一行地进行组合,所以每个组合在系统IO上花费了大量的时间。

    有什么方法可以更有效地完成这项工作吗?


    您必须显式地将时间戳大小写为字符串,例如,使用strftime:

    1
    2
    3
    4
    5
    6
    7
    In [11]: df = pd.DataFrame([[pd.Timestamp("2017-01-01"), 'a'], [pd.Timestamp("2017-01-02"), 'b']], columns=["A","B"])

    In [12]: df["A"].dt.strftime("%Y-%m-%d") + df["B"]
    Out[12]:
    0    2017-01-01a
    1    2017-01-02b
    dtype: object

    尝试使用astype,可以将Timestamp这样的对象强制转换为string这样的对象:

    1
    2
    3
    4
    import pandas as pd
    df = pd.DataFrame({'A':['XX','YY','ZZ','AA'], 'Date':[pd.Timestamp("2016-01-01"),pd.Timestamp('2016-01-15'),pd.Timestamp('2016-12-01'),pd.Timestamp('2016-07-12')]})
    df['Combine'] = df['Date'].astype(str) + '_'+df['A']
    df

    df将是:

    1
    2
    3
    4
    5
        A   Date        Combine
    0   XX  2016-01-01  2016-01-01_XX
    1   YY  2016-01-15  2016-01-15_YY
    2   ZZ  2016-12-01  2016-12-01_ZZ
    3   AA  2016-07-12  2016-07-12_AA


    安装程序

    1
    2
    3
    4
    df = pd.DataFrame(dict(
            A='XX YY ZZ AA'.split(),
            Date=pd.date_range('2017-03-31', periods=4)
        ))

    选项1基于format和字典解包的applylambda。这是一种缓慢但很酷的方法。

    1
    2
    3
    4
    5
    6
    7
    df.assign(C=df.apply(lambda x: '{Date:%Y-%m-%d}_{A}'.format(**x), 1))

        A       Date              C
    0  XX 2017-03-31  2017-03-31_XX
    1  YY 2017-04-01  2017-04-01_YY
    2  ZZ 2017-04-02  2017-04-02_ZZ
    3  AA 2017-04-03  2017-04-03_AA

    选项2numpy.core.defchararray.add'datetime64[D]'来完成这项任务的非常快的方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    chr_add = np.core.defchararray.add

    d = df.Date.values.astype('datetime64[D]').astype(str)
    a = df.A.values.astype(str)
    df.assign(C=chr_add(chr_add(d, '_'), a))

        A       Date              C
    0  XX 2017-03-31  2017-03-31_XX
    1  YY 2017-04-01  2017-04-01_YY
    2  ZZ 2017-04-02  2017-04-02_ZZ
    3  AA 2017-04-03  2017-04-03_AA

    选项3把@andyhayden的答案撕下来,稍作改动。我将在strftime中添加下划线'_'…主要地,这是我将在timeit中使用的。

    1
    2
    3
    4
    5
    6
    7
    df.assign(C=df.Date.dt.strftime('%Y-%m-%d_') + df.A)

        A       Date              C
    0  XX 2017-03-31  2017-03-31_XX
    1  YY 2017-04-01  2017-04-01_YY
    2  ZZ 2017-04-02  2017-04-02_ZZ
    3  AA 2017-04-03  2017-04-03_AA

    计时

    1
    2
    3
    4
    5
    6
    7
    8
    9
    %%timeit
    chr_add = np.core.defchararray.add

    d = df.Date.values.astype('datetime64[D]').astype(str)
    a = df.A.values.astype(str)
    chr_add(chr_add(d, '_'), a)

    %timeit df.assign(C=df.apply(lambda x: '{Date:%Y-%m-%d}_{A}'.format(**x), 1))
    %timeit df.assign(C=df.Date.dt.strftime('%Y-%m-%d_') + df.A)

    小数据

    1
    2
    3
    10000 loops, best of 3: 53.2 μs per loop
    1000 loops, best of 3: 1.14 ms per loop
    1000 loops, best of 3: 831 μs per loop

    大数据

    1
    2
    3
    4
    5
    df = pd.concat([df] * 10000, ignore_index=True)

    10 loops, best of 3: 80.3 ms per loop
    1 loop, best of 3: 4.58 s per loop
    1 loop, best of 3: 233 ms per loop

    大约1,您可以将时间戳打印为字符串

    大约2。如果您计划定期运行这个程序,那么应该考虑使用map/reduce。mrjob是一个用python编写的工具,它允许您在本地运行映射/减少作业,将它们拆分为多个并行运行的作业。检查示例,您的脚本应该非常简单。重要提示:只有当您不担心行顺序时,这才有效,并且只有当您有多个核心可用时才有用。

    最好的。