为什么有时在 Pandas 数据框中应用并不比 for 循环更快?
- 2025-03-21 09:07:00
- admin 原创
- 59
问题描述:
在大多数情况下,它似乎apply
可以加速数据框上的操作过程,但是,当我使用时,apply
我发现加速并不明显。这是我的示例;我有一个包含两列的数据框:
>>>df
index col1 col2
1 10 20
2 20 30
3 30 40
R(x)
我想要做的是通过实现一个函数来计算数据框中每一行的值col1
,然后将结果除以中的值col2
。例如,第一行的结果应该是R(10)/20
。
这是我的函数,将在以下位置调用apply
:
def _f(input):
return R(input['col1'])/input['col2']
然后我_f
打电话apply
:df.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']
有人能解释一下原因吗?
解决方案 1:
据我所知,这通常不会.apply
比轴上的迭代更快。我相信在底层它只是轴上的一个循环,只不过在这种情况下每次都会产生函数调用的开销。
如果我们查看源代码,我们可以看到,本质上我们正在遍历指示的轴并应用函数,将各个结果作为系列构建到字典中,最后调用字典上的数据框构造函数返回一个新的 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
根据请求的轴构建的位置。
为了获得更好的功能性能,您可以遵循此处给出的建议。
本质上,您的选择是:
编写 C 扩展
使用
numba
(JIT 编译器)用于
pandas.eval
提高大型 Dataframe 的性能
相关推荐
热门文章
项目管理软件有哪些?
热门标签
曾咪二维码
扫码咨询,免费领取项目管理大礼包!
云禅道AD