gpt4 book ai didi

python - 如何使用前几行的数据在数据框列上应用函数?

转载 作者:行者123 更新时间:2023-12-03 15:27:24 27 4
gpt4 key购买 nike

我有一个包含三列的数据框:nums使用一些值,b始终是 10result列当前除第一行之外的所有地方都为零(因为我们必须有一个初始值才能使用)。
数据框如下所示:

   nums   b    result
0 20.0 1 20.0
1 22.0 0 0
2 30.0 1 0
3 29.1 1 0
4 20.0 0 0
...

问题

我想从第二行开始查看数据框中的每一行,做一些计算并将结果存储在 result 中。柱子。由于我正在处理大文件,因此我需要一种方法来使此操作快速进行,这就是为什么我想要类似 apply 的原因。 .

我要做的计算是取 nums中的值并在 result来自 上一页 行,如果在 当前 b col 是 0然后我想(例如)添加 numresult从前一行。如 b该行是 1例如,我想减去它们。

我尝试了什么?

我尝试使用 apply但我无法访问前一行,遗憾的是,如果我确实设法访问了前一行,数据框直到最后才会更新结果列。

我也尝试使用这样的循环,但对于我正在使用的大文件来说太慢了:
       for i in range(1, len(df.index)):
row = df.index[i]
new_row = df.index[i - 1] # get index of previous row for "nums" and "result"
df.loc[row, 'result'] = some_calc_func(prev_result=df.loc[new_row, 'result'], prev_num=df.loc[new_row, 'nums'], \
current_b=df.loc[row, 'b'])
some_calc_func看起来像这样(只是一个一般的例子):
def some_calc_func(prev_result, prev_num, current_b):
if current_b == 1:
return prev_result * prev_num / 2
else:
return prev_num + 17

请就回答 some_calc_func

最佳答案

如果你想保留功能 some_calc_func并且不使用另一个库,您不应该尝试在每次迭代时访问每个元素,您可以使用 zip在 nums 和 b 列上,当您尝试从前一行访问 nums 并在每次迭代时将 prev_res 保留在内存中时,在两者之间进行转换。另外,append到列表而不是数据框,并在循环后将列表分配给列。

prev_res = df.loc[0, 'result'] #get first result
l_res = [prev_res] #initialize the list of results
# loop with zip to get both values at same time,
# use loc to start b at second row but not num
for prev_num, curren_b in zip(df['nums'], df.loc[1:, 'b']):
# use your function to calculate the new prev_res
prev_res = some_calc_func (prev_res, prev_num, curren_b)
# add to the list of results
l_res.append(prev_res)
# assign to the column
df['result'] = l_res
print (df) #same result than with your method
nums b result
0 20.0 1 20.0
1 22.0 0 37.0
2 30.0 1 407.0
3 29.1 1 6105.0
4 20.0 0 46.1

现在有了 5000 行的数据帧 df,我得到了:
%%timeit
prev_res = df.loc[0, 'result']
l_res = [prev_res]
for prev_num, curren_b in zip(df['nums'], df.loc[1:, 'b']):
prev_res = some_calc_func (prev_res, prev_num, curren_b)
l_res.append(prev_res)
df['result'] = l_res
# 4.42 ms ± 695 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

使用您的原始解决方案,速度慢了约 750 倍
%%timeit 
for i in range(1, len(df.index)):
row = df.index[i]
new_row = df.index[i - 1] # get index of previous row for "nums" and "result"
df.loc[row, 'result'] = some_calc_func(prev_result=df.loc[new_row, 'result'], prev_num=df.loc[new_row, 'nums'], \
current_b=df.loc[row, 'b'])
#3.25 s ± 392 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

使用另一个名为 numba 的库进行编辑, 如果函数 some_calc_func可以很容易地与 Numba 装饰器一起使用。
from numba import jit
# decorate your function
@jit
def some_calc_func(prev_result, prev_num, current_b):
if current_b == 1:
return prev_result * prev_num / 2
else:
return prev_num + 17

# create a function to do your job
# numba likes numpy arrays
@jit
def with_numba(prev_res, arr_nums, arr_b):
# array for results and initialize
arr_res = np.zeros_like(arr_nums)
arr_res[0] = prev_res
# loop on the length of arr_b
for i in range(len(arr_b)):
#do the calculation and set the value in result array
prev_res = some_calc_func (prev_res, arr_nums[i], arr_b[i])
arr_res[i+1] = prev_res
return arr_res

最后,称之为
df['result'] = with_numba(df.loc[0, 'result'], 
df['nums'].to_numpy(),
df.loc[1:, 'b'].to_numpy())

随着时间的推移,我比使用 zip 的方法快了大约 9 倍,并且速度可能会随着大小的增加而增加
%timeit df['result'] = with_numba(df.loc[0, 'result'], 
df['nums'].to_numpy(),
df.loc[1:, 'b'].to_numpy())
# 526 µs ± 45.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

请注意,根据您的实际情况,使用 Numba 可能会出现问题 some_calc_func

关于python - 如何使用前几行的数据在数据框列上应用函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62170148/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com