You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何遍历DataFrame并基于前置条件(含前置新增值)添加方向列

问题解决:基于DataFrame生成direction列

原始数据与需求

首先定义目标DataFrame:

import pandas as pd
df = pd.DataFrame({'timestamp': [123, 456, 789, 101112, 131415, 161718, 192021, 222324, 252627, 282930, 313233, 343536], 
                   'value': ["", "", "", 68, 47, 62, 62, 62, 62, 54, 54 , 54]})

需要生成第三列direction,规则如下:

  • 若value为空,则direction为空;
  • 若value > 前一行value,则direction = "positive";
  • 若value < 前一行value,则direction = "negative";
  • 若value = 前一行value 且 前一行direction为"positive",则direction = "positive";
  • 若value = 前一行value 且 前一行direction为"negative",则direction = "negative";

尝试的方法及问题

1. 循环遍历代码

for i in range(len(df)):
    if i == 0 :
        if df.iloc[i-1,'value'] > df.iloc[i,'value']:
           df.iloc[i,'direction'] = "positive"

报错:ValueError: Can only index by location with a [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array]
问题:iloc仅支持位置索引,不能传入列名;且i=0时i-1=-1会触发索引越界。

2. 另一种循环代码

for i in range(1, len(df) + 1):
    col = 'value'
    j = df.columns.get_loc('direction')
    if (df[col] > (df[col].shift(1))):
        df.loc[i - 1, j] = "positive"
    elif (df[col] < (df[col].shift(1))):
        df.loc[i - 1, j] = "negative"

报错:ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
问题:直接用Series做if判断会触发歧义,因为Series包含多个布尔值,无法直接判断真假。

3. 使用np.where

import numpy as np
df['positive']   = np.where( (df['value'] > df['value'].shift(1)) , "1",  "")
df['negative'] = np.where( (df['value'] < df['value'].shift(1)) , "1", "")

df['positive2']   = np.where( (df['positive'].shift(1)   =="1")  & (df['value'] == df['value'].shift(1)), "1", "0")
df['negative2'] = np.where( (df['negative'].shift(1) =="1") & (df['value'] == df['value'].shift(1)), "1","0")

问题:无报错但未实现预期效果,因为np.where是矢量化操作,无法依赖前一行的direction计算结果,无法处理连续相等值的继承逻辑。

解决方案

由于逻辑依赖前一行的计算结果,逐行循环是最直接的实现方式,步骤如下:

import pandas as pd

# 初始化DataFrame
df = pd.DataFrame({'timestamp': [123, 456, 789, 101112, 131415, 161718, 192021, 222324, 252627, 282930, 313233, 343536], 
                   'value': ["", "", "", 68, 47, 62, 62, 62, 62, 54, 54 , 54]})

# 将value列转为数值类型,空字符串转为NaN
df['value'] = pd.to_numeric(df['value'], errors='coerce')

# 初始化direction列
df['direction'] = ""

# 逐行遍历处理
for i in range(1, len(df)):
    # 当前value为空(NaN)时,保持direction为空
    if pd.isna(df.loc[i, 'value']):
        continue
    # 前一行value为空时,无对比基准,保持direction为空
    if pd.isna(df.loc[i-1, 'value']):
        continue
    
    # 数值比较逻辑
    if df.loc[i, 'value'] > df.loc[i-1, 'value']:
        df.loc[i, 'direction'] = "positive"
    elif df.loc[i, 'value'] < df.loc[i-1, 'value']:
        df.loc[i, 'direction'] = "negative"
    else:
        # 值相等时,继承前一行的direction
        df.loc[i, 'direction'] = df.loc[i-1, 'direction']

处理后结果

timestampvaluedirection
123NaN
456NaN
789NaN
10111268
13141547negative
16171862positive
19202162positive
22232462positive
25262762positive
28293054negative
31323354negative
34353654negative

方案说明

  1. 先将value列转为数值类型,空字符串转为NaN,方便空值判断和数值比较;
  2. 初始化direction列为空字符串;
  3. 从第2行(索引1)开始遍历,针对不同场景处理:
    • 当前值或前一行值为空时,保持direction为空;
    • 数值大小对比后设置对应direction;
    • 值相等时直接继承前一行的direction,完全符合需求。

内容的提问来源于stack exchange,提问作者chouchou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:39:34