【问题标题】:Find the (row,column) locations of all matches to a substring in large dataset查找大型数据集中子字符串的所有匹配项的(行、列)位置
【发布时间】:2018-07-20 23:33:19
【问题描述】:

在大型数据集中查找包含子字符串“en”的所有匹配项的(行、列)位置。

  1. 数据集有 100 多个列和 100 万行

  2. 本来不知道有没有

示例数据集:

#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"

或任何可向量化的表达式。

  1. ※which(df == "en",arr.ind = T) 找不到匹配的子字符串,对字符不起作用。
  2. ※grep("en",df[1:ncol(df)])不能返回ROW索引
  3. ※for (i in 1:ncol(df)){print(grep("en",df[i]))} COL 的索引未可视化,无法返回 SECOND ENCOUNTER 在同一列中的索引。
  4. Excel 中的功能:Ctrl+F --Find > “Find All”更像是 预期的解决方案。

【问题讨论】:

    标签: r dataframe string-matching


    【解决方案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 替换原始表的内容?
    猜你喜欢
    • 2023-01-06
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 2013-03-19
    • 2022-07-16
    • 2017-11-14
    相关资源
    最近更新 更多