【问题标题】:Using the ifelse statement in R在 R 中使用 ifelse 语句
【发布时间】:2015-10-14 10:09:58
【问题描述】:

我想使用 ifelse 语句来创建一个新变量,比如 z。但是,其中一个返回值取决于矩阵的第 i 列。这是一个简单的例子

set.seed(1)
data <- data.frame(x = rnorm(10), y = rnorm(10), ind = rep(c(0, 1), 5))
m <- data.frame(matrix(rnorm(100), 10, 10))

z <- ifelse(data$ind == 1, data$x, sum(m[, i]))

我知道带有 z 的行不会运行,但它说明了我想要做什么。如果一个主题的 ind 变量等于 0,那么我将 m 中对应于主题 i 的列的 10 个条目的总和分配给 z。

我可以使用 ifelse 执行此操作,还是需要一个 for 循环?我试图远离 for 循环,这就是我首先尝试 ifelse 的原因。

z 应该是这样的:

z
 [1] -1.3367324  0.1836433  1.3413668  1.5952808  4.5120996 -0.8204684  1.2736029
 [8]  0.7383247  3.4748021 -0.3053884

谢谢!

【问题讨论】:

  • 您目前遇到什么错误?
  • 好吧,如果我在最后一行使用了“i”,我会收到一条错误消息,指出“i”未找到。如果我使用没有特定索引的 m,它将添加 m 的每个条目,我只想添加第 i 列。
  • 您如何确定使用哪个i 值?您的问题并不清楚这一点。
  • 我不想实际使用 i 值,我只是将其包括在内以说明我想要做什么,因为我不确定如何在 ifelse 语句中到达 m 的特定列.基本上,我将对应于 data$ind[i] == 0 的主题(行号)。

标签: r


【解决方案1】:

是的,您可以使用 ifelse 和单行符来完成,非常接近您所写的内容:

z <- ifelse(data$ind == 0, colSums(m), data$x)

这是 R 在执行此语句时所做的:

  1. 它计算布尔向量data$ind == 0,并将两个数字向量colSums(m)data$x存储到内存中
  2. 其中(data$ind == 0)True,它输出colSums(m);其中(data$ind == 0)False,它输出data$x

【讨论】:

    【解决方案2】:

    或者我们可以使用算术

    colSums(m)*(data$ind==0) + (data$ind==1)*data$x
    #     X1         X2         X3         X4         X5         X6         X7 
    #-1.3367324  0.1836433  1.3413668  1.5952808  4.5120996 -0.8204684  1.2736029 
    #        X8         X9        X10 
    # 0.7383247  3.4748021 -0.3053884 
    

    【讨论】:

      【解决方案3】:

      您可以改为使用两条线:

      z <- data$x
      z[data$ind == 0] <- colSums(m[,data$ind == 0])
      
       [1] -1.3367324  0.1836433  1.3413668  1.5952808  4.5120996 -0.8204684  1.2736029  0.7383247  3.4748021
      [10] -0.3053884
      

      更一般地说,您可以使用apply 函数。这通常比像上面那样的直接矢量化解决方案要慢。这里是 sapply:

      sapply(1:nrow(data), function(x){ifelse(data$ind[x] == 1, data$x[x], sum(m[, x]))})
      
       [1] -1.3367324  0.1836433  1.3413668  1.5952808  4.5120996 -0.8204684  1.2736029  0.7383247  3.4748021
      [10] -0.3053884
      

      基准测试:

      microbenchmark::microbenchmark(
           sapply = sapply(1:nrow(data), function(x){ifelse(data$ind[x] == 1, data$x[x], sum(m[, x]))}), 
           vectorised = {z <- data$x;
                         z[data$ind == 0] <- colSums(m[,data$ind == 0])})
      Unit: microseconds
             expr     min      lq     mean   median       uq     max neval cld
           sapply 391.297 408.193 423.6525 412.4170 423.7450 853.249   100   b
       vectorised 197.377 199.873 208.7701 202.5605 214.4645 284.545   100  a 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-17
        • 2020-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-11
        相关资源
        最近更新 更多