查找大型数据集中子字符串的所有匹配项的(行、列)位置

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 &lt;- i %% nrow(x)col &lt;- 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 替换原始表的内容?

以上是关于查找大型数据集中子字符串的所有匹配项的(行、列)位置的主要内容,如果未能解决你的问题,请参考以下文章

查找大型数据集中的两个日期之间是不是有假期?

R:从R中的大型数据集中根据列中的值删除行[重复]

从大型数据集中采样

如何从 BigQuery 中存储的大型线串数据集中查找所有道路交叉口

使用 python 在大型数据集中快速查找

如何按名称查找不匹配的第n个子行?