【问题标题】:Fast subtraction of two dataframes ignoring indices (Python)忽略索引的两个数据帧的快速减法(Python)
【发布时间】:2016-11-07 22:47:00
【问题描述】:

如何以可能的最快方式减去 2 个忽略索引的数据帧。

例如,我想减去:

d1=
      x1
0 -3.141593
0 -3.141593
0 -3.141593
1 -2.443461
1 -2.443461

来自

d2 = 
      x2
1 -2.443461
2 -1.745329
3 -1.047198
4 -0.349066
2 0.349066

我尝试过的:

我可以这样做,例如:

dsub = d1.reset_index(drop=True) - d2.reset_index(drop=True)

但是,我想以最有效的方式进行减法。我一直在寻找答案,但我只看到了不考虑速度的解决方案。

我该如何做到这一点?


编辑根据一些答案,以下是在我的机器上运行的一些时间:

对于较小的数据框:

方法一(a和b):

a: d1.reset_index(drop=True) - d2.reset_index(drop=True)
b: d1.reset_index(drop=True).sub(d2.reset_index(drop=True))
~1024.91 usec/pass

方法二:

d1 - d2.values
~784.79 usec/pass

方法三:

pd.DataFrame(d1.values - d2.values, d1.index, ['x1-x2'])
~653.82 usec/pass

对于非常大的数据帧,请参阅下面@MaxU 的答案。

【问题讨论】:

  • 试试这个:d1 - d2.values
  • @MaxU 那不会返回一个 numpy.array 吗?如果这是所需的输出,则必须将其转换回 DataFrame。编辑:错过了你的编辑,nvm!
  • @beeftendon,是的,谢谢!我已经更正了我的评论并在我的答案中添加了一个演示

标签: python performance pandas dataframe


【解决方案1】:

你可以这样做:

d1 - d2.values

或:

d1.x1 - d2.x2.values

演示:

In [172]: d1 - d2.values
Out[172]:
         x1
0 -0.698132
0 -1.396264
0 -2.094395
1 -2.094395
1 -2.792527

In [173]: d1.x1 - d2.x2.values
Out[173]:
0   -0.698132
0   -1.396264
0   -2.094395
1   -2.094395
1   -2.792527
Name: x1, dtype: float64

更大的 DF 的时机:

In [180]: d1 = pd.concat([d1] * 10**5, ignore_index=True)

In [181]: d2 = pd.concat([d2] * 10**5, ignore_index=True)

In [182]: d1.shape
Out[182]: (500000, 1)

In [183]: %timeit pd.DataFrame(d1.values - d2.values, d1.index, ['x1-x2'])
100 loops, best of 3: 4.07 ms per loop

In [184]: %timeit d1 - d2.values
100 loops, best of 3: 3.99 ms per loop

In [185]: d1 = pd.concat([d1] * 10, ignore_index=True)

In [186]: d2 = pd.concat([d2] * 10, ignore_index=True)

In [187]: d1.shape
Out[187]: (5000000, 1)

In [188]: %timeit pd.DataFrame(d1.values - d2.values, d1.index, ['x1-x2'])
10 loops, best of 3: 19.9 ms per loop

In [189]: %timeit d1 - d2.values
100 loops, best of 3: 14 ms per loop

In [190]: %timeit d1.reset_index(drop=True) - d2.reset_index(drop=True)
1 loop, best of 3: 242 ms per loop

In [191]: %timeit d1.reset_index(drop=True).sub(d2.reset_index(drop=True))
1 loop, best of 3: 242 ms per loop

【讨论】:

  • 哇,感谢为超大帧增加的时间测试......很有趣。那么这是我们能做到的最快的吗? :)
  • @denvar 你能分享一下为什么在适当大小的输入上需要 4 毫秒的单个操作是一个问题吗?
  • @Jeff 好问题 :),当然:我将这个包裹在一个蒙特卡洛例程中,最终可能需要数百万步。 4 毫秒加起来。
  • 你可以简单地使用 numpy 或 numba 然后完全避免构建开销
  • 好吧,我的程序的其他部分也使用了数据框。我的理解是数据框处理数据的速度非常快。但也许你是对的,对于这个特定的应用程序,转换为 numpy 数组的前期成本是值得的。好建议。
【解决方案2】:
dsub = pd.DataFrame(d1.values - d2.values, d1.index, ['x1-x2'])

dsub

【讨论】:

  • 我想知道如果我们在两个数据框中都有多个列,这将如何工作?
  • 我用于columns 参数的['x1-x2'] 非常随意。将其关闭,或将其设置为 d1.columns
【解决方案3】:

已经有一个内置的 DataFrame 减法方法。看看DataFrame.sub

您的示例中的用法基本上是:

dsub = df1['x1'].reset_index(drop=True).sub(df2['x2'].reset_index(drop=True))

如果 DataFrame 具有相同的列标题,则不需要指定列,例如

dsub = df1.reset_index(drop=True).sub(df2.reset_index(drop=True))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-25
    • 2019-02-01
    • 1970-01-01
    • 2017-04-20
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    相关资源
    最近更新 更多