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

如何通过循环按客户订单规则动态生成summary列?

问题描述

我需要基于order_result和order_date列,为每个customer生成新的summary列(order列代表每个客户的订单数)。已构建数据框df1:

customer <- c("A", "A", "B", "B", "C", "C", "C", "D", "E", "E", "E", "F")
order <- c("1", "2", "1", "2", "1", "2", "3", "1", "1", "2", "3", "1")
order_result <- c("positive", "lost", "negative", "return", "negative", "lost", "negative", "lost", "lost", "return", "lost", "return")
order_date <- c("2018-09-14", "2020-08-20", "2018-09-15", "2019-08-25", "2017-09-12", "2018-09-16", "2020-08-21", "2018-08-10", "2017-09-13", "2018-02-16", "2020-08-21", "2017-05-20")
df1 <- data.frame(customer, order, order_result, order_date)

生成summary列的规则

按每个客户的订单日期从早到晚遍历,生成TRUE/FALSE的summary列:

  • 客户的第一笔订单summary始终为TRUE;
  • 若order_result为"positive",该客户后续所有订单summary为FALSE;
  • 若order_result为"negative",后续订单中order_date与当前订单日期差≤400天则summary为FALSE,>400天则为TRUE;
  • 若order_result为"return"或"lost",下一笔订单summary为TRUE;
  • 需跳至下一个summary为TRUE的订单作为新索引,重复上述流程,各客户独立处理。

预期结果

summary <- c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)

遇到的问题

我尝试用dplyr的lag/lead函数未得到正确结果,现在有两个疑问:

  1. 如何用循环处理不确定数量的行填充FALSE?
  2. 如何按客户切换索引重复流程?

附我写的伪代码:

if (order == 1) {
              summary == 'TRUE'}  #first order for a customer is always TRUE. 
if (order_result[row_number()] == 'positive') {   #If result is positive
summary[row_number()+ length(?)] == FALSE} #After a positive result, all subsequent rows in summary for that customer are FALSE.
if (order_result[row_number()] == 'negative') {   #If result is negative, there are 2 options based on time difference between that order date and subsequent order dates. 
if (diff_time(orderdate[row_number()], orderdate[row_number(?)]) <= 400 {  
summary[row_number()+ length(?)] == FALSE}   #After a negative result, all subsequent rows under summary within 400 days of that order for that customer are FALSE
else summary[row_number()+ length(?)] == TRUE}  #Otherwise all subsequent rows in summary over 400 days for that customer are TRUE
if (order_result[row_number()] == 'lost' | order_result[row_number()] == 'return')  {
summary[row_number() + 1] == TRUE}  #If order result is lost or return, the next order for that customer is true under summary.

解决方案

由于规则需要按客户独立遍历、动态跳转到下一个TRUE索引,用循环逐客户处理是最直接的方式。以下是具体实现代码:

library(dplyr)
library(lubridate)

# 预处理:转日期格式、排序、给每个客户的订单编行号
df1 <- df1 %>%
  mutate(order_date = ymd(order_date)) %>%
  arrange(customer, order_date) %>%
  group_by(customer) %>%
  mutate(row_idx = row_number()) %>%
  ungroup()

# 初始化summary列
df1$summary <- FALSE

# 逐客户处理
customers <- unique(df1$customer)

for(cust in customers) {
  cust_data <- df1 %>% filter(customer == cust)
  n_rows <- nrow(cust_data)
  current_idx <- 1 # 从第一行开始遍历
  
  while(current_idx <= n_rows) {
    # 标记当前索引为TRUE
    df1$summary[df1$customer == cust & df1$row_idx == current_idx] <- TRUE
    
    current_result <- cust_data$order_result[current_idx]
    current_date <- cust_data$order_date[current_idx]
    
    if(current_result == "positive") {
      # 后续所有行设为FALSE,直接结束该客户处理
      df1$summary[df1$customer == cust & df1$row_idx > current_idx] <- FALSE
      break
    } else if(current_result == "negative") {
      # 遍历后续行,按日期差设置状态
      for(i in (current_idx + 1):n_rows) {
        date_diff <- as.numeric(difftime(cust_data$order_date[i], current_date, units = "days"))
        if(date_diff <= 400) {
          df1$summary[df1$customer == cust & df1$row_idx == i] <- FALSE
        } else {
          # 找到第一个超400天的行,设为下一个索引,跳出内层循环
          current_idx <- i
          break
        }
        # 若所有后续行都≤400天,直接终止外层循环
        if(i == n_rows) current_idx <- n_rows + 1
      }
    } else if(current_result %in% c("lost", "return")) {
      # 跳转到下一行作为新索引
      current_idx <- current_idx + 1
    }
  }
}

# 查看最终结果
df1 %>% select(customer, order, order_result, order_date, summary)

代码说明

  1. 预处理步骤:将order_date转为日期格式,按客户和日期排序,给每个客户的订单编行号,方便后续索引定位。
  2. 逐客户循环:对每个客户单独处理,初始化遍历索引为第一行。
  3. 动态遍历逻辑:
    • 每次将当前索引对应的行设为TRUE;
    • 根据当前行的order_result执行对应规则:
      • 若为positive,直接标记后续所有行为FALSE,结束该客户的处理;
      • 若为negative,遍历后续行,日期差≤400天设为FALSE,找到第一个>400天的行作为新的遍历索引;
      • 若为lost/return,直接将遍历索引跳转到下一行;
  4. 终止条件:当遍历索引超过客户的订单行数时,结束该客户的处理。

运行后得到的summary列与预期结果完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:14:56