3

为了计算每个 ID 的行的最高贡献,我有一个漂亮的脚本,当 ID 是数字时它可以工作。然而,今天我发现 ID 也可能有字符(例如 ABC10101)。为了使函数起作用,数据集被转换为矩阵。但是data.matrix(df)不支持字符。是否可以更改代码以使函数与各种 ID(字符、数字等)一起使用?目前,我编写了一个快速解决方法,当 ID=character 时将 ID 转换为数字,但这会减慢大型数据集的处理速度。

代码示例(功能:提取贡献最高的第一个条目,因此如果 2 个条目具有相同的贡献,则选择第一个):

注意:在此示例中,ID 被解释为一个因子,data.matrix() 将其转换为数值。在下面的代码中,ID 列的类型应为字符,输出应如底部所示。订单 ID 必须保持不变。

tc <- textConnection('
    ID   contribution   uniqID      
   ABCUD022221       40           101  
   ABCUD022221       40           102 
   ABCUD022222       20           103
   ABCUD022222       10           104
   ABCUD022222       90           105
   ABCUD022223       75           106
   ABCUD022223       15           107
   ABCUD022223       10           108        ')

df <- read.table(tc,header=TRUE)

#Function that needs to be altered
uniqueMaxContr <- function(m, ID = 1, contribution = 2) {
  t(
    vapply(
           split(1:nrow(m), m[,ID]), 
           function(i, x, contribution) x[i, , drop=FALSE]
           [which.max(x[i,contribution]),], m[1,], x=m, contribution=contribution
          )
  )
}

df<-data.matrix(df) #only works when ID is numeric
highestdf<-uniqueMaxContr(df)
highestdf<-as.data.frame(highestdf)

在这种情况下,结果应该是:

    ID   contribution   uniqID      
   ABCUD022221       40           101  
   ABCUD022222       90           105
   ABCUD022223       75           106
4

1 回答 1

7

其他人可能可以使它更简洁,但这是我对 data.table 解决方案的尝试:

tc <- textConnection('
    ID   contribution   uniqID      
   ABCUD022221       40           101  
   ABCUD022221       40           102 
   ABCUD022222       20           103
   ABCUD022222       10           104
   ABCUD022222       90           105
   ABCUD022223       75           106
   ABCUD022223       15           107
   ABCUD022223       10           108        ')

df <- read.table(tc,header=TRUE)

library(data.table)
dt <- as.data.table(df)
setkey(dt,uniqID)

dt2 <- dt[,list(contribution=max(contribution)),by=ID]

setkeyv(dt2,c("ID","contribution"))
setkeyv(dt,c("ID","contribution"))

dt[dt2,mult="first"]

##               ID contribution uniqID
## [1,] ABCUD022221           40    101
## [2,] ABCUD022222           90    105
## [3,] ABCUD022223           75    106

编辑——更简洁的解决方案

  • 您可以使用.SDwhich 是 data.table 的子集进行分组,然后使用它which.max来提取单行。

在一行中

dt[,.SD[which.max(contribution)],by=ID]

##               ID contribution uniqID
## [1,] ABCUD022221           40    101
## [2,] ABCUD022222           90    105
## [3,] ABCUD022223           75    106
于 2012-09-10T09:52:00.857 回答