应用 grepl 检查数据 table 列值与列表元素的匹配,并添加结果列
Applying grepl to check for match of data table column values with list elements, and adding resulting column
我这里有两个问题。第一个是我没有从 grepl
函数获得预期的输出,第二个是我无法根据函数调用的结果正确应用循环来添加新列。
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。但是,对于第六行,它 returns FALSE,其中 X == 2。我认为应该 return TRUE,因为 2 包含在 myList$a.
中
类似地,输出的第二行为 myData$X 第 3 行和第 4 行提供 TRUE,其中 myData$x == 4 和 6。但是,对于第 7 行,它不 return TRUE,其中 myData$X == 5。(myList$b 包含 4、5 和 6。)
~~~
我的第二个问题是如何应用一个循环来用列表元素的标题覆盖 myData$Z,如果 grepl
return 该特定行为 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
我认为类似下面的方法可能会起作用,但它 return 有六个警告消息并且没有产生所需的输出:
for (i in myList) {
myData$Z[sapply(myData[,X], function(x) (grepl(x,myList)))] <- i
}
提前感谢您的任何意见。
不需要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
您可以 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)
我这里有两个问题。第一个是我没有从 grepl
函数获得预期的输出,第二个是我无法根据函数调用的结果正确应用循环来添加新列。
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。但是,对于第六行,它 returns FALSE,其中 X == 2。我认为应该 return TRUE,因为 2 包含在 myList$a.
中类似地,输出的第二行为 myData$X 第 3 行和第 4 行提供 TRUE,其中 myData$x == 4 和 6。但是,对于第 7 行,它不 return TRUE,其中 myData$X == 5。(myList$b 包含 4、5 和 6。)
~~~
我的第二个问题是如何应用一个循环来用列表元素的标题覆盖 myData$Z,如果 grepl
return 该特定行为 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
我认为类似下面的方法可能会起作用,但它 return 有六个警告消息并且没有产生所需的输出:
for (i in myList) {
myData$Z[sapply(myData[,X], function(x) (grepl(x,myList)))] <- i
}
提前感谢您的任何意见。
不需要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
您可以 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)