为每一行返回最大值的列名称

我有一个员工名册,我需要知道他们最常在哪个部门工作。 将员工ID与部门名称进行制表是微不足道的,但是从频率表中返回部门名称而不是名册数量更为棘手。 下面是一个简单的例子(列名=部门,行名=员工ID)。

DF <- matrix(sample(1:9,9),ncol=3,nrow=3) DF <- as.data.frame.matrix(DF) > DF V1 V2 V3 1 2 7 9 2 8 3 6 3 1 5 4 

现在我怎么得到

 > DF2 RE 1 V3 2 V1 3 V2 

一个select使用您的数据(以备将来参考,使用set.seed()来举例使用sample重现):

 DF <- data.frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(9,6,4)) colnames(DF)[apply(DF,1,which.max)] [1] "V3" "V1" "V2" 

比使用apply更快的解决scheme可能是max.col

 colnames(DF)[max.col(DF,ties.method="first")] #[1] "V3" "V1" "V2" 

ties.method可以是任何"random" "first""last"

这当然会导致问题,如果你碰巧有两个列等于最大值。 我不确定你想在这个例子中做什么,因为你将有一个以上的结果一些行。 例如:

 DF <- data.frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(7,6,4)) apply(DF,1,function(x) which(x==max(x))) [[1]] V2 V3 2 3 [[2]] V1 1 [[3]] V2 2 

如果您对data.table解决scheme感兴趣,请点击这里。 这是有点棘手,因为你喜欢得到第一个最大的ID。 如果你想要最后的最大值,这会容易得多。 不过,这并不复杂,而且速度很快!

在这里我已经生成了你的尺寸(26746 * 18)的数据。

数据

 set.seed(45) DF <- data.frame(matrix(sample(10, 26746*18, TRUE), ncol=18)) 

data.table答案:

 require(data.table) DT <- data.table(value=unlist(DF, use.names=FALSE), colid = 1:nrow(DF), rowid = rep(names(DF), each=nrow(DF))) setkey(DT, colid, value) t1 <- DT[J(unique(colid), DT[J(unique(colid)), value, mult="last"]), rowid, mult="first"] 

标杆:

 # data.table solution system.time({ DT <- data.table(value=unlist(DF, use.names=FALSE), colid = 1:nrow(DF), rowid = rep(names(DF), each=nrow(DF))) setkey(DT, colid, value) t1 <- DT[J(unique(colid), DT[J(unique(colid)), value, mult="last"]), rowid, mult="first"] }) # user system elapsed # 0.174 0.029 0.227 # apply solution from @thelatemail system.time(t2 <- colnames(DF)[apply(DF,1,which.max)]) # user system elapsed # 2.322 0.036 2.602 identical(t1, t2) # [1] TRUE 

这些维度的数据速度快了11倍,而data.table相当好。


编辑:如果任何最大ID都可以,那么:

 DT <- data.table(value=unlist(DF, use.names=FALSE), colid = 1:nrow(DF), rowid = rep(names(DF), each=nrow(DF))) setkey(DT, colid, value) t1 <- DT[J(unique(colid)), rowid, mult="last"] 

基于以上build议,以下data.table解决scheme对我来说工作得非常快:

 set.seed(45) DT <- data.table(matrix(sample(10, 10^7, TRUE), ncol=10)) system.time( DT[, MAX := colnames(.SD)[max.col(.SD, ties.method="first")]] ) user system elapsed 0.10 0.02 0.21 DT V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 MAX 1: 7 4 1 2 3 7 6 6 6 1 V1 2: 4 6 9 10 6 2 7 7 1 3 V4 3: 3 4 9 8 9 9 8 8 6 7 V3 4: 4 8 8 9 7 5 9 2 7 1 V4 5: 4 3 9 10 2 7 9 6 6 9 V4 --- 999996: 4 6 10 5 4 7 3 8 2 8 V3 999997: 8 7 6 6 3 10 2 3 10 1 V6 999998: 2 3 2 7 4 7 5 2 7 3 V4 999999: 8 10 3 2 3 4 5 1 1 4 V2 1000000: 10 4 2 6 6 2 8 4 7 4 V1 

而且还带有这样的优点,即通过在.SDcols提及它们,可以始终指定哪些列.SD应考虑。

 DT[, MAX2 := colnames(.SD)[max.col(.SD, ties.method="first")], .SDcols = c("V9", "V10")]