【问题标题】:Speed up applying function to a list of pandas dataframes加快将函数应用于熊猫数据框列表
【发布时间】:2019-05-14 14:56:39
【问题描述】:

我有一些时间序列数据,其中每个数据点都是熊猫数据框,即数据框列表。我还有一个函数foo 对每个数据点进行操作。目的是将函数应用于整个时间序列数据并有效地完成。

我已经对函数foo 进行了矢量化处理,以便它对整个数据帧进行操作,并实现了大约 32 倍的加速。

原代码如下:

def bar(row, cols):
    return tuple([row[col] for col in cols])

def foo(df, cols):
    keys = set()
    for index, row in df.iterrows():
        key = bar(row, cols)
        keys.add(key)

    # do calculations on keys that returns a numeric output, result
    return result # float64

矢量化代码如下:

def vect_bar(df, cols):
    df['key'] = df[cols].values.sum(axis=1)
    return df

def vect_foo(df, cols):
    df['key'] = ""
    df = vect_bar(df, cols)
    keys = df.key.unique()

    # do calculations on keys that returns a numeric output, result
    return result # float64

计时结果如下:

%timeit -n 100 foo(df, cols)
100 loops, best of 3: 42.9 ms per loop

%timeit -n 100 vect_foo(df, cols)
100 loops, best of 3: 1.34 ms per loop

注意: cols 是列名列表。 数据框的所有元素都是字符串和 dtype 对象。

但是,将vect_foo 应用于所有数据点仍然需要很长时间。如何进一步加快速度?

我尝试根据数据创建熊猫系列并使用series.apply()。但是,这并没有导致常规 for 循环方法的任何加速。

编辑: 如果我之前不清楚,给定一个数据框,函数vect_foo 非常有效。 我想要的是一种加快将vect_foo 应用于所有数据点(即数据帧列表)的方法。

data_series = pd.Series(data)
def apply_data():
    return data_series.apply(vect_foo, cols)

data 是 pandas 数据帧的列表,即data = [df1, df2, ..., df50K]

在这里,我尝试了pandas.Series.apply(),但它的表现类似于普通的 for 循环方法。

【问题讨论】:

  • 数据框有多大?另外,我是否理解您基本上只是在创建一个名为 keys 的新列,以逐行汇总值?
  • 每个数据框都有 [50, 200] 范围内的行。列表的长度约为 50K。是的,你是对的。我按行添加值,但仅添加 cols 指定的那些列。

标签: python pandas vectorization


【解决方案1】:
import pandas as pd

def foo(row, cols):
    row['keys'] = row[cols].sum()
    return row

df.apply(foo, axis=1)

只需创建您的辅助函数并使用apply 函数。这通常是在 pandas 中跨行/列应用函数的最有效方式

【讨论】:

  • 感谢您的意见。我按照您的建议尝试了apply,但是,在整个数据帧上运行的vect_foo 速度快了大约 4 倍。所以我认为重点应该是更快地将vect_foo 应用于列表中的所有点,而不是让vect_foo 本身更快。
  • 为什么vect_foo 存在? vect_bar 如果您想一次将其应用于整个数据帧,实际上应该绰绰有余。
  • 你是对的。 vect_foo 中还有一些与问题无关的其他计算,所以我删除了它们。你可以只考虑vect_bar,它只是一个方便的函数,除了函数调用开销之外没有什么区别,这只是一次。
  • vect_bar应用于列表中的每个数据框后,您是否打算在其上使用pandas.concat
  • 老实说,如果您仍然需要为已经非常高效地运行的函数运行效率标记,最好的办法是使用 dask 并并行处理计算。
猜你喜欢
  • 2019-02-07
  • 2017-11-29
  • 2018-11-13
  • 1970-01-01
  • 2021-02-12
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多