过滤行时的子字符串匹配
Substring match when filtering rows
我在 file1 中的字符串与 file2 中的部分字符串相匹配。我想过滤掉 file2 中与 file1 中部分匹配的字符串。请看我的尝试。不确定如何以这种方式定义子字符串匹配。
文件 1:
V1
species1
species121
species14341
文件 2
V1
genus1|species1|strain1
genus1|species121|strain1
genus1|species1442|strain1
genus1|species4242|strain1
genus1|species4131|strain1
我的尝试:
file1[!file1$V1 %in% file2$V1]
你不能在R中以这种方式使用%in%
运算符。它用于确定一个向量的元素是否在另一个向量中,不像in
在Python中可用于匹配子字符串:看这个:
"species1" %in% "genus1|species1|strain1" # FALSE
"species1" %in% c("genus1", "species1", "strain1") # TRUE
但是,您可以为此使用 grepl
(l
用于逻辑,即 returns TRUE
或 FALSE
)。
grepl("species1", "genus1|species1|strain1") # TRUE
这里有一个额外的复杂性,您不能将 grepl
与向量一起使用,因为它只会比较第一个值:
grepl(file1$V1, "genus1|species1|strain1")
[1] TRUE
Warning message:
In grepl(file1$V1, "genus1|species1|strain1") :
argument 'pattern' has length > 1 and only the first element will be used
上面简单的告诉你file1$V1
的第一个元素在"genus1|species1|strain1"
.
此外,您想将 file1$V1
中的每个元素与整个字符串向量进行比较,而不仅仅是一个字符串。没关系,但你会得到一个与第二个向量长度相同的向量作为输出:
grepl("species1", file2$V1)
[1] TRUE TRUE TRUE FALSE FALSE
我们可以看看其中 any()
个是否匹配。当您用 tidyverse
标记您的问题时,这里有一个 dplyr
解决方案:
library(dplyr)
file1 |>
rowwise() |> # This makes sure you only pass one element at a time to `grepl`
mutate(
in_v2 = any(grepl(V1, file2$V1))
) |>
filter(!in_v2)
# A tibble: 1 x 2
# Rowwise:
# V1 in_v2
# <chr> <lgl>
# 1 species14341 FALSE
获得所需内容的一种方法是使用 grepl
函数。所以,你可以运行下面的代码:
# Load library
library(qdapRegex)
# Extract the names of file2$V1 you are interested in (those between | |)
v <- unlist(rm_between(file2$V1, "|", "|", extract = T))
# Which of theese elements are in file1$V1?
elem.are <- which(v %in% file1$V1)
# Delete the elements in elem.are
file2$V1[-elem.are]
在v
中我们保存我们感兴趣的file2$V1
的名字(那些
之间 | |)
然后我们把出现的那些名字的位置保存在elem.are
在 file1$V1
最后,我们使用 file2$V1[-elem.are]
省略了那些元素
我在 file1 中的字符串与 file2 中的部分字符串相匹配。我想过滤掉 file2 中与 file1 中部分匹配的字符串。请看我的尝试。不确定如何以这种方式定义子字符串匹配。
文件 1:
V1
species1
species121
species14341
文件 2
V1
genus1|species1|strain1
genus1|species121|strain1
genus1|species1442|strain1
genus1|species4242|strain1
genus1|species4131|strain1
我的尝试:
file1[!file1$V1 %in% file2$V1]
你不能在R中以这种方式使用%in%
运算符。它用于确定一个向量的元素是否在另一个向量中,不像in
在Python中可用于匹配子字符串:看这个:
"species1" %in% "genus1|species1|strain1" # FALSE
"species1" %in% c("genus1", "species1", "strain1") # TRUE
但是,您可以为此使用 grepl
(l
用于逻辑,即 returns TRUE
或 FALSE
)。
grepl("species1", "genus1|species1|strain1") # TRUE
这里有一个额外的复杂性,您不能将 grepl
与向量一起使用,因为它只会比较第一个值:
grepl(file1$V1, "genus1|species1|strain1")
[1] TRUE
Warning message:
In grepl(file1$V1, "genus1|species1|strain1") :
argument 'pattern' has length > 1 and only the first element will be used
上面简单的告诉你file1$V1
的第一个元素在"genus1|species1|strain1"
.
此外,您想将 file1$V1
中的每个元素与整个字符串向量进行比较,而不仅仅是一个字符串。没关系,但你会得到一个与第二个向量长度相同的向量作为输出:
grepl("species1", file2$V1)
[1] TRUE TRUE TRUE FALSE FALSE
我们可以看看其中 any()
个是否匹配。当您用 tidyverse
标记您的问题时,这里有一个 dplyr
解决方案:
library(dplyr)
file1 |>
rowwise() |> # This makes sure you only pass one element at a time to `grepl`
mutate(
in_v2 = any(grepl(V1, file2$V1))
) |>
filter(!in_v2)
# A tibble: 1 x 2
# Rowwise:
# V1 in_v2
# <chr> <lgl>
# 1 species14341 FALSE
获得所需内容的一种方法是使用 grepl
函数。所以,你可以运行下面的代码:
# Load library
library(qdapRegex)
# Extract the names of file2$V1 you are interested in (those between | |)
v <- unlist(rm_between(file2$V1, "|", "|", extract = T))
# Which of theese elements are in file1$V1?
elem.are <- which(v %in% file1$V1)
# Delete the elements in elem.are
file2$V1[-elem.are]
在
v
中我们保存我们感兴趣的file2$V1
的名字(那些 之间 | |)然后我们把出现的那些名字的位置保存在
elem.are
在file1$V1
最后,我们使用
省略了那些元素file2$V1[-elem.are]