3

给定如下数据结构:

set.seed(10)
fruits <- c("apple", "orange", "pineapple")
fruits2 <- data.frame(id = 1:10, fruit1 = sample(fruits, 10, replace = T), fruit2 =   sample(fruits, 10, replace = T), fruit3 = sample(fruits, 10, replace = T))

> fruits2
   id    fruit1    fruit2    fruit3
1   1    orange    orange pineapple
2   2     apple    orange    orange
3   3    orange     apple pineapple
4   4 pineapple    orange    orange
5   5     apple    orange    orange
6   6     apple    orange pineapple
7   7     apple     apple pineapple
8   8     apple     apple     apple
9   9    orange    orange pineapple
10 10    orange pineapple    orange

我可以轻松测试 data.frame 中的任何位置是否与给定字符串完全相等fruits2 == "mystring",并且它将返回一个非常方便的格式。例如:

fruits2 == "orange"
         id fruit1 fruit2 fruit3
 [1,] FALSE   TRUE   TRUE  FALSE
 [2,] FALSE  FALSE   TRUE   TRUE
 [3,] FALSE   TRUE  FALSE  FALSE
 [4,] FALSE  FALSE   TRUE   TRUE
 [5,] FALSE  FALSE   TRUE   TRUE
 [6,] FALSE  FALSE   TRUE  FALSE
 [7,] FALSE  FALSE  FALSE  FALSE
 [8,] FALSE  FALSE  FALSE  FALSE
 [9,] FALSE   TRUE   TRUE  FALSE
[10,] FALSE   TRUE  FALSE   TRUE

然而,我真正想做的是搜索一个模式(例如“apple”)并返回相同的格式。也就是说,我希望能够测试 data.frame 中的每个项目是否包含(但不一定等于)字符串“apple”并返回相同的逻辑矩阵。在这种情况下,我希望它产生:

         id fruit1 fruit2 fruit3
 [1,] FALSE  FALSE  FALSE   TRUE
 [2,] FALSE   TRUE  FALSE  FALSE
 [3,] FALSE  FALSE   TRUE   TRUE
 [4,] FALSE   TRUE  FALSE  FALSE
 [5,] FALSE   TRUE  FALSE  FALSE
 [6,] FALSE   TRUE  FALSE   TRUE
 [7,] FALSE   TRUE   TRUE   TRUE
 [8,] FALSE   TRUE   TRUE   TRUE
 [9,] FALSE  FALSE  FALSE   TRUE
[10,] FALSE  FALSE   TRUE  FALSE

在 R 中是否有任何简单的方法可以在不指定多个模式的情况下执行此操作(我知道在这种情况下fruits2 == "apple" | fruits2 == "pineapple"会这样做,但在我的真实数据集中枚举所有可能的字符串以完全匹配是不可能的)?

我认为有解决方法,我可以编写一个函数来使用它,grepl()但我想知道是否有更简单的解决方案。

4

2 回答 2

5

在基础 R 中,

> apply(fruits2,2,function(x){grepl("apple",x)})
         id fruit1 fruit2 fruit3
 [1,] FALSE  FALSE  FALSE   TRUE
 [2,] FALSE   TRUE  FALSE  FALSE
 [3,] FALSE  FALSE   TRUE   TRUE
 [4,] FALSE   TRUE  FALSE  FALSE
 [5,] FALSE   TRUE  FALSE  FALSE
 [6,] FALSE   TRUE  FALSE   TRUE
 [7,] FALSE   TRUE   TRUE   TRUE
 [8,] FALSE   TRUE   TRUE   TRUE
 [9,] FALSE  FALSE  FALSE   TRUE
[10,] FALSE  FALSE   TRUE  FALSE

 n = 10000
 fruits2 <- data.frame(id = 1:n, fruit1 = sample(fruits, n, replace = T), fruit2 =   sample(fruits, n, replace = T), fruit3 = sample(fruits, n, replace = T))

> system.time(apply(fruits2,2,function(x){grepl("apple",x)}))   
  user  system elapsed 
  0.016   0.000   0.019 

> system.time(colwise(myfun)(fruits2))
  user  system elapsed 
  0.016   0.000   0.017

> system.time(sapply(fruits2,function(x) grepl('apple',x)))
   user  system elapsed 
  0.032   0.000   0.034

正如@eddi 指出的那样,lapply确实是最快的:

> system.time(do.call("cbind",lapply(colnames(fruits2),function(x) grepl('apple',fruits2[,x]))))
   user  system elapsed 
  0.016   0.000   0.016
于 2013-06-14T15:08:19.560 回答
3

不知道如果你认为这更简单,但你可以colwiseplyr包中使用:

myfun <- function(x) grepl('apple', x)

colwise(myfun)(fruits2)

      id fruit1 fruit2 fruit3
1  FALSE  FALSE  FALSE   TRUE
2  FALSE   TRUE  FALSE  FALSE
3  FALSE  FALSE   TRUE   TRUE
4  FALSE   TRUE  FALSE  FALSE
5  FALSE   TRUE  FALSE  FALSE
6  FALSE   TRUE  FALSE   TRUE
7  FALSE   TRUE   TRUE   TRUE
8  FALSE   TRUE   TRUE   TRUE
9  FALSE  FALSE  FALSE   TRUE
10 FALSE  FALSE   TRUE  FALSE
于 2013-06-14T15:03:46.377 回答