【问题标题】:Matching rows to columns and counting same occurences R将行与列匹配并计算相同的出现次数 R
【发布时间】:2020-07-05 17:40:48
【问题描述】:

我有一个如下形式的数据集:-

a <- data.frame(X1=c("A", "B", "C", "A", "B", "C"),
                X2=c("B", "C", "C", "A", "A", "B"),
                X3=c("B", "E", "A", "A", "A", "B"),
                X4=c("E", "C", "A", "A", "A", "C"),
                X5=c("A", "C", "C", "A", "B", "B")
               )

我还有另外一组如下表格:-

b <- data.frame(col_1=c("ASD", "ASD", "BSD", "BSD"),
                col_2=c(1, 1, 1, 1),
                col_3=c(12, 12, 31, 21),
                col_4=("A", "B", "B", "A")
               )

我想要做的是从集合b 中取出列col_4 并在集合a 中逐行匹配,以便它告诉我哪一行在新列中有多少来自col_4 的元素.新列的名称无关紧要。

例如:- 集合a 中的第一行和第五行包含集合bcol_4 的所有元素。

此外,不应找到重复项。例如。集合中的第六行 a 有 3 个 "B"s。但由于 col_4 来自集合 b 只有两个 "B"s,它应该告诉我 2 而不是 3。

预期输出的形式为:-

c <- data.frame(X1=c("A", "B", "C", "A", "B", "C"),
                X2=c("B", "C", "C", "A", "A", "B"),
                X3=c("B", "E", "A", "A", "A", "B"),
                X4=c("E", "C", "A", "A", "A", "C"),
                X5=c("A", "C", "C", "A", "B", "B"),
                found=c(4, 1, 2, 2, 4, 2)
               )

【问题讨论】:

    标签: r dataframe dplyr plyr tidyr


    【解决方案1】:

    另一个高效操作集合的想法是计数并比较b$col_4a的每一行中的元素出现次数

    b1 = c(table(b$col_4))
    #b1
    #A B 
    #2 2
    
    a1 = table(factor(as.matrix(a), names(b1)), row(a))
    #a1
    #   
    #    1 2 3 4 5 6
    #  A 2 0 2 5 3 0
    #  B 2 1 0 0 2 3
    

    最后,确定每个元素(每行)的最少出现次数并求和:

    colSums(pmin(a1, b1))
    #1 2 3 4 5 6 
    #4 1 2 2 4 2
    

    如果a“data.frame”和更多元素的维度更大,Matrix::sparseMatrix 提供了一个合适的替代方案:

    library(Matrix)
    
    a.fac = factor(as.matrix(a), names(b1))
    .i = as.integer(a.fac)
    .j = c(row(a))
    
    noNA = !is.na(.i)  ## need to remove NAs manually
    .i = .i[noNA]
    .j = .j[noNA]
    
    a1 = sparseMatrix(i = .i, j = .j, x = 1L, dimnames = list(names(b1), 1:nrow(a)))
    
    a1
    #2 x 6 sparse Matrix of class "dgCMatrix"
    #  1 2 3 4 5 6
    #A 2 . 2 5 3 .
    #B 2 1 . . 2 3
    
    colSums(pmin(a1, b1))
    #1 2 3 4 5 6 
    #4 1 2 2 4 2
    

    【讨论】:

      【解决方案2】:

      我们可以使用vecsets::vintersect 来处理重复项。

      使用apply 按行计算,我们可以计算b$col4a 中的每一行之间有多少共同值。

      apply(a, 1, function(x) length(vecsets::vintersect(b$col_4, x)))
      #[1] 4 1 2 2 4 2
      

      【讨论】:

        【解决方案3】:

        使用data.table的选项:

        library(data.table)
        
        #convert a into a long format
        m <- melt(setDT(a)[, rn:=.I], id.vars="rn", value.name="col_4")
        
        #order by row number and create an index for identical occurrences in col_4
        setorder(m, rn, col_4)[, vidx := rowid(col_4), rn]
        
        #create a similar index for b
        setDT(b, key="col_4")[, vidx := rowid(col_4)]
        
        #count occurrences and lookup this count into original data
        a[b[m, on=.(col_4, vidx), nomatch=0L][, .N, rn], on=.(rn), found := N]
        

        输出:

           X1 X2 X3 X4 X5 rn found
        1:  A  B  B  E  A  1     4
        2:  B  C  E  C  C  2     1
        3:  C  C  A  A  C  3     2
        4:  A  A  A  A  A  4     2
        5:  B  A  A  A  B  5     4
        6:  C  B  B  C  B  6     2
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-25
          • 2019-09-25
          • 1970-01-01
          • 1970-01-01
          • 2019-02-27
          • 1970-01-01
          相关资源
          最近更新 更多