【问题标题】:Multiple columns in R to conditionally modify other columns (not create a new column)R中的多个列有条件地修改其他列(不创建新列)
【发布时间】:2014-11-25 16:07:36
【问题描述】:

我看到一些问题询问如何比较 R 中两列之间的值,但我无法弄清楚如何使用两列有条件地编辑行的其余部分。我基本上是在尝试对每一行应用不同的范围。

例如:

data <- matrix(c(0.1, 0.3, 0.1,0.5,0.4,0.2,0.3,2,2,1,0.1,0.5,0.4,0.3,0.2), nrow=3, ncol=5)
colnames(data) <- c("Min", "Lim", "Var1", "Var2", "Var3")
data
     Min    Lim    Var1    Var2    Var3
[1,] 0.1    0.5     0.3     1.0     0.4
[2,] 0.3    0.4     2.0     0.1     0.3
[3,] 0.1    0.2     2.0     0.5     0.2

我想将 Var1、Var2 和 Var3 与 Min 和 Lim 列进行比较。如果第 1 行中的 Var1、Var2 或 Var3 值低于第 1 行中的最小值,则该值应替换为“低于最小值”。如果某个值高于 Min 但低于 Lim,则该值应替换为“Below Lim”。如果某个值同时高于 Min 和 Lim,则应保持原样。 我的预期输出是:

data
     Min    Lim    Var1       Var2       Var3
[1,] 0.1    0.5  Below Lim     1.0     Below Lim
[2,] 0.3    0.4     2.0     Below Min  Below Lim
[3,] 0.1    0.2     2.0        0.5        0.2   

我是 R 新手,并尝试过使用类似...的内容循环遍历行

for(i in 1:nrow(data){
    data[i,3:5] <- ifelse(data[,3:5] > data[,1], data[,3:5], "Below LOD")
}

...但这显然不适用于多列(Var1、Var2、Var3),我知道在 R 中应该避免循环。还有其他方法可以实现这一点吗?

非常感谢任何人指出我正确的方向,谢谢!

【问题讨论】:

  • ifelse 已经矢量化了,您不需要将其放入for 循环中。
  • 对于那些变成字符和数值组合的行,你会得到强制,这是你想要的吗?
  • 这些结果将在此步骤之后写入 PDF,因此强制不是问题。就是为了好看。这是我的第一个 SO 问题,我不认为在描述中包含该信息,但我一定会在下次提及它!

标签: r


【解决方案1】:
library(data.table)
DT <- data.table(data)

## The columns need to be converted to strings. You cannot mix strings with numbers
varCols <- grep("^Var", names(DT), value=TRUE, ignore.case=TRUE)
DT[, (varCols) := lapply(.SD, as.character), .SDcols = varCols]

DT[Var1 < Lim, Var1 := ifelse(Var1 < Min, "Below Min", "Below Lim")]
DT[Var2 < Lim, Var2 := ifelse(Var2 < Min, "Below Min", "Below Lim")]
DT[Var3 < Lim, Var3 := ifelse(Var3 < Min, "Below Min", "Below Lim")]

DT
#    Min Lim      Var1      Var2      Var3
# 1: 0.1 0.5 Below Lim         1 Below Lim
# 2: 0.3 0.4         2 Below Min Below Lim
# 3: 0.1 0.2         2       0.5       0.2

您可以以编程方式执行重复的行:

for (col in varCols)
  DT[get(col) < Lim, (col) := ifelse((get(col)) < Min, "Below Min", "Below Lim")]

【讨论】:

  • 嗨,里卡多,感谢您的回答。我可以用重复的行复制您的结果,但是当我使用编程答案时,DT 没有任何反应。您是否要使用您给我的两个选项为 DT 产生相同的结果?
  • 您好,您的要求并不完全清楚。但是,请随时提出一个新问题并包含一个可重复的示例。您可以链接回这个。
  • 对不起,这可能不是很清楚。我是说当我尝试您的第一个代码示例时,我能够重现您的结果。但是,当我尝试“以编程方式”回答for (col in varCols) DT[get(col) &lt; Lim, (col) := ifelse((get(col)) &lt; Min, "Below Min", "Below Lim")] 时,我没有得到相同的结果。 DT 中的值不会更改为“Below Lim”。
  • 编辑:原来我的数据在数据框中而不是矩阵中,哎呀!
【解决方案2】:

试试:

data[,c("Var1", "Var2", "Var3")] <- 
  ifelse(data[,c("Var1", "Var2", "Var3")] < data[,"Min"], "Below Min",
              ifelse(data[,c("Var1", "Var2", "Var3")] < data[,"Lim"], "Below Lim", data))    

这会给你:

data
    Min   Lim   Var1        Var2        Var3       
[1,] "0.1" "0.5" "Below Lim" "1"         "Below Lim"
[2,] "0.3" "0.4" "2"         "Below Min" "Below Lim"
[3,] "0.1" "0.2" "2"         "0.5"       "0.2"    

现在,请记住,您将数字与字符混合在一起,因此这会将您的矩阵强制转换为字符。

【讨论】:

    猜你喜欢
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多