【问题标题】:Creating a new variable from a conditional operation on 3 old variables in R从 R 中 3 个旧变量的条件运算创建一个新变量
【发布时间】:2011-01-04 02:03:12
【问题描述】:

我在 R 中有一个数据集,其中包含快速诊断测试的结果。如果测试工作正常,则该测试有一条可见线(对照线),如果患者样本中存在两种寄生虫,则该测试有一条可见线。

数据集包含每个测试行的逻辑列,如下所示: (数据库称为RDTbase)

   Control  Pf    Pv
1. TRUE     TRUE  FALSE
2. TRUE     FALSE TRUE
3. FALSE    FALSE FALSE
4. TRUE     TRUE  TRUE
5. TRUE     FALSE FALSE

我想添加一个新列,其中包含每个快速测试的单个结果。根据三行所满足的不同逻辑条件指定结果。对于上面的示例,新列将如下所示:

Control  Pf     Pv     Result
1. TRUE  TRUE   FALSE  Pf
2. TRUE  FALSE  TRUE   Pv
3. FALSE FALSE  FALSE  Invalid
4. TRUE  TRUE   TRUE   Mixed
5. TRUE  FALSE  FALSE  Negative

我能够创建新列,但需要大量编码,而且我认为必须有一种更简单(更短)的方法来做到这一点。

这是我目前的(长)方法:

R.Pf <- RDTbase[which(Control == "TRUE" & Pf == "TRUE" & Pv == "FALSE"),]
R.Pv <- RDTbase[which(Control == "TRUE" & Pf == "FALSE" & Pv == "TRUE"),]
R.inv <- RDTbase[which(Control == "FALSE"),]
R.mix <- RDTbase[which(Control == "TRUE" & Pf == "TRUE" & Pv == "TRUE"),]
R.neg <- RDTbase[which(Control == "TRUE" & Pf == "FALSE" & Pv == "FALSE"),]

R.Pf$Result <- c("Pf")
R.Pv$Result <- c("Pv")
R.inv$Result <- c("Invalid")
R.mix$Result <- c("Mixed")
R.neg$Result <- c("Negative")

RDTbase2 <- rbind(R.Pf, R.Pv, R.inv, R.mix, R.neg)

任何关于如何简化和缩短此代码的想法将不胜感激,因为我必须对我的数据库做很多此类事情。

非常感谢, 艾米

【问题讨论】:

  • 请使用编辑器中的代码按钮重新格式化您的数据集,以明确它是表格格式。

标签: r variables conditional


【解决方案1】:

我会简单地创建数据框的另一列,并有条件地分配给它的不同子集。您还可以精简数据框索引代码。

RDTbase$Result = NA 
RDTbase <- within(RDTbase, Result[Control=="TRUE" & Pf=="TRUE" & Pv=="FALSE"] <- "Pf")
RDTbase <- within(RDTbase, Result[Control=="FALSE"] <- "Invalid")

等等

"within" 只是节省了一点打字时间。

【讨论】:

  • 谢谢 xbalto - 也会试试这个。那么“内部”是另一种子集化方式吗?
  • 啊 - 我现在明白了,“内部”允许您引用数据帧的子集而无需将其取出。结合您的建议后,我的代码现在缩短了 5 行 - 再次感谢!
【解决方案2】:

首先使用logical 向量代替character 会很好,然后你可以写Control 代替Control == "TRUE"!Control 代替Control == "FALSE"。而且你的代码会更短。

对于你的问题我会使用几个ifelse:

RDTbase$Result <- ifelse(
  Control == "TRUE",
  ifelse(
    Pf == "TRUE",
    ifelse(Pv == "TRUE","Mixed","Pf"), # when Control is TRUE, Pf is TRUE
    ifelse(Pv == "TRUE","Pv","Negative"), # when Control is TRUE, Pf is FALSE
  ),
  "Invalid" # when Control is FALSE
)

但我喜欢魔术,所以你可以跟随:

num_code <- (
  as.numeric(as.logical(Control))
  + 2*as.numeric(as.logical(Pf))
  + 4*as.numeric(as.logical(Pv))
) # values are 0,1,2,...,7
# then 
RDTbase$Result <- c( 
  "Invalid" , # 0 = F,F,F # Control, Pf, Pv
  "Negative", # 1 = T,F,F
  "Invalid" , # 2 = F,T,F
  "Pf"      , # 3 = T,T,F
  "Invalid" , # 4 = F,F,T
  "Pv"      , # 5 = T,F,T
  "Invalid" , # 6 = F,T,T
  "Mixed"   , # 7 = T,T,T
)[num_code+1]

当您需要将多个逻辑列解码为字符时,这是一个不错的技巧。

【讨论】:

  • 谢谢马雷克!这两个非常有用的技巧,我不知道可以引用这样的逻辑向量,并且将逻辑转换为数字很巧妙。这肯定有助于使其更简洁......
【解决方案3】:

使用变换使这个紧凑而优雅:

transform(a, Result = 
 ifelse(Control,
  ifelse(Pf, 
   ifelse(Pv, "Mixed", "Pf"),
   ifelse(Pv, "Pv", "Negative")),
  "Invalid"))

产量

  Control    Pf    Pv   Result
1    TRUE  TRUE FALSE       Pf
2    TRUE FALSE  TRUE       Pv
3   FALSE FALSE FALSE  Invalid
4    TRUE  TRUE  TRUE    Mixed
5    TRUE FALSE FALSE Negative

或者,在 Marek 的版本的基础上,我们可以使用逻辑向量来稍微更紧凑地计算索引:

a$Result = apply(a,1,
  function(x){
    c(rep("Invalid", 4), "Negative", "Pv", "Pf", "Mixed")
      [1+sum(c(4,2,1)[x])]})

【讨论】:

    猜你喜欢
    • 2022-07-15
    • 1970-01-01
    • 2022-08-13
    • 1970-01-01
    • 2020-11-27
    • 2021-07-14
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多