查找大型数据集中子字符串的所有匹配项的(行、列)位置
Posted
技术标签:
【中文标题】查找大型数据集中子字符串的所有匹配项的(行、列)位置【英文标题】:Find the (row,column) locations of all matches to a substring in large dataset 【发布时间】:2018-07-20 23:33:19 【问题描述】:在大型数据集中查找包含子字符串“en”的所有匹配项的(行、列)位置。
数据集有 100 多个列和 100 万行
本来不知道有没有
示例数据集:
#Dataset call df
col_1 col_2 col_3
1 101 10n1 cb101
2 ed10en dn 101
3 101 NA 1e01
4 101 r1en1 ""
5 en10 101 en5en
结果如下:第一个匹配是 (2,1) ,第二个匹配是 (5,1),第三个匹配是 (4,2) ,第四个匹配是 (5,3) 是解决方案可以提供的预期结果。
>"2,1","5,1","4,2","5,3"
或任何可向量化的表达式。
-
※
which(df == "en",arr.ind = T)
找不到匹配的子字符串,对字符不起作用。
※grep("en",df[1:ncol(df)])
不能返回ROW索引
※for (i in 1:ncol(df))print(grep("en",df[i]))
COL 的索引未可视化,无法返回 SECOND ENCOUNTER 在同一列中的索引。
Excel 中的功能:Ctrl+F --Find > “Find All”更像是
预期的解决方案。
【问题讨论】:
【参考方案1】:
reprex::reprex_info()
#> Created by the reprex package v0.1.1.9000 on 2018-02-10
您可以使用grepl
加上一些技巧来获得结果为行
和列索引,而不是您从 grep
获得的向量索引。
df <- read.table(
header = T, text = '
col_1 col_2 col_3
101 10n1 cb101
ed10en dn 101
101 NA 1e01
101 r1en1 ""
en10 101 en5en')
x <- as.matrix(df)
i <- grepl("en", x) # logical vector of length = nrow(x) * ncol(x)
i
#> [1] FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE
#> [12] FALSE FALSE FALSE TRUE
dim(i) <- dim(x) # coerce to matrix with same dimensions as x
i
#> [,1] [,2] [,3]
#> [1,] FALSE FALSE FALSE
#> [2,] TRUE FALSE FALSE
#> [3,] FALSE FALSE FALSE
#> [4,] FALSE TRUE FALSE
#> [5,] TRUE FALSE TRUE
which(i, arr.ind = T) # check which are TRUE and report as row, col
#> row col
#> [1,] 2 1
#> [2,] 5 1
#> [3,] 4 2
#> [4,] 5 3
另一种方法可能是只使用grep
,结合一些模块化
算术计算行和列的位置,给定
数据的维度,并使用 R 中的矩阵基本上是
以行数包裹的列向量:
i <- grep("en", x)
i
#> [1] 2 5 9 15
row <- 1 + (i - 1) %% nrow(x) # number of positions outside full columns
col <- 1 + (i - 1) %/% nrow(x) # number of full columns before position i
cbind(row, col)
#> row col
#> [1,] 2 1
#> [2,] 5 1
#> [3,] 4 2
#> [4,] 5 3
感觉后一种方法在大数据的情况下会更有效,因为您可以避免创建大的中间逻辑向量。
【讨论】:
显然是一种优雅的方法。你能解释一下 row Matrices in R are atomic vectors with a dimension attribute. 它们是按列填充的,这意味着如果向量上的某个位置大于行数,它会“越过”到下一列。我们可以使用integer division,并将向量位置除以矩阵中的行数,以找到分别为我们提供列和行索引的商 (%/%
) 和余数 (%%
)。
需要整个1 + (i - 1)
,因为R从1开始索引而不是0
。对于从0
开始的索引,我们可以只有row <- i %% nrow(x)
和col <- i %/% nrow(x)
。
非常感谢 Mikko。我现在明白了!【参考方案2】:
希望这会有所帮助!
l <- lapply(colnames(df), function(x) grep("en", df[,x]))
final_result <- unlist(lapply(seq_along(l), function(i) paste(l[[i]], i, sep = ",")))
final_result
输出是:
[1] "2,1" "5,1" "4,2" "5,3"
样本数据:
df <- structure(list(col_1 = c("101", "ed10en", "101", "101", "en10"
), col_2 = c("10n1", "dn", NA, "r1en1", "101"), col_3 = c("cb101",
"101", "1e01", "", "en5en")), .Names = c("col_1", "col_2", "col_3"
), class = "data.frame", row.names = c("1", "2", "3", "4", "5"
))
【讨论】:
级长。我还是一个没有使用过“function(x)”的初学者。有什么简单的方法可以理解这段代码吗? --lapply(seq_along(l), function(i) paste(l[[i]], i, sep = ","))
--- 特别是当 paste("x","d", sep =" , ") = " x , d" ,那么 paste() 参数中的中间“i”是什么?跨度>
如果您打印str(l)
(即第一个lapply
结果),那么您可以看到它是“3 个列表”。它的大小为“3”,因为function(x)
应用于df
的3 列。现在回到你的问题——l[[i]]
(即列表l
的第i个元素)输出行索引,i
给出df
的列索引(你可以打印l
来确认)。当您在这些组合之上应用paste
时,您将获得所需的结果。
谢谢。双 [[]] 括号返回每个元素,粘贴的第二个参数将 i 本身添加到每个元素。
有没有办法将输出转换为行和列的表?谢谢!
@tom 你能更具体地了解你想要的输出吗?您是否只是想根据子字符串的存在或不存在分别用 True/False 替换原始表的内容?以上是关于查找大型数据集中子字符串的所有匹配项的(行、列)位置的主要内容,如果未能解决你的问题,请参考以下文章