【问题标题】:How to iterate with result of previous rows of same column?如何迭代同一列的前几行的结果?
【发布时间】:2021-07-07 02:21:17
【问题描述】:

从具有 A B D P 列的数据框开始:

import numba
import numpy as np
import pandas as pd
import vaex

d = {'A':[0,1,2,3,4,5,6],'B':[30,35,32,35,31,39,37],'D':[12,10,13,19,12,21,13],'P':[3,3,3,3,3,3,3]}
df = pd.DataFrame(data=d)

df['C'] = 0

df

导出到 hdf5:

df.to_csv("v_df", index=False)
    
df = vaex.from_csv("v_df", convert=True, chunk_size=5_000_000)

我需要计算每行的“C”列,所需结果如下:

'C': [0, 1.666666667, 0.552380952, 2.333630952, 0.962202381, 6.38155722, 5.714890553]

要达到这个结果,我需要从第 (1) 行开始迭代每一行并计算如下内容:

%%time
@numba.njit
def func(B, D, C, b_0=0):
    n = len(B)
    b = np.full(n, b_0, dtype=np.float64)
    for i in range(1, n):
        b[i] = ((((B[i] - B[i - 1]) / B[i - 1])) * D[i]) + C[i-1]
    return b
df['C'] = func(df['B'].to_numpy(),df['D'].to_numpy(),df['C'].to_numpy())
df

但它不起作用。

第一行和第二行结果正常:

'C': [0, 1.666666667, -1.114286, 1.781250, -1.371429, 5.419355, -0.666667]

我已经尝试过“转变”(sammywemmy 的建议)。在“vaex.from_csv”之前的这个示例数据帧可以正常工作,但是当通过 vaex 将概念实现到大数据帧时,移位不起作用。

所以,问题是:是否有一种“良好实践”的方法来执行这种演算(迭代“C”列中的一行的结果,考虑到“C”中的前几行)使用大型数据源(I´ m 使用 vaex 从 100 万行 csv 导入)?

提前致谢。

【问题讨论】:

  • 试试这个:df.B.shift(-1).sub(df.B).div(df.B).mul(df.D.shift(-1)).cumsum().shift(fill_value=0)
  • sammywemmy,感谢您的快速回答和帮助...它非常适合我的示例 createad 和一个简单的 pandas 数据框!谢谢!但是......当我尝试将这个概念从 vaex 实施到大数据框架时,它不起作用。显示消息:'AttributeError: 'Expression' object has no attribute 'shift''。感谢您的帮助...
  • 我对vaex不熟悉;你可以看看他们的 API 看看是否有替代 shift
  • 再次感谢您的帮助和善意。谢谢!

标签: python pandas numpy numba vaex


【解决方案1】:

我不确定它是否是最佳解决方案,但至少它是有效的:您可以使用 apply 方法并将 vectorize 设置为 True

这是完整的sn-p:

import numba
import numpy as np
import pandas as pd
import vaex

d = {'A':[0,1,2,3,4,5,6],'B':[30,35,32,35,31,39,37],'D':[12,10,13,19,12,21,13],'P':[3,3,3,3,3,3,3]}
df = pd.DataFrame(data=d)

df['C'] = 0

df

# I removed the b_0 for simplicity
def my_func(B, D, C):
    n = len(B)
    b = np.full(n, 0, dtype=np.float64)
    for i in range(1, n):
        b[i] = ((((B[i] - B[i - 1]) / B[i - 1])) * D[i]) + C[i-1]

    return b

df_vaex = vaex.from_pandas(df)

df_vaex.apply(my_func, arguments=[df_vaex["B"], df_vaex["D"], df_vaex["C"]], vectorize=True)

它给出了预期的输出:

0          0
1    1.66667
2   -1.11429
3    1.78125
4   -1.37143
5    5.41935
6  -0.666667

基本上,apply 方法允许逐行应用函数,如果将 vectorize 设置为 True,则将传递完整的数组而不是行值。在您的情况下,这是强制性的,因为您需要前几行的值来计算给定行中的 C 值。

【讨论】:

  • 完美!我很高兴在不需要“转变”的情况下取得成果并学到更多东西!非常感谢!
  • 完美!另一个建议是实现 vaex 的 shift 方法,在这里您可以找到与此任务相关的答案:stackoverflow.com/a/61075267/8056572
  • 嗨,我试图了解您的解决方案,但我想我迷路了?在您发布的代码中,您绝不会将结果存储在“C”列中。那么在计算中如何/何时检索上一行'C[i-1]'的结果以用于下一行'C[i]'?感谢您的澄清。
猜你喜欢
  • 2023-01-24
  • 2021-07-29
  • 2015-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
相关资源
最近更新 更多