我正在尝试创建一个 R 函数,该函数在值等于最大值的条目中随机选择一个条目,并逐行执行此操作。诀窍是,一旦我选择给定行的列,我不再希望该列被考虑用于后续行的选择。我还想知道有多少列的条目等于行最大值,以及该行的最大值到底是多少。我已经尝试了该主题的许多变体,这是我现在的代码。 Largemat 是一个 5000 行 x 20000 列的大矩阵。我尝试对其进行矢量化,但问题是这是一个动态过程,因此第 2 行的结果取决于为第 1 行选择的列。因此我不能立即选择行最大值,因为它们可能会发生变化。
这是前两行的示例:
第 1 行:.5, .5, 1, 1 第 2 行:.6、.8、.7、.9
所以我知道第 1 行的最大行数是 1,第 2 行的最大行数是 0.9。但是,如果我选择第四列(从第 1 行的第三列和第四列),那么我会从第 2 行的可能选择中删除该列(现在有候选项 0.6、.8、.7)
我正在努力思考如何提高效率。任何意见,将不胜感激。你们都是大师,我正在努力成为大师。因此,非常感谢任何建议!
这是我当前的 R 代码:
function(largemat, reordervector, IDvector)
nrowz<-nrow(largemat)
maxvalues<-numeric(nrowz)
numberofmaxes<-integer(nrowz)
idvalue<-integer(nrowz)
#this line randomizes the order of the rows
tempmat<-largemat[reordervector,]
tempsims<-NULL
for (i in 1:nrowz){
tempsims<-which(tempmat[i,]==max(tempmat[i,]))
numberofmaxes[i]<-length(tempsims)
tempindx<-ifelse(length(tempsims)==1, tempsims, sample(x=tempsims, size=1))
#pick off the largest value
distvalues[i]<-tempmat[i, tempindx]
# record the column id name of the largest value
idvalue[i]<-IDvector[tempindx]
#remove the column so that it cannot be selected again
tempmat<-tempmat[,-tempindx]
list(nm=numberofmaxes, dv=distvalues, ids=idvalue)
}
该函数将生成三个向量,每个向量的长度为 nrow(largemat),生成每行的最大值数、给定行中找到最大值的列位置的 id 名称以及来自原始矩阵。
这是一个小例子:
largemat 是一个矩阵:
largemat<-rbind(c(.2 .5 .6 .8 .9 1 1 1),
c(.3 .4 .8 .9 1 .7 1 1),
c(.5 1 .6 .6 .9 .9 .8 .1))
假设该矩阵已经对行进行了排列(因此 reordervector 已应用于 Largemat)
第一步:确定第 1 行中哪些列具有最大值:(6, 7, 8) 第二步:随机选择其中一列(比如 7) 第三步:获取第 7 列的 id 名称向量对应的 id 值(并记录第 1 行的最大值实际上是 1) 第四步:缩小矩阵以消除第 7 列以供进一步考虑,并对新矩阵的第 2 行重复步骤:
largemat<-rbind(c(.2 .5 .6 .8 .9 1 1),
c(.3 .4 .8 .9 1 1 1),
c(.5 1 .6 .6 .9 .8 .1))
继续- ids 的结果向量将类似于 最大值:1 等 ids:col7id等(将列解释为列id) numberof maxes 将为:3 等(对应于给定行具有该行最大值的列数)
最佳答案
我将创建辅助函数来完成任务。您使用 ifelse
在临时创建中存在问题。使用if
更合适。 data.frame 输出对我来说最有意义:
choose.max <- function(x, omit=NULL) {
x[omit] <- -Inf
xmax <- which(x == max(x))
x_col <- if(length(xmax) == 1L) xmax else sample(xmax, size=1L)
x_value <- max(x)
num_maxes <- length(xmax)
return(data.frame(col=x_col, max_value=x_value, num_maxes=num_maxes))
}
max_choice <- function(df) {
res <- list(choose.max(df[1,,drop=FALSE]))
for(i in 2:nrow(df)) {
res[[i]] <- choose.max(x=df[i,,drop=FALSE], omit=sapply(res, '[[', "col"))
}
return(do.call("rbind", res))
}
调用函数max_choice
将创建数据框,第一列用于选择的最大列,然后是该行的最大值,以及最大值的数量:
set.seed(143)
mat <- matrix(sample(1:5, 16, TRUE), 4, 4)
max_choice(mat)
# col max_value num_maxes
# 1 1 5 2
# 2 2 5 1
# 3 4 5 1
# 4 3 1 1
编辑
如果速度很重要,您可以通过此编辑获得提升:
max_choice <- function(df) {
res <- vector("list", nrow(df))
res[[1]] <- choose.max(df[1,,drop=FALSE])
for(i in 2:nrow(df)) {
res[[i]] <- choose.max(x=df[i,,drop=FALSE], omit=sapply(res[!sapply(res,is.null)], '[[', "col"))
}
return(do.call("rbind", res))
}
编辑2
这甚至可能更快。 parallel
是用于并行处理的内置包:
library(parallel)
no_cores <- detectCores() - 1
cl <- makeCluster(no_cores)
clusterExport(cl, c("mat", "choose.max", "max_choice"))
fast_res <- parLapply(cl, 1, function(x) max_choice(mat))[[1]]
关于矩阵的 R 索引用于确定 R 中超过 8 小时的最大值的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38422131/