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

为什么在pandas DataFrame中应用有时不比for-loop快?

孔经武
2023-03-14

在大多数情况下,apply似乎可以加速对dataframe的操作过程。但是当我使用apply时,我没有发现加速效果。下面是我的示例,我有一个包含两列的数据表

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

我要做的是通过在col1上实现函数r(x)来计算dataframe中每一行的值,结果将被col2中的值除以。例如,第一行的结果应该是r(10)/20。下面是我的函数,它将在apply中调用

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

然后在apply中调用_f:df.apply(_f,axis=1)

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

共有1个答案

曹伟泽
2023-03-14

根据我的理解,.apply通常不比轴上的迭代快。我相信在下面,它只是一个轴上的循环,只是在这种情况下,您每次都要承受函数调用的开销。

如果我们查看源代码,我们可以看到本质上我们在指示的轴上迭代并应用函数,将单个结果作为系列构建到字典中,最后在字典上调用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)
    null
 类似资料:
  • 问题内容: 例如,此行失败: 什么是正确的方法? 问题答案: 因为’nohup’需要一个单词命令及其参数-不是shell循环构造。您必须使用:

  • 问题内容: 该代码在第一个“等级”之后保持两次打印。有谁知道为什么要打印两次?我做错了“ For Loop”吗? 问题答案: 这是“两次打印”,因为当您按回车键输入一个字符时,实际上是在写两个字符:您键入的字符和(换行符)。 添加第二个调用以读取换行符: 同样,不需要初始化为in 也可以。实际上,在此循环中使用a没有意义,首选使用a 。

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

  • 在大多数情况下,似乎可以加速数据帧上的操作过程,但当我使用时,我没有发现加速。这是我的例子;我有一个包含两列的数据框: 我想做的是通过在上实现函数来计算数据帧中每一行的值,结果将除以中的值。例如,第一行的结果应该是。 这是我的函数,将在中调用: 然后我在中调用: 但是,我发现在这种情况下,比for循环慢得多,比如 有人能解释原因吗?

  • 我一直在学习JAVA,我对代码有点怀疑: 我编写了处理异常的小程序,如果用户输入不是Int,则抛出异常并分配默认值。如果我将扫描仪语句放入循环中,它可以正常工作,但如果我将其置于其外部,则分配抛出异常的相同值,即我输入的是char而不是int。但如果我输入所有整数,它会在数组中分配正确的值。 我希望你们理解我的问题。

  • 构造循环允许您实现像其他语言中最常见的for循环之类的迭代。 它允许你 为迭代设置变量 指定将有条件地终止迭代的表达式 指定用于在每次迭代中执行某些作业的表达式 指定表达式,以及在退出循环之前执行某些工作的表达式 构造的for循环遵循几种语法 - (loop for loop-variable in <a list> do (action) ) (loop for loop-variable