按组迭代的不同 类 个因子的欧氏距离

Euclidean distant for distinct classes of factors iterated by groups

*更新:Rui 建议的答案很好,可以正常工作。然而,当我 运行 它进行了大约 700 万次观察(我的实际数据集)时,R 卡在了一个计算块中(我使用的是具有 64gb RAM 的机器)。非常感谢任何其他解决方案!

我有一个专利数据框,包括公司、申请年份、专利号和专利 classes。我想根据以下公式计算每个公司基于专利 classes 的连续年份之间的欧氏距离:

其中Xi表示t年属于特定class的专利数,Yi表示上一年(t-1)属于特定class的专利数.

为了进一步说明这一点,请考虑以下数据集:

df <- data.table(Firm = rep(c(LETTERS[1:2]),each=6), Year = rep(c(1990,1990,1991,1992,1992,1993),2),
                   Patent_Number = sample(184785:194785,12,replace = FALSE),
                   Patent_Class = c(12,5,31,12,31,6,15,15,15,3,3,1))
> df
    Firm Year Patent_Number Patent_Class
 1:    A 1990        192473           12
 2:    A 1990        193702            5
 3:    A 1991        191889           31
 4:    A 1992        193341           12
 5:    A 1992        189512           31
 6:    A 1993        185582            6
 7:    B 1990        190838           15
 8:    B 1990        189322           15
 9:    B 1991        190620           15
10:    B 1992        193443            3
11:    B 1992        189937            3
12:    B 1993        194146            1

由于 1990 年是公司 A 的开始年份,因此该年没有欧几里得距离(应生成 NA。前进到 1991 年,今年 (1991) 的不同 classses和前一年 (1990) 分别是 31、5 和 12。因此,上面的公式对这三个不同的 classes 求和(有三个不同的 'i's)。所以公式的输出将是:

经过相同的计算并重复公司,最终输出应为:

> df
    Firm Year Patent_Number Patent_Class   El_Dist
 1:    A 1990        192473           12        NA
 2:    A 1990        193702            5        NA
 3:    A 1991        191889           31 1.2247450
 4:    A 1992        193341           12 0.7071068
 5:    A 1992        189512           31 0.7071068
 6:    A 1993        185582            6 1.2247450
 7:    B 1990        190838           15        NA
 8:    B 1990        189322           15        NA
 9:    B 1991        190620           15 0.5000000
10:    B 1992        193443            3 1.1180340
11:    B 1992        189937            3 1.1180340
12:    B 1993        194146            1 1.1180340

为了提高速度,我最好寻找 data.table 解决方案。

非常感谢您的帮助。

我相信下面的函数可以满足问题的要求,但是 Firm == "B" 的结果不等于问题的结果。

fEl_Dist <- function(X){
  Year <- X[["Year"]]
  PatentClass <- X[["Patent_Class"]]
  sapply(seq_along(Year), function(i){
    j <- which(Year %in% (Year[i] - 1:0))
    tbl <- table(Year[j], PatentClass[j])
    if(NROW(tbl) == 1){
      NA_real_
    } else {
      numer <- sum((tbl[2, ] - tbl[1, ])^2)
      denom <- sum(tbl[2, ]^2)*sum(tbl[1, ]^2)
      sqrt(numer/denom)
    }
  })
}
  
setDT(df)[, El_Dist := fEl_Dist(.SD), 
          by = .(Firm),
          .SDcols = c("Year", "Patent_Class")]

head(df)
#   Firm Year Patent_Number Patent_Class   El_Dist
#1:    A 1990        190948           12        NA
#2:    A 1990        186156            5        NA
#3:    A 1991        190801           31 1.2247449
#4:    A 1992        185226           12 0.7071068
#5:    A 1992        185900           31 0.7071068
#6:    A 1993        186928            6 1.2247449