基于R语言识别销售数据规律:过滤周期性零销量产品
解决周期性零销量产品的过滤问题
要过滤掉存在固定间隔零销量规律的产品,核心是识别每个产品零销量日期的时间间隔是否存在重复的固定模式。下面是基于你现有代码的改进方案,包含完整的周期性检测逻辑:
步骤1:定义周期性检测函数
首先写一个函数,用来判断某个产品的零销量是否有固定周期:
# 检测产品是否存在周期性零销量规律 detect_periodic_zero <- function(dates, sale_counts) { # 筛选出所有销量为0的日期 zero_dates <- dates[sale_counts == 0] # 如果零销量日期不足2个,无法判断周期性 if (length(zero_dates) < 2) { return(FALSE) } # 计算相邻零销量日期的间隔天数 interval_days <- as.numeric(diff(zero_dates)) # 统计各间隔天数的出现频率 interval_freq <- table(interval_days) max_freq_ratio <- max(interval_freq) / length(interval_days) # 如果超过80%的间隔是同一个固定值(可根据需求调整阈值),判定为有周期性 return(max_freq_ratio >= 0.8) }
步骤2:整合到现有工作流
你的现有代码把数据转成了宽格式,但周期性检测需要按产品查看完整的时间序列,所以我们先保留长格式处理周期性,再合并回宽格式结果:
library(dplyr) library(tidyr) # 读取并预处理数据(修正日期格式为Date类型,之前转character是错误的) csv <- read.csv('result_branch.csv') csv$INCENTIVE_DATE <- as.Date(csv$INCENTIVE_DATE, format = "%m/%d/%Y") csv$COST_CENTER <- as.character(csv$COST_CENTER) # 用长格式数据检测每个产品的周期性 periodic_check <- csv %>% group_by(PRODUCT_DESCRIPTION) %>% summarise(has_periodic_zero = detect_periodic_zero(INCENTIVE_DATE, Sale_Count), .groups = "drop") # 继续执行你原来的宽格式处理流程 wide_data <- csv %>% spread(INCENTIVE_DATE, Sale_Count) %>% replace(is.na(.), 0) %>% mutate( prod_mean = round(rowMeans(select(., -COST_CENTER, -PRODUCT_DESCRIPTION)), 2), # 建议用列名代替索引,比如假设当日是最后一列:last_col() Today_Missing = select(., last_col()) == 0, Red_Flag = Today_Missing & prod_mean > 10 ) # 合并周期性标记并过滤掉有周期性的产品 final <- wide_data %>% left_join(periodic_check, by = "PRODUCT_DESCRIPTION") %>% # 只保留无周期性零销量的产品,同时保留Red_Flag的筛选逻辑 filter(!has_periodic_zero | is.na(has_periodic_zero)) %>% arrange(-Red_Flag, -prod_mean) rownames(final) <- final$COST_CENTER
关键说明
- 日期格式修正:必须把
INCENTIVE_DATE转成Date类型,这样才能正确计算日期间隔,之前转成character会导致间隔计算错误。 - 阈值调整:函数里的
0.8是指80%的零销量间隔一致就判定为周期性,你可以根据业务场景调整(比如严格周期性可以设为1,即所有间隔都相同)。 - 列索引替代:建议用
last_col()代替[,23]这样的硬编码索引,避免数据列顺序变化导致错误。
内容的提问来源于stack exchange,提问作者jamesB
相关产品推荐
相关产品推荐

