如何高效地将两列合并成一列/合并字符串?

4
我有两列(A和Date)如下,需要将它们合并成一列(C),这个数据集有超过900,000行。

enter image description here 然后我遇到了两个主要问题:
  1. 列"Date"的数据类型是"timestamp",当我与字符串类型结合时会导致错误:

TypeError: unsupported operand type(s) for +: 'Timestamp' and 'str'。

  1. 代码的时间成本太高了。 我写了一个for循环来进行组合,如下所示:

    for i in range(0,911462): df['Combine'][i]=df['Date'][i]+df['A'][i]

我猜这是因为使用for循环是逐行进行组合,因此每个单独的组合在系统IO上花费了很多时间。
是否有更有效的方法来完成这项工作?

抱歉,我不熟悉添加照片的过程,请点击超链接“输入图像描述”以查看数据描述。 - Vane Leung
4个回答

4
你需要明确地将时间戳转换为字符串,例如使用 strftime 函数:
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

3

使用 astype,它可以将像Timestamp这样的对象转换为string

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将会是:

    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

@piRSquared 嗯,我认为 OP 只是想简单地将 A 列(str)和 Date 列(Timestamp)组合起来。 - Tiny.D

2

设置

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

选项 1
使用基于format和字典解包的lambda进行apply
这种方法较慢,但很酷。

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

选项 2
numpy.core.defchararray.add
使用'datetime64[D]'将日期舍入到天,非常快速的方法。

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 中使用。

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

时间控制


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

小数据

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

大数据

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

0

关于第一点,您可以将时间戳打印为字符串

关于第二点。如果您计划定期运行此操作,应考虑使用map/reduce。MrJob是一个用Python编写的工具,允许您在本地运行map/reduce作业,将它们拆分成多个并行运行的作业。请查看示例,您的脚本应该非常简单。重要提示:仅当您不担心行顺序并且只有一个以上的核心可用时,才能使用此功能。

最好的祝愿。


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