data.matrix()当涉及角色时

Max*_*den 3 r character matrix data.table

为了计算每个ID的行的最高贡献,我有一个漂亮的脚本,当ID是数字时,它可以工作.然而今天我发现ID也可能有字符(例如ABC10101).要使功能起作用,数据集将转换为矩阵.但是data.matrix(df)不支持字符.是否可以更改代码以使函数能够处理各种ID(字符,数字等)?目前我写了一个快速的解决方法,当ID =字符时将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)
Run Code Online (Sandbox Code Playgroud)

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

    ID   contribution   uniqID      
   ABCUD022221       40           101  
   ABCUD022222       90           105
   ABCUD022223       75           106
Run Code Online (Sandbox Code Playgroud)

Rol*_*and 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
Run Code Online (Sandbox Code Playgroud)

编辑 - 更简洁的解决方案

  • 您可以使用.SD哪个是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
Run Code Online (Sandbox Code Playgroud)

  • 使它更简洁. - 无需合并. (2认同)