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

为什么在熊猫数据框中应用有时并不比for循环快?

黄无尘
2023-03-14
问题内容

apply在大多数情况下,似乎可以加快数据框上的操作过程。但是当我使用时,我apply找不到加速器。这是我的示例,我有一个包含两列的数据框

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

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

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

然后我打电话_fapplydf.apply(_f, axis=1)

但是我发现在这种情况下,apply它比for循环要慢得多,例如

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

谁能解释原因?


问题答案:

我的理解.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)

series_gen根据请求的轴在哪里构造。

为了使功能发挥更大的性能,您可以按照此处给出的建议进行操作。

本质上,您的选择是:

  1. 写一个C扩展
  2. 使用numba(JIT编译器)
  3. 用于pandas.eval从大型数据帧中挤出性能


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

  • 问题内容: 我有一个熊猫数据框,我想根据是否满足某些条件进行过滤。我跑了一个循环,然后用来测试速度。数据集大约有45000行。循环的代码片段为: 每个循环1.44 s±3.7毫秒(平均±标准偏差,共7次运行,每个循环1次) 而且是: 每个循环6.71 s±54.6 ms(平均±标准偏差,共7次运行,每个循环1次) 我认为应该比循环遍历大熊猫更快。有人可以解释为什么在这种情况下速度变慢吗? 问题答案

  • 问题内容: 当从父数据帧中选择子数据帧时,我注意到有些程序员使用该方法复制数据帧。例如, …而不只是 他们为什么要复制数据框?如果我不复制怎么办? 问题答案: 这扩展了保罗的答案。在Pandas中,为DataFrame编制索引将返回对初始DataFrame的引用。因此,更改子集将更改初始DataFrame。因此,如果要确保不更改初始DataFrame,则需要使用该副本。考虑以下代码: 你会得到:

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

  • 使用pandas dataframe假设我有如下结构相似的数据帧: 我想要一个新的2列(Choise,Value),它满足“a_Cho”、“b_Cho”和“c_Cho”中所有值的以下条件 如果“a_Cho”=true,则选择“a_n”,值=a对应于“a_Cho”的值如果“a_Cho”=false,则移动到下一步 如果“b_Cho”=true,则选择“b_n”,值=b表示“b_Cho”的对应值,如果

  • 问题内容: 当我对数据框中的单个元素进行比较时出现错误,但我不明白为什么。 我有一个数据框df,其中包含许多客户的时间序列数据,其中包含一些空值: 在我的脚本中,该行 生成一个错误: 但是,如果我在脚本行上放置了一个断点,并且在脚本停止时我将其输入到控制台中: 输出为: 如果我允许脚本从这一点继续执行,则会立即生成错误。 如果布尔表达式可以求值并具有值,为什么它在if表达式中生成错误?这对我来说毫