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

R语言按分组计算月度在网用户滚动累计值的实现方法

R语言实现月度滚动在网用户量统计

核心思路

直接按月聚合订阅记录出现重复计数,本质是没有将用户生命周期转化为时间维度的增减量事件。正确计算逻辑如下:

  • 过滤退订时间早于订阅时间的异常无效记录
  • 每条有效订阅对应两个计数事件:用户订阅当月在网数+1,用户退订当月在网数-1;未退订(unique_unsubs为NA)的用户不生成减事件,持续计入后续在网量
  • 按国家维度生成数据覆盖周期内的完整月度序列,避免出现月份空缺
  • 按国家分组对每月的增减量做累计求和,即可得到每个月度节点的去重在网用户总量,同一用户在在网周期内的重复订阅会被事件增量自动抵消,不会重复计数

完整实现代码

代码依赖tidyverse和lubridate包,可直接衔接已完成的重复退订清洗步骤运行:

library(tidyverse)
library(lubridate)

# 1. 重复退订数据清洗(补充类型一致性处理,避免if_else类型报错)
dat <- dat %>%
  mutate(
    across(c(subscribed_at, unsubscribed_at), as.POSIXct),
    unsub_date = as.Date(unsubscribed_at)
  ) %>%
  group_by(account_id, unsub_date) %>%
  mutate(
    unique_unsubs = if_else(
      row_number() %in% which.max(unsubscribed_at), 
      unsubscribed_at, 
      as.POSIXct(NA_real_, origin = "1970-01-01")
    )
  ) %>%
  ungroup() %>%
  select(-c(unsubscribed_at, unsub_date)) %>%
  filter(!is.na(subscribed_at))

# 2. 过滤异常记录:退订时间早于订阅时间的无效数据
dat_valid <- dat %>%
  filter(is.na(unique_unsubs) | subscribed_at <= unique_unsubs)

# 3. 生成用户增减事件
user_events <- dat_valid %>%
  # 订阅事件:当月新增在网+1
  transmute(
    country,
    account_id,
    event_month = floor_date(as.Date(subscribed_at), unit = "month"),
    delta = 1
  ) %>%
  bind_rows(
    # 退订事件:当月流失在网-1,未退订用户不生成减项
    dat_valid %>%
      filter(!is.na(unique_unsubs)) %>%
      transmute(
        country,
        account_id,
        event_month = floor_date(as.Date(unique_unsubs), unit = "month"),
        delta = -1
      )
  )

# 4. 生成完整月度序列,计算滚动累计值
month_range <- seq(
  from = floor_date(min(as.Date(dat_valid$subscribed_at)), "month"),
  to = floor_date(
    max(c(as.Date(dat_valid$subscribed_at), as.Date(dat_valid$unique_unsubs)), na.rm = T), 
    "month"
  ),
  by = "month"
)

result <- expand_grid(
  country = unique(dat_valid$country),
  month = month_range
) %>%
  left_join(
    user_events %>% 
      group_by(country, event_month) %>% 
      summarise(total_delta = sum(delta), .groups = "drop"),
    by = c("country" = "country", "month" = "event_month")
  ) %>%
  mutate(
    total_delta = replace_na(total_delta, 0),
    running_total = cumsum(total_delta),
    .by = country
  ) %>%
  select(month, running_total, country)

结果验证

针对提供的示例数据,筛选US地区的输出和期望格式、数值完全匹配:

# A tibble: 11 × 3
   month      running_total country
   <date>             <dbl> <chr>  
 1 2016-06-01             1 US     
 2 2016-07-01             0 US     
 3 2016-08-01             0 US     
 4 2016-09-01             0 US     
 5 2016-10-01             0 US     
 6 2016-11-01             0 US     
 7 2016-12-01             0 US     
 8 2017-01-01             1 US     
 9 2017-02-01             2 US     
10 2017-03-01             2 US     
11 2017-04-01             1 US     

逻辑说明

  • 同一用户在未退订期间产生的重复订阅记录,会生成等额的+1和-1事件,自动抵消不会造成重复计数
  • 退订后重新订阅的用户,会在重新订阅当月再次计入在网量,符合流失后回流的统计规则
  • 未填写退订时间的用户会永久计入在网量,若后续补充退订时间,重新运行代码即可自动修正历史统计值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:03:23