【问题标题】:R: how to identify the minimum representative vector/row sets from a list of vectors/dataframeR:如何从向量/数据框列表中识别最小代表性向量/行集
【发布时间】:2016-05-08 14:24:18
【问题描述】:

我有一个向量列表,每个向量都包含许多元素。我想确定具有最大覆盖唯一元素的向量的最小数量。例如,如果向量表示为二进制数据框中的行,列中的唯一元素,如下所示:

    >df<- data.frame(a=c(1,0,0,0,0),b=c(1,1,1,1,0),c=c(1,0,1,1,1),d=c(0,0,0,1,1),e=c(0,0,0,1,1), f=c(0,0,0,0,1))
    > df
        a b c d e f
      1 1 1 1 0 0 0
      2 0 1 0 0 0 0
      3 0 1 1 0 0 0
      4 0 1 1 1 1 0
      5 0 0 1 1 1 1

假设向量是从 1 到 5 的行,并且它们包含元素 a 到 f 的不同组合。我想获得覆盖尽可能多的元素的最小代表向量或行。在这个例子中,最小代表(最大简约)向量是第 1 行和第 5 行。有没有办法在统计上做到这一点?我试图在双向聚类热图中可视化数据集,以手动识别最小组合。但是,有没有一种统计方法可以处理这个问题并能够提供一些选择性能的数字度量?

另一个例子来说明我的问题。给定以下向量:

    > vec.1 <- c("a", "c", "d")
    > vec.2 <- c("a", "b", "c", "d")
    > vec.3 <- c("b","e")
    > vec.4 <- c("b", "c", "d", "g")
    > vec.5 <- c("f","g")

最小组合是 2,3 和 5,因为它们覆盖了从 a 到 g 的所有元素,并且重叠最少。在较大的数据集中,可能有多个答案,但是,组合中的向量数量越少越好。 谢谢。

【问题讨论】:

  • 你需要i1 &lt;- apply(df, 1, FUN = function(x) length(rle(x)$values));df[i1,]
  • 这是一个组合问题。第一:是否有一行全为 1?如果不是第二个:是否存在涵盖所有元素的两行组合。如果不是: ... 三 ... 使用函数combn() 生成组合。如果找到组合,则计算重叠量以选择重叠最小的组合。

标签: r


【解决方案1】:

一种解决方案是计算行之间的“重叠”并提取具有最大重叠的行对,如下所示:

m <- apply(df, 1, function(x) apply(df, 1, function(y) sum(x | y)))
which(m == max(m), arr.ind = TRUE)

结果输出是:

     row col
[1,]   5   1
[2,]   1   5

您可以选择任一组合(因为第 1 行与第 5 行和第 5 行与第 1 行相同)。

这个方法虽然使用了 n^2 次操作。不确定是否有更有效的包/算法可以找到最大汉明距离对的行,这似乎是您想要的。

【讨论】:

  • 您好 Gopala,非常感谢您的回复。我已经在我的数据集中尝试过这个,它给了我最大覆盖率的对。有没有办法获得最大覆盖率的组合,即 2 行或更多。以尽可能少的行数表示所有数据的想法。因此,如果我正确理解您的方法,则应在所有可能的行组合上测试重叠。
  • 会有计算上禁止的组合来测试。不知道这将如何工作。
【解决方案2】:

这是一个组合问题。第一:是否有一行全为 1?如果不是第二个:是否存在涵盖所有元素的两行组合。如果不是:...三个...使用函数combn() 生成组合。如果找到组合,则计算重叠量以选择重叠最小的组合:

df<- data.frame(a=c(1,0,0,0,0),b=c(1,1,1,1,0),c=c(1,0,1,1,1),d=c(0,0,0,1,1),e=c(0,0,0,1,1), f=c(0,0,0,0,1))
n <- nrow(df)
test1.allc <- function(i) all(colSums(df[i,, drop=FALSE])>0)
for (i in 1:n) {
  Ci <- combn(n,i)
  t1 <- apply(Ci, 2, test1.allc)
  if (any(t1)) break # minimal number of rows/vectors is i
}
print(i) # number of rows needed to have all elements
Ci <- Ci[, t1, drop=FALSE] # only valid combinations

overlap <- function(j) { o <- colSums(df[j,, drop=FALSE]); sum(o) - length(o) }
j <- which.min(apply(Ci, 2, overlap))
print(j) # the j-th combination(s) has/have minimal overlap
for (jj in j) print(df[Ci[, jj],])

【讨论】:

  • 嗨,jogo。谢谢您的答复。我已经尝试过了,它给了我这个错误:base::colSums(x, na.rm = na.rm, dims = dims, ...) 中的错误:'x' 必须是至少二维的数组。
  • @Samar.y 您使用了其他数据?对于给定的数据,代码给出了正确的结果。我编辑了我的答案,使其更加可靠。
猜你喜欢
  • 1970-01-01
  • 2021-05-14
  • 1970-01-01
  • 1970-01-01
  • 2020-04-27
  • 1970-01-01
  • 1970-01-01
  • 2014-07-10
  • 2021-01-18
相关资源
最近更新 更多