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

在R中统计ID的年度事件数,包含无事件年份的0值

解决DataFrame中按ID统计起止日期内每年事件数(含无事件年份0值)

需求说明

需要统计每个ID在start到end日期范围内每年的事件发生数量,包含无事件年份的0值,而非仅统计有事件的年份。

示例数据

example<-data.frame(ID=c(1,1,1,1,2,2,3,3,3,3,3,3,3,3),
                    start=c("1998-05-01","1998-05-01","1998-05-01","1998-05-01",
                            "2020-07-20","2020-07-20",
                            "1977-12-23","1977-12-23","1977-12-23","1977-12-23",
                            "1977-12-23","1977-12-23","1977-12-23","1977-12-23"),
                    end=c("2007-05-01","2007-05-01","2007-05-01","2007-05-01",
                           "2021-07-20","2021-07-20",
                           "1990-12-23","1990-12-23","1990-12-23","1990-12-23",
                           "1990-12-23","1990-12-23","1990-12-23","1990-12-23"),
                    date_event=c("1998-06-05","2000-01-01","2002-11-30","2006-12-21",
                                 "2020-12-20","2020-12-25",
                                 "1978-02-23","1982-05-05","1983-06-20","1988-11-29",
                                 "1988-12-29","1990-01-01","1990-12-15","1990-12-15"))

现有尝试的问题

  • data.table代码:仅统计了有事件的年份,无法覆盖起止范围内的所有年份
    example[,year:=lubridate::year(date_event)]
    summary<-example[,.(contacts=.N),by=c("ID","year","start","end")]
    
  • dplyr代码:错误在于尝试全局生成年份水平,未按ID分组处理各自的起止年份,导致逻辑错误
    summary<-example %>% 
      transmute(ID, year_start=year(start), year_end=year(end),
                year=year(date_event),event=1) %>% 
      count(ID,event,year=factor(year,levels=unique(year_start:year_end)))
    

解决方案

核心思路:先为每个ID生成其起止日期范围内的所有年份,再与事件统计结果做左连接,将无事件年份的缺失值填充为0。

方法一:使用data.table实现

library(data.table)
library(lubridate)

# 转换为data.table并统一日期格式
setDT(example)
example[, c("start", "end", "date_event") := lapply(.SD, ymd), .SDcols = c("start", "end", "date_event")]

# 生成每个ID对应的全年份序列(从start年到end年)
id_full_years <- example[, .(year = seq(year(start)[1], year(end)[1], by = 1)), by = .(ID, start, end)]

# 统计每个ID每年的事件发生数
event_stats <- example[, .(contacts = .N), by = .(ID, year = year(date_event))]

# 左连接并填充无事件年份的0值
final_result_dt <- id_full_years[event_stats, on = .(ID, year), contacts := i.contacts]
final_result_dt[is.na(contacts), contacts := 0]

方法二:使用dplyr实现

library(dplyr)
library(lubridate)
library(tidyr)

# 处理日期格式,为每个ID生成全年份序列
id_full_years_dplyr <- example %>%
  mutate(across(c(start, end, date_event), ymd)) %>%
  distinct(ID, start, end) %>% # 去重ID的起止信息,避免重复生成年份
  rowwise() %>%
  mutate(year = list(seq(year(start), year(end), by = 1))) %>%
  unnest(year) # 展开年份列表为行

# 统计每个ID每年的事件数
event_stats_dplyr <- example %>%
  mutate(year = year(date_event)) %>%
  count(ID, year, name = "contacts")

# 左连接并填充0值
final_result_dplyr <- id_full_years_dplyr %>%
  left_join(event_stats_dplyr, by = c("ID", "year")) %>%
  mutate(contacts = replace_na(contacts, 0))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:46:13