【问题标题】:how to count binary patterns如何计算二进制模式
【发布时间】:2019-09-20 16:09:35
【问题描述】:

这个问题有很多应用。我想识别和计算许多变量中的唯一二进制模式。我找到了与我正在寻找的内容相近的东西,但我无法完成代码。

countpattern {e1071}

与链接中的数据相同:

library(data.table)
xx <- rbind(c(1,0,0),c(1,0,0),c(1,0,1),c(0,1,1),c(0,1,1))
xx <- as.data.table(xx)

library(e1071)
countpattern(xx[,1:3])
000 001 010 011 100 101 110 111 
  0   0   0   2   2   1   0   0 

(cols <- names(which(countpattern(xx[,1:3])>0)))
for(i in cols) { xx[,i] <- as.character("") }  # ... and that's it :(

xx
   V1 V2 V3 011 100 101
1:  1  0  0            
2:  1  0  0            
3:  1  0  1            
4:  0  1  1            
5:  0  1  1            

我有 data.table 和列,当每行中的模式与可用列名匹配时,我想用 TRUE/FALSE 或 1/0 填充它们。最终结果应如下所示:

xx
   V1 V2 V3 011 100 101
1:  1  0  0   0   1   0          
2:  1  0  0   0   1   0             
3:  1  0  1   0   0   1            
4:  0  1  1   1   0   0            
5:  0  1  1   1   0   0            

我已经尝试了多个版本的快速for (i in seq_along) {set(DT, i, 1L, i)},但我的目标远大于我的技能。

谢谢, 阿尔多

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    这是一种方法

    library(data.table)
    #Paste all the binary columns together rowwise
    vals <- do.call(paste0, xx)
    #Get only unique values
    unique_vals <- unique(vals)
    #Initialise the columns to 0
    xx[, (unique_vals) := 0]
    
    #Create a matrix with row and column index and replace those position with 1
    xx[cbind(seq_len(nrow(xx)), match(vals, unique_vals) + 3)] <- 1
    #Replace 3 with number in original columns
    xx
    #   V1 V2 V3 100 101 011
    #1:  1  0  0   1   0   0
    #2:  1  0  0   1   0   0
    #3:  1  0  1   0   1   0
    #4:  0  1  1   0   0   1
    #5:  0  1  1   0   0   1
    

    countpattern from e1071 返回所有可能的模式,我们可以使用该函数和matching = TRUE 来获取匹配索引,然后使用该信息将列变为 1。

    library(e1071)
    
    pat <- countpattern(xx, matching=TRUE)
    xx[, (names(pat$pat)) := 0]
    xx[cbind(seq_len(nrow(xx)), pat$matching + 3)] <- 1
    
    xx
    #   V1 V2 V3 000 001 010 011 100 101 110 111
    #1:  1  0  0   0   0   0   0   1   0   0   0
    #2:  1  0  0   0   0   0   0   1   0   0   0
    #3:  1  0  1   0   0   0   0   0   1   0   0
    #4:  0  1  1   0   0   0   1   0   0   0   0
    #5:  0  1  1   0   0   0   1   0   0   0   0
    

    【讨论】:

    • 神圣!那很快。我没想到。它有效!
    • @504aldo 谢谢!还使用countpattern 函数更新了答案。
    • 感谢您的两个答案,它们有效。我更喜欢第一个,因为我不想依赖e1071。如果你不介意,你能帮我理解两行:1)do.call 做什么? - 我可以看到最终结果,但是paste0(xx, collapse = "")paste... anything 的各种组合不会产生与do.call 相同的结果。我要去低谷?do.call 但仍然。 2) 最后一行,我知道您将列绑定到xx,但我仍然不明白 为什么 它有效。另外,我可以用+length(unique_vals) 代替+3 吗?
    • @504aldo 1) 如果您检查do.call 的输出,它会逐行粘贴列的所有值。所以do.call(paste0, xx)apply(xx, 1, paste0, collapse = "") 相同 2) 我们已经绑定了前一行中的列 ((unique_vals) := 0)。 match 用于获取我们需要分配 1 的列号。不,您不能用 length(unique_vals) 替换 +3,因为 length(unique_vals) 是要添加的新列数,而 +3 是在添加新列之前数据框中的原始列在这种情况下碰巧是相同的。
    • 感谢您帮助我理解。 apply(xx, 1, paste0, collapse = "") - 天哪,我觉得很尴尬,我没想到这一点。经过一些试验和错误后,我提出了另一个替代方案:Reduce(paste0, xx),但根据this postReducedo.call
    猜你喜欢
    • 1970-01-01
    • 2012-11-23
    • 2021-12-27
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多