当前位置: 首页 > 面试题库 >

为什么熊猫在这里应用lambda比循环慢?

满自明
2023-03-14
问题内容

我有一个熊猫数据框,我想根据是否满足某些条件进行过滤。我跑了一个循环,.apply()然后用来%%timeit测试速度。数据集大约有45000行。循环的代码片段为:

%%timeit
qualified_actions = []
for row in all_actions.index:
    if all_actions.ix[row,'Lower'] <= all_actions.ix[row, 'Mid'] <= all_actions.ix[row,'Upper']:
        qualified_actions.append(True)
    else:
        qualified_actions.append(False)

每个循环1.44 s±3.7毫秒(平均±标准偏差,共7次运行,每个循环1次)

而且.apply()是:

%%timeit
qualified_actions = all_actions.apply(lambda row: row['Lower'] <= row['Mid'] <= row['Upper'], axis=1)

每个循环6.71 s±54.6 ms(平均±标准偏差,共7次运行,每个循环1次)

我认为.apply()应该比循环遍历大熊猫更快。有人可以解释为什么在这种情况下速度变慢吗?


问题答案:

apply在后台使用循环,因此,如果需要更好的性能,最好的和最快的方法是最好的选择。

没有循环,只有链2条件向量化解决方案:

m1 = all_actions['Lower'] <= all_actions['Mid']
m2 = all_actions['Mid'] <= all_actions['Upper']
qualified_actions = m1 & m2

感谢Jon Clements提供的另一种解决方案:

all_actions.Mid.between(all_actions.Lower, all_actions.Upper)

时间

np.random.seed(2017)
N = 45000
all_actions=pd.DataFrame(np.random.randint(50, size=(N,3)),columns=['Lower','Mid','Upper'])

#print (all_actions)
In [85]: %%timeit
    ...: qualified_actions = []
    ...: for row in all_actions.index:
    ...:     if all_actions.ix[row,'Lower'] <= all_actions.ix[row, 'Mid'] <= all_actions.ix[row,'Upper']:
    ...:         qualified_actions.append(True)
    ...:     else:
    ...:         qualified_actions.append(False)
    ...: 
    ...: 
__main__:259: DeprecationWarning: 
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing

See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated
1 loop, best of 3: 579 ms per loop

In [86]: %%timeit
    ...: (all_actions.apply(lambda row: row['Lower'] <= row['Mid'] <= row['Upper'], axis=1))
    ...: 
1 loop, best of 3: 1.17 s per loop

In [87]: %%timeit
    ...: ((all_actions['Lower'] <= all_actions['Mid']) & (all_actions['Mid'] <= all_actions['Upper']))
    ...: 
1000 loops, best of 3: 509 µs per loop


In [90]: %%timeit
    ...: (all_actions.Mid.between(all_actions.Lower, all_actions.Upper))
    ...: 
1000 loops, best of 3: 520 µs per loop


 类似资料:
  • 问题内容: 在大多数情况下,似乎可以加快数据框上的操作过程。但是当我使用时,我找不到加速器。这是我的示例,我有一个包含两列的数据框 我想做的是通过在on上实现一个函数来计算数据帧中每一行的值,结果将除以中的值。例如,第一行的结果应为。这是我要调用的函数 然后我打电话的: 但是我发现在这种情况下,它比for循环要慢得多,例如 谁能解释原因? 问题答案: 我的理解是,通常 不会 比在轴上迭代快。我相信

  • 问题内容: 这里是Spark新手。我最近开始使用以下命令在两个内核的本地计算机上使用Spark: 我有一个393Mb的文本文件,其中包含近一百万行。我想执行一些数据操作操作。我使用的是内置PySpark的数据帧的功能进行简单的操作,如,,,。 但是,当我在完全相同的数据集上对熊猫进行完全相同的操作时,就延迟而言,熊猫似乎在很大程度上击败了pyspark。 我想知道这可能是什么原因。我有几点想法。

  • 内置函数是否低效地执行序列化/反序列化过程?如果是,有哪些替代方案? 数据集是否太小,以至于无法超过运行spark的底层JVM的开销? 谢谢你找我。非常感谢。

  • 我对Lambda很陌生,以下是教科书(简而言之就是java)所说的: 只有某些类型才有资格成为lambda的目标。目标类型也称为函数接口,它们必须: BE接口 只有一个非默认方法(但可能有其他默认方法) 我知道这个lambda将转换成接口,它是,与书中的描述相符 但是,当希望接收时,我可以在这里使用lambda 但是它有两个非默认方法和。

  • 问题内容: 我想在熊猫数据框上生成一个总和。我有类似的东西: 我想得到: 因此,每个单元格应该是其自身与所有先前单元格的总和,我应该如何在不使用循环的情况下做到这一点。 问题答案: 正如@JonClements提到的,您可以使用DataFrame方法执行此操作:

  • 问题内容: 我正在经历 递增/递减运算符 ,并且 遇到了这样的情况:如果在这种情况下以递减形式运行循环,则其运行速度将比相同的以递增形式运行的循环快。 我期望两者将花费相同的时间,因为将遵循相同数量的步骤。我在网上搜索,但找不到令人信服的答案。是因为与增量运算符相比,减数运算符花费的时间更少吗? 问题答案: 这是因为在字节码中,与0比较与与非零数字比较是不同的操作。实际需要先将数字加载到堆栈上,然