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

基于data.table计算企业年度技术专利类别放弃数(3/5年窗口)

问题描述

需要在包含企业与专利类别的数据库中计算「技术放弃数(Technological abandonment)」变量:

  • 定义:企业每年放弃的原活跃技术专利类别数量
  • 计算规则:
    1. 统计企业过去N年窗口(如3年窗口为t-3、t-2、t-1;若企业历史不足N年,则统计所有已有历史年份)中使用过,但本年(t)未使用的专利类别数量
    2. 需同时支持3年、5年两种窗口计算
  • 约束:数据集规模达数百万行,优先采用高效的data.table方案

示例数据集

library(data.table)
df <- data.table(
  year = c(1979,1979,1980,1980,1981,1981,1982,1983,1983,1984,1984),
  category = c("A","A","B","C","A","D","F","F","C","A","B")
)

注:示例中省略了企业ID字段,实际场景需按企业分组计算

3年窗口预期输出

year category tech_aband_3
 1: 1979        A            0
 2: 1979        A            0
 3: 1980        B            1
 4: 1980        C            1
 5: 1981        A            2
 6: 1981        D            2
 7: 1982        F            4
 8: 1983        F            3
 9: 1983        C            3
10: 1984        A            3
11: 1984        B            3

高效data.table实现方案

核心思路:先提取每个企业每年的唯一活跃专利类别,再通过滚动窗口统计历史活跃类别集合,最后对比本年类别计算放弃数量,全程用data.table的向量化操作保证效率。

步骤1:数据预处理(去重)

同一企业同一年可能有多条同一类别的记录,先去重得到「企业-年份-唯一类别」的精简数据集:

# 实际场景需加入企业ID(如firm_id)作为分组键
unique_df <- unique(df, by = c("year", "category"))

步骤2:定义通用窗口计算函数

封装函数支持任意N年窗口计算,复用性更强:

calc_tech_abandon <- function(dt, window_size = 3) {
  # 按年份排序,保证窗口逻辑正确
  setorder(dt, year)
  
  # 1. 计算每个年份的历史窗口范围:最小年份到t-1,且不超过窗口上限
  dt[, `:=`(
    window_start = pmax(min(year), year - window_size),
    window_end = year - 1
  ), by = .(category)] # 实际场景替换为by = .(firm_id)
  
  # 2. 用非等值join匹配窗口内所有历史活跃类别
  historical_classes <- dt[dt, 
                          on = .(year >= window_start, year <= window_end),
                          allow.cartesian = TRUE,
                          .(current_year = i.year, hist_category = x.category)]
  
  # 3. 按当前年份聚合,得到去重后的历史类别集合
  hist_summary <- historical_classes[, 
                                    .(hist_classes = list(unique(hist_category))),
                                    by = current_year]
  
  # 4. 统计本年的活跃类别集合
  current_summary <- dt[, .(current_classes = list(unique(category))), by = year]
  
  # 5. 计算放弃数量:历史类别总数 - 历史与本年的交集数量
  combined <- merge(current_summary, hist_summary, by.x = "year", by.y = "current_year", all.x = TRUE)
  combined[, `:=`(
    hist_count = sapply(hist_classes, length),
    intersect_count = mapply(function(h, c) length(intersect(h, c)), hist_classes, current_classes)
  )]
  combined[, tech_aband := hist_count - intersect_count]
  
  # 处理初始年份(无历史数据时放弃数为0)
  combined[is.na(tech_aband), tech_aband := 0]
  
  # 6. 合并回原数据集,补全重复行的计算结果
  result <- merge(df, combined[, .(year, tech_aband)], by = "year", all.x = TRUE)
  setnames(result, "tech_aband", paste0("tech_aband_", window_size))
  
  return(result)
}

步骤3:执行计算

# 计算3年窗口结果
result_3 <- calc_tech_abandon(df, window_size = 3)
# 计算5年窗口结果
result_5 <- calc_tech_abandon(df, window_size = 5)

# 合并两个窗口的结果(可选)
final_result <- merge(result_3, result_5, by = c("year", "category"))

性能优化说明

  • 提前用unique()去重,大幅减少后续计算的数据量
  • 用非等值join替代循环遍历,利用data.table的高效索引加速匹配
  • 用列表存储类别集合,避免重复计算去重逻辑
  • 全程采用向量化操作,适配百万级甚至更大规模的数据集

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 00:55:03