如何用Pandas实现递推公式计算新列C且避免逐行迭代?
问题描述
假设存在如下测试DataFrame:
data = {'A': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100], 'B': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] } df = pd.DataFrame(data)
输出结果:
A B 0 10 1 1 20 2 2 30 3 3 40 4 4 50 5 5 60 6 6 70 7 7 80 8 8 90 9 9 100 10
需要计算列C,满足递推公式:Ci = (Ci-1 * Ai-1 + Bi * (Ai - Ai-1)) / Ai(注:从代码和期望结果反推,公式需包含除以Ai的操作)。
我尝试了以下代码:
df["C"] = df["B"] df["C"] = (df["C"].shift(1, fill_value=0) * df["A"].shift(1, fill_value=0) + df["B"] * (df["A"] - df["A"].shift(1, fill_value=0)))/df["A"]
得到如下结果:
A B C 0 10 1 1.000000 1 20 2 1.500000 2 30 3 2.333333 3 40 4 3.250000 4 50 5 4.200000 5 60 6 5.166667 6 70 7 6.142857 7 80 8 7.125000 8 90 9 8.111111 9 100 10 9.100000
但期望的结果是:
A B C 0 10 1 1 1 20 2 1.5 2 30 3 2 3 40 4 2.5 4 50 5 3 5 60 6 3.5 6 70 7 4 7 80 8 4.5 8 90 9 5 9 100 10 5.5
请问是否有不通过逐行迭代的方法实现正确计算?
解决方案
你的代码问题在于,shift操作只会取列的原始前一行值,无法利用递推产生的中间C值,所以无法实现真正的递推逻辑。我们可以通过公式变形,将递推转化为向量化的累积运算:
公式变形
把递推公式整理为:Ci * Ai = Ci-1 * Ai-1 + Bi*(Ai - Ai-1)
令Di = Ci * Ai,则公式简化为:Di = Di-1 + Bi*(Ai - Ai-1)
这就变成了一个累积求和的问题,完全可以用Pandas的向量化操作实现。代码实现
import pandas as pd data = {'A': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100], 'B': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]} df = pd.DataFrame(data) # 计算Ai与前一行Ai的差值,首行填充0 delta_A = df['A'].sub(df['A'].shift(1, fill_value=0)) # 计算Bi*(Ai - Ai-1)项 terms = df['B'] * delta_A # 计算Di的累积和,首项刚好匹配D0=10(对应C0=1) D = terms.cumsum() # 还原得到Ci = Di / Ai df['C'] = D / df['A'] print(df)运行结果
A B C 0 10 1 1.0 1 20 2 1.5 2 30 3 2.0 3 40 4 2.5 4 50 5 3.0 5 60 6 3.5 6 70 7 4.0 7 80 8 4.5 8 90 9 5.0 9 100 10 5.5
全程为向量化操作,没有逐行迭代,效率远高于循环计算。
内容的提问来源于stack exchange,提问作者Andrew_097
相关产品推荐
相关产品推荐

