将数据帧的所有列传递给函数以进行矢量化

问题描述

我正在尝试加快要在数据帧上执行的功能。我最初使用iterrows,但是它肯定慢一些,所以我使用了apply。它肯定有所改善,但是我想使用np.vectorize以获得更好的性能。我的问题是如何将数据框的列传递给函数(假设列数或列名可以变化)。如何传递列然后遍历它们。我猜我可以在函数参数上使用* args,但是如何传递和破坏df的列呢?我也不想复制df(假设df非常大)。希望我的问题清楚

例如,假设我只想将数据打印成如下格式:

data = [ {"a": str(x),"b": x,"c": x} for x in range(10)]
df = pd.DataFrame(data)

def func(row):
    print(f"{row.to_json()}:",end="")

_ = df.apply(func,axis=1)

这比进行迭代要快得多,但是如何进一步改进呢?在这种情况下,还应假设列数及其名称可以不同。

解决方法

通常,为了提高性能,您需要尽可能使用numpy / pandas内置方法,并且只能使用applynumpy.vectorize当绝对必要时。有关更多信息,请参阅this post from cs95

例如,可以使用pandas.DataFrame.to_json

来实现帖子中的功能

方法1:

print(df.to_json(orient="records",lines=True).replace(os.linesep,':'),end=':')

方法2:

print(':'.join(df.to_json(orient="records",lines=True).split()),end=':')

输出:

{"a":"0","b":0,"c":0}:{"a":"1","b":1,"c":1}:{"a":"2","b":2,"c":2}:{"a":"3","b":3,"c":3}:{"a":"4","b":4,"c":4}:{"a":"5","b":5,"c":5}:{"a":"6","b":6,"c":6}:{"a":"7","b":7,"c":7}:{"a":"8","b":8,"c":8}:{"a":"9","b":9,"c":9}:

性能测试代码和结果如下所示。为了进行比较,我还添加了仅打印一次的原始解决方案的变体。

import sys,os

data = [ {"a": str(x),"b": x,"c": x} for x in range(10)]
df = pd.DataFrame(data)

def func(row,file=sys.stdout):
    print(f"{row.to_json()}:",end="",file=file)

def func2(row):
    return row.to_json()

null_output = open(os.devnull,'w')

%timeit df.apply(func,axis=1,file=null_output)
%timeit print(':'.join(df.apply(func2,axis=1)),end=':',file=null_output)
%timeit print(':'.join(df.apply(pd.Series.to_json,file=null_output)
%timeit print(df.to_json(orient="records",file=null_output)
%timeit print(':'.join(df.to_json(orient="records",file=null_output)

输出:

1.67 ms ± 13 µs per loop (mean ± std. dev. of 7 runs,1000 loops each)
1.67 ms ± 16.5 µs per loop (mean ± std. dev. of 7 runs,1000 loops each)
1.68 ms ± 42.3 µs per loop (mean ± std. dev. of 7 runs,1000 loops each)
51.8 µs ± 1.61 µs per loop (mean ± std. dev. of 7 runs,10000 loops each)
51.4 µs ± 728 ns per loop (mean ± std. dev. of 7 runs,10000 loops each)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...