如何在矩阵的行上复制相同的函数

时间:2018-10-30 20:24:38

标签: r loops

我正在尝试编写一个循环,该循环确定哪个单元格具有最大的值,并选择具有高中或低字符串的结果作为该单元格。这是要试用的数据。

data <- matrix(c(0.3000003,0.3299896,0.3700101,
                 0.3299896,0.3700101,0.3000003,
                 0.3700101,0.3000003,0.3299896,
                 0.3000003,0.3299896,0.3700101,
                 0.3299896,0.3700101,0.3000003,
                 0.3700101,0.3000003,0.3299896),6,3)
colnames(data) <- c("Low","Medium","High")
rownames(data) <- paste("case",1:6)

> data
             Low    Medium      High
case 1 0.3000003 0.3700101 0.3299896
case 2 0.3299896 0.3000003 0.3700101
case 3 0.3700101 0.3299896 0.3000003
case 4 0.3299896 0.3000003 0.3700101
case 5 0.3700101 0.3299896 0.3000003
case 6 0.3000003 0.3700101 0.3299896

我正在使用此函数,但似乎只在计算第一行。

assign.levels <- function(data) {

  for (i in nrow(data)) {

    scored.thetas.1 <- names(which.max(data[i,1:3])) ## I wrote 1:3 here becasue I have multiple coloumns in the original dataset.
    return(scored.thetas.1)

  }
}


> assign.levels(data)
[1] "Medium"

有什么想法吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

以下是您可能更喜欢的矢量化解决方案:

colnames(data)[apply(data, 1, which.max)]
# [1] "Medium" "High"   "Low"    "High"   "Low"    "Medium"

这是您尝试的一种简洁形式:apply的{​​{1}}的每一行(维度which.max1函数并获得相应的列名。

根据您的尝试,这是一个更正的版本:

data

关于您的尝试,有几件事需要提及:1)您正在使用assign.levels <- function(data) { scored.thetas.1 <- rep(NA, nrow(data)) for (i in 1:nrow(data)) scored.thetas.1[i] <- names(which.max(data[i, ])) scored.thetas.1 } assign.levels(data) # [1] "Medium" "High" "Low" "High" "Low" "Medium" 进行迭代,而i in nrow(data)只是一个数字。因此,基本上,您只查看最后一行; 2)您一直在每次迭代中重新定义相同的变量nrow(data)(在这种情况下,只有一次迭代,但是趋势很差); 3)循环不是函数,您不需要从中返回任何内容,而是您很可能想将新获得的值存储在某个地方。

相比之下,请注意,首先我定义了一个长度为scored.thetas.1的空向量scored.thetas.1。然后,我遍历所有行(nrow(data))并将每个行/迭代的值存储到1:nrow(data)

答案 1 :(得分:2)

这应该很快

colnames(data)[max.col(data)]
#[1] "Medium" "High"   "Low"    "High"   "Low"    "Medium"

这里是一个基准。

n <- 1e6
set.seed(1)
data <- matrix(runif(n * 3), ncol = 3)
colnames(data) <- c("Low","Medium","High")

library(microbenchmark)

benchmark <- microbenchmark(
  OP = assign.levels(data), # as defined in Julius's answer
  Julius = colnames(data)[apply(data, 1, which.max)],
  markus = colnames(data)[max.col(data)], times = 20
)

autoplot(benchmark)

enter image description here