目标:从矩阵或数据框中查找每行的最低n
值。对于此示例,我们希望找到每行的3个最低值。我们想用
rowname | colname_min | value_min | colname_min2 | value_min2 | colname_min3 | value_min3
出发点:我修改了这个问题的答案:R getting the minimum value for each row in a matrix, and returning the row and column name
这是我修改后的代码:
df<-data.frame(matrix(data=round(x=rnorm(100,10,1),digits=3),nrow=10),
row.names=c("A","B","C","D","E","F","G","H","I","J"))
colnames(df)<-c("AD","BD","CD","DD","ED","FD","GD","HD","ID","JD")
result <- t(sapply(seq(nrow(df)), function(i) {
j <- apply(df, 1, function(x){order(x, decreasing=F)[1:3]})
c(rownames(df)[i], colnames(df)[j[1,i]], as.numeric(df[i,j[1,i]]),
colnames(df)[j[2,i]], as.numeric(df[i,j[2,i]]),
colnames(df)[j[3,i]], as.numeric(df[i,j[3,i]]))
}))
这是有效的,并且它适用于小示例data.frame。但是,我正在使用的data.frame有200,000行和300列。在我的机器上,代码现在运行约1小时,仍在工作。任何想法如何优化代码?我在想dplyr
,但找不到解决方案。非常感谢帮助。
答案 0 :(得分:3)
您可以使用此基本R解决方案,该解决方案对每行进行排序并选择n.min
最低值及其索引:
示例数据
N <- 5
n.min <- 2
set.seed(1)
m <- matrix(runif(N^2),N)
rownames(m) <- letters[1:N]
colnames(m) <- LETTERS[1:N]
# A B C D E
# a 0.2655087 0.89838968 0.2059746 0.4976992 0.9347052
# b 0.3721239 0.94467527 0.1765568 0.7176185 0.2121425
# c 0.5728534 0.66079779 0.6870228 0.9919061 0.6516738
# d 0.9082078 0.62911404 0.3841037 0.3800352 0.1255551
# e 0.2016819 0.06178627 0.7698414 0.7774452 0.2672207
代码
f <- function(rw) {
O <- order(rw)[1:n.min]
rbind(O,rw[O])
}
result <- t(apply(m,1,f))
示例数据的输出
# [,1] [,2] [,3] [,4]
# a 3 0.20597457 1 0.2655087
# b 3 0.17655675 5 0.2121425
# c 1 0.57285336 5 0.6516738
# d 5 0.12555510 4 0.3800352
# e 2 0.06178627 1 0.2016819
<强>更新强>
如果您想按列名替换列号,您可以另外执行以下操作:
d <- as.data.frame(result)
d[,c(T,F)] <- colnames(m)[unlist(d[,c(T,F)])]
请注意,通过这种方式,您可以避免将数字强制转换为字符串,然后向后转换为数字格式,这对于大型数据集来说可能代价很高。