当前位置: 首页 > 知识库问答 >
问题:

为什么有时在Pandas数据帧中应用并不比for循环更快?

严琨
2023-03-14

在大多数情况下,apply似乎可以加速数据帧上的操作过程,但当我使用apply时,我没有发现加速。这是我的例子;我有一个包含两列的数据框:

>>>df
index col1 col2
1 10 20
2 20 30
3 30 40

我想做的是通过在col1上实现函数R(x)来计算数据帧中每一行的值,结果将除以col2中的值。例如,第一行的结果应该是R(10)/20

这是我的函数,将在Application中调用:

def _f(input):
    return R(input['col1'])/input['col2']

然后我在apply中调用\u fdf。应用(_f,轴=1)

但是,我发现在这种情况下,applyfor循环慢得多,比如

for i in list(df.index)
    new_df.loc[i] = R(df.loc[i,'col1'])/df.loc[i,'col2']

有人能解释原因吗?

共有1个答案

祁修诚
2023-03-14

据我所知,。应用通常不会比轴上的迭代快。我相信在引擎盖下面,它只是轴上的一个循环,但在这种情况下,每次都会产生函数调用的开销。

如果我们查看源代码,我们可以看到,本质上我们是在指示的轴上迭代并应用函数,将单个结果作为序列构建到字典中,最后在字典上调用dataframe构造函数,返回一个新的dataframe:

    if axis == 0:
        series_gen = (self._ixs(i, axis=1)
                      for i in range(len(self.columns)))
        res_index = self.columns
        res_columns = self.index
    elif axis == 1:
        res_index = self.index
        res_columns = self.columns
        values = self.values
        series_gen = (Series.from_array(arr, index=res_columns, name=name,
                                        dtype=dtype)
                      for i, (arr, name) in enumerate(zip(values,
                                                          res_index)))
    else:  # pragma : no cover
        raise AssertionError('Axis must be 0 or 1, got %s' % str(axis))

    i = None
    keys = []
    results = {}
    if ignore_failures:
        successes = []
        for i, v in enumerate(series_gen):
            try:
                results[i] = func(v)
                keys.append(v.name)
                successes.append(i)
            except Exception:
                pass
        # so will work with MultiIndex
        if len(successes) < len(res_index):
            res_index = res_index.take(successes)
    else:
        try:
            for i, v in enumerate(series_gen):
                results[i] = func(v)
                keys.append(v.name)
        except Exception as e:
            if hasattr(e, 'args'):
                # make sure i is defined
                if i is not None:
                    k = res_index[i]
                    e.args = e.args + ('occurred at index %s' %
                                       pprint_thing(k), )
            raise

    if len(results) > 0 and is_sequence(results[0]):
        if not isinstance(results[0], Series):
            index = res_columns
        else:
            index = None

        result = self._constructor(data=results, index=index)
        result.columns = res_index

        if axis == 1:
            result = result.T
        result = result._convert(datetime=True, timedelta=True, copy=False)

    else:

        result = Series(results)
        result.index = res_index

    return result

明确地:

for i, v in enumerate(series_gen):
                results[i] = func(v)
                keys.append(v.name)

其中series_gen是基于请求的轴构建的。

要获得函数的更高性能,您可以遵循此处给出的建议。

基本上,您的选择是:

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

  • 在大多数情况下,似乎可以加速对dataframe的操作过程。但是当我使用时,我没有发现加速效果。下面是我的示例,我有一个包含两列的数据表 我要做的是通过在上实现函数来计算dataframe中每一行的值,结果将被中的值除以。例如,第一行的结果应该是。下面是我的函数,它将在中调用 然后在中调用:

  • 问题内容: 我读到 增强的for循环 比普通的 for循环 更有效: http://developer.android.com/guide/practices/performance.html#foreach 当我搜索它们的效率之间的差异时,我发现的是:如果是普通的for循环,我们需要一个额外的步骤来找出数组的长度或大小等, 但这是唯一的原因,增强的for循环优于普通的for循环吗?在那种情况下,

  • 在我的程序中,我发现当为时,循环无法正确退出。它看起来像整数溢出,远远大于10,循环不会停止。请告诉我发生了什么,以及如何在大型项目中避免这个错误。 代码链接

  • 问题内容: 是循环真正的“坏”?如果不是,在什么情况下它们会比使用更常规的“矢量化”方法更好?1个 我熟悉“矢量化”的概念,以及熊猫如何利用矢量化技术来加快计算速度。向量化功能在整个系列或DataFrame上广播操作,以实现比传统上迭代数据快得多的加速。 但是,我很惊讶地看到很多代码(包括来自Stack Overflow的答案)提供了解决问题的解决方案,这些问题涉及使用循环和列表推导遍历数据。文档

  • 我正在编写一个脚本,将文本文件读入一个数据框,该数据框可以包含各种列和行。然后,对数据进行一些操作,需要将所有数据汇总到一个数据框中,以输出到excel文档。 我的代码适用于单个文件,但现在我需要遍历所有文件。 这似乎应该很容易做到,但我已经尝试了我能找到的所有功能来实现这一点,但没有任何效果。 以下是基本结构: 输入/期望输出示例: 我尝试了追加、添加、合并、连接、合并,但没有一个有效。我只是使