Pandas DataFrame新增列计算自上一个顶/底以来的数值变化率
问题解答
你之前的两种写法报错原因如下:
shift()只接受单个整数作为全局偏移参数,不能传入Series类型的变量为每一行指定不同偏移量,因此触发ValueError: The truth value of a Series is ambiguous报错。iloc直接传入df.index - df['ST'].abs()时,pandas会执行索引对齐逻辑而非逐行计算位置,无法正确匹配到对应行的数值,因此触发重索引错误。
正确实现方案
实现思路:提取所有局部顶/底(即TB列非空)对应的A列值作为基准值,向下填充到所有行,再用当前行的A值除以上一个基准值,即可得到所需的变化率。
完整代码如下:
import pandas as pd import numpy as np df = pd.DataFrame([8, 2, 4, 5, 6, 4, 3, 5, 5, 3, 2], columns=['A']) df['UD'] = np.where(df['A'].pct_change().gt(0), 1, np.where(df['A'].pct_change().lt(0), -1, 0)) df['ST'] = df['UD'].groupby((df['UD'].ne(df['UD'].shift(1))).cumsum()).cumsum() df['TB'] = np.where(df['A'].pct_change().ge(0) & df['A'].pct_change().shift(-1).le(0), 'T', np.where(df['A'].pct_change().le(0) & df['A'].pct_change().shift(-1).ge(0), 'B', '')) # 新增C列逻辑 # 提取TB点的A值作为基准,其余位置为空 df['base'] = df['A'].where(df['TB'].ne('')) # 向下填充基准值,每一行对应上一个TB点的基准值 df['base'] = df['base'].ffill() # 计算变化率,保留2位小数,无有效结果的位置置空 df['C'] = (df['A'] / df['base'].shift(1)).round(2).fillna('') # 删除临时基准列 df = df.drop('base', axis=1) print(df)
运行输出和你给出的预期结果完全一致。
内容的提问来源于stack exchange,提问作者Jane Doe
相关产品推荐
相关产品推荐

