在 R 中,检查字符串是否出现在数据框的行中(任何列)。

12
temp = structure(list(name1 = structure(c(2L, 1L, 2L, 1L, 2L), .Label = c("Joe", 
"Mike"), class = "factor"), name2 = c("Nick", "Matt", "Nick", 
"Matt", "Nick"), name3 = c("Matt", "Tom", "Tom", "Steve", "Tom"
)), .Names = c("name1", "name2", "name3"), row.names = c(NA, 
-5L), class = "data.frame")

大家好,

我有一个关于 R 编程的看似简单的问题。请参考下面的数据框,其代码如上所示:

  name1 name2 name3
1  Mike  Nick  Matt
2   Joe  Matt   Tom
3  Mike  Nick   Tom
4   Joe  Matt Steve
5  Mike  Nick   Tom

我想要一个简单的函数,它返回一个布尔向量,指示特定名称是否出现在这个数据框的一行中(在任何列中)。例如:

myfunction(Matt) 

# should return
c(TRUE, TRUE, FALSE, TRUE, FALSE).

由于Matt出现在第1、2和第4行,对此的任何简单帮助都将不胜感激,谢谢!

4个回答

8
我也想出了自己的解决方案:
rowSums("Matt" == temp) > 0 

看起来已经达到了预期效果。

这是一种通常很整洁的方法。我还建议使用 Reduce(\|`, lapply(temp, `==`, "Matt"))`。 - thelatemail
rowSums or Reduce are also about 20 times faster than looping over each row in apply, and about 60 times faster than using by_row in dplyr/purrr - thelatemail

8

这里有一个选项。使用apply和匹配符(%in%)。

apply(temp, 1, function(x) any(x %in% "Matt")) 
[1]  TRUE  TRUE FALSE  TRUE FALSE

5
这个解决方案使用了 dplyrpurrr
myFunction <- function(df, name) {
  by_row(df, function(x) {name %in% x}, .collate = "cols") %>%
    pull(.out)
}
myFunction(temp, "Matt")

by_row将布尔型加作列。pull将该列返回为向量。

更新purrr中已删除by_row函数。


by_row 是来自于 purrrlyr,而不是 dplyr 或 purrr 吗? - camille
@camille,回答时它是purrr的一部分,但在那个库中已经被弃用。看起来你指出的函数现在在purrrlyr中。 - David Richards

5

在使用dplyr或purrr的其他非常一致和更通用的方法时,您可以避免与apply()中涉及矩阵转换相关的类强制转换问题,for循环的低效率和冗长代码,以及rowSums提案所带来的其他限制。

使用purrr的map、reduce和stringr的str_detect函数:

library(purrr)
library(stringr)

temp%>%map(~str_detect(.x,'Matt'))%>%reduce(`|`)

使用 dplyr,结合 map%>%reducepmap%>%anyrowwise%>%anyif_any

library(purrr)
library(dplyr)
library(stringr)

temp%>%mutate(has_Matt=map(., ~str_detect(.x, 'Matt'))%>%pmap_lgl(any))

#OR

temp%>%rowwise()%>%
        mutate(has_Matt=any(str_detect(c_across(everything()), "Matt")))

使用dplyr::if_any,最简洁的方法:

temp%>%mutate(has_Matt=if_any(everything(), ~.x=="Matt"))

如果您想定义一个简化此操作的新函数,您可以使用基本的 R 语言创建一个函数:

my_function<-function(dataframe, pattern){
        Reduce(`|`, Map(function(x) grepl('Matt', x), dataframe))
}

my_function(temp, "Matt")

[1]  TRUE  TRUE FALSE  TRUE FALSE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接