python-3.x - 如何将大量数据框列传递给 numpy 向量化作为参数
问题描述
我有一个正好有 31 列的数据框,例如 100 行。
我需要创建一个包含 100 个字典的列表,这些字典的值来自不同的 31 列。
我目前正在使用apply()
函数来执行此操作:
my_df.apply(lambda row: _build_data(row, param1, param2, param3), axis=1)
但现在我想探索 numpy 的vectorize()
可能性。问题是,从我正在阅读的内容来看,我应该将每一列作为单独的参数传递给它:
np.vectorize(_build_data)(my_df[col1], my_df[col2], ..., my_df[col31], param1, param2, param3)
这看起来不像 pythonic,我也不想定义一个有 34 个参数的函数。
你知道是否有另一种方法可以做到这一点?
非常感谢你的帮忙!
解决方案
我怀疑您正在尝试使用np.vectorize
,因为您读到 numpy 'vectorization' 是一种加速pandas
代码的方式。
In [29]: df = pd.DataFrame(np.arange(12).reshape(4,3), columns=['A','B','C'])
In [30]: df
Out[30]:
A B C
0 0 1 2
1 3 4 5
2 6 7 8
3 9 10 11
缓慢的逐行取行方法意味着:
In [31]: df.apply(lambda row: np.mean(row), axis=1)
Out[31]:
0 1.0
1 4.0
2 7.0
3 10.0
dtype: float64
快速的numpy方法:
In [32]: df.to_numpy()
Out[32]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
In [33]: df.to_numpy().mean(axis=1)
Out[33]: array([ 1., 4., 7., 10.])
也就是说,我们得到一个数据帧值的数组,并使用快速编译的方法来计算行均值。
但是要为每一行制作像字典一样的东西:
In [35]: df.apply(lambda row: {str(k):k for k in row}, axis=1)
Out[35]:
0 {'0': 0, '1': 1, '2': 2}
1 {'3': 3, '4': 4, '5': 5}
2 {'6': 6, '7': 7, '8': 8}
3 {'9': 9, '10': 10, '11': 11}
dtype: object
我们必须迭代数组行,就像我们对 dataframe 所做的那样apply
:
In [36]: [{str(k):k for k in row} for row in df.to_numpy()]
Out[36]:
[{'0': 0, '1': 1, '2': 2},
{'3': 3, '4': 4, '5': 5},
{'6': 6, '7': 7, '8': 8},
{'9': 9, '10': 10, '11': 11}]
数组方法更快:
In [37]: timeit df.apply(lambda row: {str(k):k for k in row}, axis=1)
1.13 ms ± 702 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [38]: timeit [{str(k):k for k in row} for row in df.to_numpy()]
40.8 µs ± 157 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
但是该apply
方法返回一个数据框,而不是一个列表。我怀疑大部分额外的时间都在这一步。
np.vectorize
(and np.frompyfunc
) 也可用于迭代数组,但默认是迭代元素,而不是行或列。一般来说,它们比更显式的迭代要慢(就像我在 [36] 中所做的那样)。
从列表中制作数据框的笨拙方法:
In [53]: %%timeit
...: df1 = pd.DataFrame(['one','two','three','four'],columns=['d'])
...: df1['d'] =[{str(k):k for k in row} for row in df.to_numpy()]
572 µs ± 18.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)