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

基于R语言计算促销产品与最近4个非促销周平均销售额比值

用R语言计算促销周销售额与非促销周均值的比值

嘿,我来帮你搞定这个计算需求!首先得明确你的数据集结构,我先假设你的数据框叫sales_data,包含以下核心字段:

  • product_id: 产品唯一ID
  • week: 周标识(可以是日期、周数字符串,比如"2024-W01",得是能排序的类型)
  • is_promotion: 促销标记(1代表促销周,0代表非促销周,就是你说的flag)
  • sales: 当期的销售额

接下来一步步实现你的需求:

1. 先给每个产品的周数据按时间排序

要取最近4个非促销周,必须先把每个产品的周数据按时间排好序,不然取到的就不是“最近”的了:

library(dplyr)
library(purrr) # 用来处理逐行的列表计算

# 按产品ID和周排序(如果week是字符串格式,建议先转成日期类型,比如用lubridate::parse_date_time(week, "%Y-W%U"))
sales_data_sorted <- sales_data %>%
  arrange(product_id, week)

2. 计算每个促销周对应的最近4个非促销周平均销售额

这里用dplyr的分组+窗口函数,结合purrr来逐行处理每个周的历史非促销数据:

sales_with_ratio <- sales_data_sorted %>%
  group_by(product_id) %>%
  # 先计算该产品所有非促销周的整体均值,作为没有历史数据时的兜底值
  mutate(overall_non_promo_avg = mean(sales[is_promotion == 0], na.rm = TRUE)) %>%
  mutate(
    # 对每个行,获取当前周之前的所有非促销周销售额
    past_non_promo_sales = map(week, ~ sales[is_promotion == 0 & week < .x]),
    # 计算最近4个非促销周的均值:够4个就取最后4个,不够就用现有全部,没有的话用兜底均值
    avg_past_non_promo = map_dbl(past_non_promo_sales, ~ {
      if (length(.x) >= 4) {
        mean(tail(.x, 4))
      } else if (length(.x) > 0) {
        mean(.x)
      } else {
        overall_non_promo_avg[1]
      }
    }),
    # 生成最终结果:促销周用销售额/均值,非促销周直接用当期销售额
    result_value = case_when(
      is_promotion == 1 ~ sales / avg_past_non_promo,
      TRUE ~ sales
    ),
    # 处理极端情况:如果连兜底均值都没有(比如产品从来没非促销过),标记为NA
    result_value = ifelse(is.nan(result_value), NA_real_, result_value)
  ) %>%
  ungroup() %>%
  # 保留需要的字段,去掉中间临时列
  select(product_id, week, is_promotion, sales, avg_past_non_promo, result_value)

3. 输出符合指定格式的结果

如果需要输出成CSV文件(最常用的格式),直接用:

# 可以先把数值格式化为两位小数,让结果更整洁
sales_with_ratio_formatted <- sales_with_ratio %>%
  mutate(across(c(sales, avg_past_non_promo, result_value), ~ round(.x, 2)))

write.csv(sales_with_ratio_formatted, "promotion_sales_ratio.csv", row.names = FALSE)

如果需要其他格式(比如Excel),可以用writexl::write_xlsx()函数,先安装包就行:install.packages("writexl")

小提醒

  • 要是你的week字段是类似"2024-W01"的字符串,记得先转成可排序的日期类型,不然排序会出错:
    library(lubridate)
    sales_data$week <- parse_date_time(sales_data$week, "%Y-W%U")
    
  • 如果不需要兜底均值,想直接把没有历史非促销数据的促销周标记为NA,把overall_non_promo_avg[1]改成NA_real_就行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:15:35