【问题标题】:Alternative for concatconcat 的替代方案
【发布时间】:2017-01-24 16:53:49
【问题描述】:

我把同一张表组合如下:

   pd.concat([df_dates,
               df_dates,
               df_dates,
               df_dates]

如何更简洁地编写代码

【问题讨论】:

  • 我不知道pd.concat是做什么的,但是[df_dates, df_dates, df_dates, df_dates]可以写成[df_dates]*4
  • 你可以做pd.concat([df_dates]*4]),但你在这之后是什么,这是更短的代码但它不是速度效率,例如pd.DataFrame(np.tile(df_dates), 4, columns = df_dates.columns)会更快

标签: python date pandas


【解决方案1】:

不确定您在效率方面追求什么,但这里有 2 种方法:

In [32]:
df = pd.DataFrame(np.random.randn(3,2), columns=list('ab'))
df

Out[32]:
          a         b
0  0.108453 -2.875348
1 -1.502857  0.057709
2  0.356384 -0.870802

您可以在列表中重复 df:

In [33]:    
pd.concat([df]*4)

Out[33]:
          a         b
0  0.108453 -2.875348
1 -1.502857  0.057709
2  0.356384 -0.870802
0  0.108453 -2.875348
1 -1.502857  0.057709
2  0.356384 -0.870802
0  0.108453 -2.875348
1 -1.502857  0.057709
2  0.356384 -0.870802
0  0.108453 -2.875348
1 -1.502857  0.057709
2  0.356384 -0.870802

但使用 np.tile 并重复 df 会更快:

In [56]:
pd.DataFrame(np.tile(df,(4,1)), columns= df.columns)

Out[56]:
           a         b
0   0.108453 -2.875348
1  -1.502857  0.057709
2   0.356384 -0.870802
3   0.108453 -2.875348
4  -1.502857  0.057709
5   0.356384 -0.870802
6   0.108453 -2.875348
7  -1.502857  0.057709
8   0.356384 -0.870802
9   0.108453 -2.875348
10 -1.502857  0.057709
11  0.356384 -0.870802

时间

In [57]:
%timeit pd.concat([df]*4)
%timeit pd.DataFrame(np.tile(df,(4,1)), columns= df.columns)

1000 loops, best of 3: 621 µs per loop
10000 loops, best of 3: 142 µs per loop

在这里您可以看到,即使在这个小型数据集上,numpy 方法的速度也快了 4 倍以上,并且对于大型数据集的扩展性更好,尤其是当您增加重复次数时:

In [65]:
%timeit pd.concat([df]*400)
%timeit pd.DataFrame(np.tile(df,(400,1)), columns= df.columns)

10 loops, best of 3: 37.5 ms per loop
10000 loops, best of 3: 152 µs per loop

对于 400 次重复,我们看到 numpy 的速度要快约 300 倍

更新

感谢@Jeff 指出这一点,如果您的 df 混合了 dtypes(就整个 df 而言,而不是针对特定列而言),那么 dtypes 将被删除:

In [2]:
df = pd.DataFrame({'a':np.random.randn(3),'b':np.arange(3)})
df

Out[2]:
          a  b
0 -0.016903  0
1  1.440656  1
2 -1.073728  2

In [3]:
pd.DataFrame(np.tile(df,(4,1)), columns= df.columns)

Out[3]:
           a    b
0  -0.016903  0.0
1   1.440656  1.0
2  -1.073728  2.0
3  -0.016903  0.0
4   1.440656  1.0
5  -1.073728  2.0
6  -0.016903  0.0
7   1.440656  1.0
8  -1.073728  2.0
9  -0.016903  0.0
10  1.440656  1.0
11 -1.073728  2.0

此处“b”列的 int64 dtype 现在已转换为 float64,这在此处是不可取的

【讨论】:

  • 在做这样的事情时需要非常小心:numpy 方法通常将 dtypes 混合在一起,只有在重新创建框架时才会重新推断。所以一般不推荐这样做
  • @Jeff 大概只要 dtypes 对 pandas 友好且同质,这将是安全的?我将在我的回答中添加更新以提及,感谢您提供信息
  • @Jeff 谢谢我刚刚发布了一个简单的例子来证明这一点
【解决方案2】:

你可以使用 pd.concat([df_dates] * 4)

您可能猜到了,*4 使用了该元素 4 次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 2015-06-13
    • 2015-03-03
    • 2015-09-25
    • 2019-12-16
    • 2011-06-20
    相关资源
    最近更新 更多