【问题标题】:If statement conditional is getting ignored in R如果语句条件在 R 中被忽略
【发布时间】:2021-08-29 13:38:25
【问题描述】:

我有一个包含 20,000 行的数据框(df),如下所示:

     type letter
1     a     a
2     a     k
3     a     j
4     a     c
5     a     p
...  ...   ...
2523  i     v
2524  i     j
2525  i     k
2526  i     b
...  ...   ...
7900  a     p
7901  a     x
7902  a     c
...  ...   ...

我想根据两个条件创建一个新列“匹配”: (1) 如果 type==a 且 letter==a、b 或 c,则 MATCH (2) MATCH if type==i and letter==i, j, or k

所以我运行了 if 语句:

a.letter=c("a", "b", "c")
i.letter=c("i", "j", "k")

if (df$type=="a") {
  df$match <- ifelse(df$letter %in% a.letter, "MATCH", "NO MATCH")
} else if (df$type=="i") {
   df$match <- ifelse(df$letter %in% i.letter, "MATCH", "NO MATCH")
}

我想要的输出是这样的:

     type letter match
1     a     a    MATCH
2     a     k    NO MATCH
3     a     j    NO MATCH
4     a     c    MATCH
5     a     p    NO MATCH
...  ...   ...   ...
2523  i     v    NO MATCH
2524  i     j    MATCH
2525  i     k    MATCH
2526  i     b    NO MATCH
...  ...   ...   ...
7900  a     p    NO MATCH
7901  a     x    NO MATCH
7902  a     c    MATCH
...  ...   ...

但是,似乎第二个 if 语句被完全忽略了。 我当前的输出如下所示:

     type letter match
1     a     a    MATCH
2     a     k    NO MATCH
3     a     j    NO MATCH
4     a     c    MATCH
5     a     p    NO MATCH
...  ...   ...   ...
2523  i     v    NO MATCH
2524  i     j    NO MATCH
2525  i     k    NO MATCH
2526  i     b    NO MATCH
...  ...   ...   ...
7900  a     p    NO MATCH
7901  a     x    NO MATCH
7902  a     c    MATCH
...  ...   ...

为了解决问题,我尝试只使用一个 if 语句进行测试,但奇怪的是,它对第一个条件语句非常有效,但对于第二个条件语句却不行。

这行得通:

if (df$type=="a") {
 df$match <- 0
}

但这没有(没有创建新列):

if (df$type=="i") {
 df$match <- 0
}

为什么 R 不能完全识别我的第二个条件句?

【问题讨论】:

  • 您可以使用dput(df) 提供包含“i”的行的样本吗?可能存在空格字符,例如前导或尾随空格,这会导致您的第二个语句无法匹配(例如,如果数据实际上是“i”而不是“i”。

标签: r if-statement conditional-statements


【解决方案1】:

外部 if else 也需要向量化。

此外,您可以在此处使用&amp;| 将两个ifelse 合并为一个。

df <- transform(df, match = ifelse(type == 'a' & letter %in% a.letter | 
                      type == 'i' & letter %in% i.letter, "MATCH", "NO MATCH"))

df

#   type letter    match
#1     a      a    MATCH
#2     a      k NO MATCH
#3     a      j NO MATCH
#4     a      c    MATCH
#5     a      p NO MATCH
#6     i      v NO MATCH
#7     i      j    MATCH
#8     i      k    MATCH
#9     i      b NO MATCH
#10    a      p NO MATCH
#11    a      x NO MATCH
#12    a      c    MATCH

数据

如果您在reproducible format 中提供数据会更容易提供帮助-

df <- structure(list(type = c("a", "a", "a", "a", "a", "i", "i", "i", 
"i", "a", "a", "a"), letter = c("a", "k", "j", "c", "p", "v", 
"j", "k", "b", "p", "x", "c")), class = "data.frame", row.names = c(NA, -12L))

【讨论】:

  • 太棒了。非常感谢!
【解决方案2】:

在处理矢量化维度时最好使用ifelse 语句。

df <- read.table(textConnection('type letter
1     a     a
2     a     k
3     a     j
4     a     c
5     a     p
2523  i     v
2524  i     j
2525  i     k
2526  i     b
7900  a     p
7901  a     x
7902  a     c'))

a.letter=c("a", "b", "c")
i.letter=c("i", "j", "k")
        
df$match <- ifelse((df$type=='a' & (df$letter %in% a.letter)) | (df$type=='i' & (df$letter %in% i.letter)),'MATCH','NOT MATCH')

df

输出;

   type  letter match    
   <fct> <fct>  <chr>    
 1 a     a      MATCH    
 2 a     k      NOT MATCH
 3 a     j      NOT MATCH
 4 a     c      MATCH    
 5 a     p      NOT MATCH
 6 i     v      NOT MATCH
 7 i     j      MATCH    
 8 i     k      MATCH    
 9 i     b      NOT MATCH
10 a     p      NOT MATCH
11 a     x      NOT MATCH
12 a     c      MATCH    

【讨论】:

    【解决方案3】:

    为了完整起见,这也可以使用 带有查找表的更新连接来解决。

    如果查找表 lut 是一个数据框,其中包含被视为匹配的 typeletter 的所有组合,例如,

      letter type
    1      a    a
    2      b    a
    3      c    a
    4      i    i
    5      j    i
    6      k    i
    

    然后下面的代码修改df 就地,即不复制整个数据对象,以便它按要求获得附加列match

    library(data.table)
    setDT(df)[, match := "NO MATCH"][
      setDT(lut), on = .(type, letter), match := "MATCH"][]
    
          rn type letter    match
     1:    1    a      a    MATCH
     2:    2    a      k NO MATCH
     3:    3    a      j NO MATCH
     4:    4    a      c    MATCH
     5:    5    a      p NO MATCH
     6: 2523    i      v NO MATCH
     7: 2524    i      j    MATCH
     8: 2525    i      k    MATCH
     9: 2526    i      b NO MATCH
    10: 7900    a      p NO MATCH
    11: 7901    a      x NO MATCH
    12: 7902    a      c    MATCH
    

    查找表lut 可以用不同的方式创建。一种可能性是从文本输入中读取,例如,

    lut <- readr::read_table("
    type letter
    a    a
    a    b
    a    c
    i    i
    i    j
    i    k")
    

    另一种选择是从命名列表创建它,不知何故但不完全类似于 OP 的方法,例如,

    lul <- list(a = c("a", "b", "c"),
                i = c("i", "j", "k"))
    lut <- setnames(reshape2::melt(lul), c("letter", "type"))
    

    数据

    df <- readr::read_table("
    rn    type  letter
    1     a     a
    2     a     k
    3     a     j
    4     a     c
    5     a     p
    2523  i     v
    2524  i     j
    2525  i     k
    2526  i     b
    7900  a     p
    7901  a     x
    7902  a     c")
    

    【讨论】:

      猜你喜欢
      • 2016-02-09
      • 2019-06-02
      • 2019-10-22
      • 1970-01-01
      • 2019-09-11
      • 2012-07-15
      • 1970-01-01
      • 2020-05-20
      • 2021-12-27
      相关资源
      最近更新 更多