应用grepl检查数据表列值与列表元素的匹配,并添加结果列

时间:2017-12-03 21:27:25

标签: r sapply grepl

我这里有两个问题。第一个是我没有得到grepl函数的预期输出,第二个是我无法正确应用循环来根据函数调用的结果添加新列。 / p>

myList <- list(a = 1:3, b = 4:6)

myList
$a
[1] 1 2 3
$b
[1] 4 5 6

myData <- data.frame(
    X = sample(1:10),
    Y = sample(c("yes", "no"), 10, replace = TRUE)
)   
myData$Z = NA
myData <- as.data.table(myData) # seems necessary for grepl to work properly?

myData

    X   Y  Z
1:  9 yes NA
2:  1  no NA
3:  4 yes NA
4:  6 yes NA
5:  7  no NA
6:  2  no NA
7:  5  no NA
8:  8  no NA
9: 10  no NA
10: 3  no NA

sapply(myData[,X], function(x) grepl(x,myList))

#      [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9] [,10]
# [1,] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE
# [2,] FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE

输出检查myData $ X中的值是否包含在myList中。我的理解是输出的第一行与myList $ a匹配,第二行是myList $ b。但是,对于myData $ X的第二行和最后一行,输出的第一行已正确地表示为TRUE,即分别为X == 1和3。但是,对于第六行,它返回FALSE,其中X == 2.我认为应该返回TRUE,因为2包含在myList $ a中。

类似地,输出的第二行为myData $ X第三行和第四行赋予TRUE,其中myData $ x == 4和6。但是,对于第7行,它不会返回TRUE,其中myData $ X == 5.(myList $ b包含4,5和6。)

~~~

我的第二个问题是如果应用循环来覆盖myData $ Z和list元素的标题,如果grepl为该特定行返回TRUE。期望的输出:

    X   Y  Z
1:  9 yes NA
2:  1  no a
3:  4 yes b
4:  6 yes b
5:  7  no NA
6:  2  no a
7:  5  no b
8:  8  no NA
9: 10  no NA
10: 3  no a

我认为以下内容可能会有效,但它会返回六条警告消息并且不会产生所需的输出:

for (i in myList) {
myData$Z[sapply(myData[,X], function(x) (grepl(x,myList)))] <- i
}

提前感谢任何输入。

2 个答案:

答案 0 :(得分:1)

不需要as.data.table(),您只是忘记引用列名称。除非您需要更高级的部分匹配,否则无需grep()

使用字符串和多个匹配

myList2 <- list(pet = c("cat", "dog", "horse", "bunny"), 
               food = c("pig", "chicken", "cow", "bunny"))

set.seed(1)
myData2 <- data.frame(
    X = sample(unique(unlist(myList2))),
    Y = sample(c("yes", "no"), 7, replace = TRUE)
)   

exist2 <- sapply(myList2, function(x) myData2[,"X"] %in% x)

Z <- apply(exist2, 1, function(x) names(which(x)))
myData2$Z <- sapply(Z, function(x) 
  ifelse(length(x) == 0, NA, paste(x, collapse="+")))

myData2
#         X   Y        Z
# 1     dog  no      pet
# 2   horse  no      pet
# 3 chicken yes     food
# 4   bunny yes pet+food
# 5     cat yes      pet
# 6     cow  no     food
# 7     pig yes     food

答案 1 :(得分:1)

您可以melt列表,merge使用数据框:

merge(myData, reshape2::melt(myList), by.x = "X", by.y = "value", all.x = TRUE)

#      X   L1
#  1   1 <NA>
#  2   2    a
#  3   3    a
#  4   4    a
#  5   5 <NA>
#  6   6 <NA>
#  7   7 <NA>
#  8   8    b
#  9   9    b
# 10  10    b

数据:

myData <- data.frame(X = 1:10)
myList <- list(a = 2:4, b = 8:10)