【问题标题】:If any row contains a substring, then flag如果任何行包含子字符串,则标记
【发布时间】:2018-12-02 19:22:36
【问题描述】:

我有一个字符变量数据集:

col1 = c("a","b","c")
col2 = c("a","b_a","d")
df = data.frame(col1,col2)

  col1 col2
1    a    a
2    b  b_a
3    c    d

如果该行中的任何值包含子字符串“a”,我想创建一个标记 1,0 的变量 a。

  col1 col2 a
1    a    a 1
2    b  b_a 1
3    c    d 0

我的尝试如下。它并没有完全做到这一点,因为我相信如果数据框中的任何值包含子字符串而不是行,它需要TRUE

df["a"] = ifelse(any(sapply(df,function(x) str_detect(x,"a")),TRUE),1,0)

我的想法是,对于 ifelse 语句,ifelse 语句中的任何函数只评估 df[i,] 而不是整个数据框,其中 i 是它正在查看的行。情况似乎并非如此。

1) 如何构建我正在寻找的数据框?请注意,在我的真实数据集中,有 100 多列,因此将它们全部列出是没有意义的。

2) 为什么 ifelse 不只计算 df 的行 i,而不是整个 df

请注意,以前的问题只看at one variable,我正在查看所有变量,所以这不是重复的。

【问题讨论】:

  • @A.Suliman 我不这么认为。您引用的帖子仅搜索 1 个变量。我正在寻找行中的所有变量。在我发布的示例中,我正在对 col1 和 col2 进行子字符串搜索。另外,我正在寻求帮助来理解 ifelse 的底层逻辑。

标签: r


【解决方案1】:

你可以使用

grepl('a', paste0(df$col1, df$col2))

或者对任意数量的列进行泛化

grepl('a',  do.call(paste0, df))

还有第三个选项,如果您正在搜索多字符子字符串而不是单个字母,这可能更安全。在这种情况下,您可能希望避免使用 paste 以便例如在向量c('xa', 'bx') 中搜索'ab' 不会给出误报。在这种情况下,我们可以使用:

substr = 'a'
as.logical(colSums(apply (df, 1, function(x) grepl(substr, x))))

【讨论】:

  • 这会产生一个逻辑向量。将其包装在对 as.numeric 的调用中以产生零和一。
  • 在您的第二种方法中,applyMARGIN = 1 的替代方案是do.call(paste0, df)。无论如何 +1。
【解决方案2】:

1) 如何构建我要查找的数据框?

df$a <- apply(df,1,function(x) { 
  as.numeric( length(grep("a",x)) > 0) 
  })

输出

  col1 col2 a
1    a    a 1
2    b  b_a 1
3    c    d 0

2) 为什么 ifelse 不只评估 df 的第 i 行,而不是整个 df?

让我们分解一下 -

  1. 你正在做 sapply(df,function(x) str_detect(x,"a")) 这会给你这个 -

      col1  col2     a
    

    [1,] 真真假 [2,] 假真假 [3,] 假 假 假

  2. 接下来你要做any(sapply(df,function(x) str_detect(x,"a")),TRUE) - 这就是问题所在。 any 没有按行应用,输出是单个布尔值。如果应用 any 函数行明智地得到你想要的,你有。

【讨论】:

  • @macworthy 哎呀愚蠢的错字感谢您指出。修复它请检查
猜你喜欢
  • 2017-11-16
  • 2012-04-07
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 2017-10-19
相关资源
最近更新 更多