我有一个包含许多列的大型数据框架。为了简单起见,让我们这样说:
df_sample = pd.DataFrame({'a':np.arange(10)})我需要在df_sample中定义一个新的列(比如列'b'),它需要使用一些插值函数,它的参数取自列'a‘。
现在,问题是每行的插值函数是不同的。对于每一行,我从不同的1D网格进行插值;因此,我对每一行都有不同的插值函数。所以,我所做的就是预先生成这些插值函数,并将它们存储到一个数组中。仅给出一个示例,显示了生成样本数组“list_interpfns”的以下代码
list_interpfns = np.array([None]*10)
for j in range(10):
list_interpfns[j] = scipy.interpolate.interp1d(np.linspace(0,10*(j+1),10),np.linspace(0,50,10))要生成df_sample.bj,我需要使用带有参数df_sample.aj的list_interpfnsj。因为我不能直接应用列公式来达到这个目的,所以我把它放在一个循环中。
df_sample['b'] = 0
for j in range(10):
df_sample.loc[j,'b'] = list_interpfns[j](df_sample.a[j])问题是这个操作需要很长时间。在这个小例子中,计算可能看起来很快。但我的实际程序要大得多,当我比较所有操作所用的时间时,这个特定的操作序列占用了总时间的84%;我需要加快速度。
如果有一些方法可以避免for循环(例如使用df.apply或其他方法),那么我相信它可以减少操作时间。你能给出可能的替代方案吗?
发布于 2019-04-24 23:49:45
考虑避免初始化和更新数组和序列的多个for循环和记账,并使用Series.apply()将列值传递到函数构建和函数参数中
def interp_(j):
return scipy.interpolate.interp1d(np.linspace(0,10*(j+1),10), np.linspace(0,50,10))
df_sample['b_'] = df_sample['a'].apply(lambda x: interp_(x)(x))结果复制您的原始结果
df_sample
# a b b_
# 0 0 0.000000 0.000000
# 1 1 2.500000 2.500000
# 2 2 3.333333 3.333333
# 3 3 3.750000 3.750000
# 4 4 4.000000 4.000000
# 5 5 4.166667 4.166667
# 6 6 4.285714 4.285714
# 7 7 4.375000 4.375000
# 8 8 4.444444 4.444444
# 9 9 4.500000 4.500000尽管Series.apply()仍然是一个循环,但计时表明处理速度会稍微快一些:
def run1():
list_interpfns = np.array([None]*10)
for j in range(10):
list_interpfns[j] = scipy.interpolate.interp1d(np.linspace(0,10*(j+1),10),
np.linspace(0,50,10))
df_sample['b'] = 0
for j in range(10):
df_sample.loc[j,'b'] = list_interpfns[j](df_sample.a[j])
def run2():
def interp_(j):
return scipy.interpolate.interp1d(np.linspace(0,10*(j+1),10), np.linspace(0,50,10))
df_sample['b_'] = df_sample['a'].apply(lambda x: interp_(x)(x))
if __name__=='__main__':
from timeit import Timer
f1 = Timer("run1()", "from __main__ import run1")
res1 = f1.repeat(repeat=100, number=1)
print('LOOP: {}'.format(np.mean(res1)))
f2 = Timer("run2()", "from __main__ import run2")
res2 = f2.repeat(repeat=100, number=1)
print('APPLY: {}'.format(np.mean(res2)))
# LOOP: 0.006322918700000002
# APPLY: 0.0015046094699999867https://stackoverflow.com/questions/55829797
复制相似问题