根据不同数字的数量对矩阵行进行排序

时间:2014-10-17 20:23:09

标签: r matrix

我有一个包含二进制向量行的矩阵:

library(gtools)
mat<-permutations(2,6,v=c(0,1),repeats.allowed=TRUE)

我想对矩阵的行进行排序,以使每行与其直接邻居(上方和下方)相差1位。

这可能吗?

2 个答案:

答案 0 :(得分:5)

有趣的问题!我想要实现这一目标的方法是从具有较少位数的那些矩阵中递归地构建这样的矩阵。假设我们有一个n位矩阵(包含所有2 ^ n个唯一的n位序列),其中每个邻居最多相差一个。如果我们rbind这个矩阵的反转(按行),那么结果的每一行最多相差1,中间的两行将是相同的。我们可以在前半部分前面添加0,在后半部分前面添加1。结果包含所有2 ^(n + 1)个唯一(n + 1)位序列,所有邻居的距离最多为1。

对于基本情况,我们可以使用(0 1)表示1位矩阵。

get.mat <- function(size) {
  if (size == 1) {
    return(matrix(c(0, 1), ncol=1))
  } else {
    smaller <- get.mat(size-1)
    return(rbind(cbind(0, smaller), cbind(1, smaller[nrow(smaller):1,])))
  }
}
get.mat(4)
#  [1,]    0    0    0    0
#  [2,]    0    0    0    1
#  [3,]    0    0    1    1
#  [4,]    0    0    1    0
#  [5,]    0    1    1    0
#  [6,]    0    1    1    1
#  [7,]    0    1    0    1
#  [8,]    0    1    0    0
#  [9,]    1    1    0    0
# [10,]    1    1    0    1
# [11,]    1    1    1    1
# [12,]    1    1    1    0
# [13,]    1    0    1    0
# [14,]    1    0    1    1
# [15,]    1    0    0    1
# [16,]    1    0    0    0

构建这些矩阵的方法的一个有趣的副作用是第一行和最后一行的距离也相互为止。

答案 1 :(得分:2)

这是另一种递归方法,感谢@josilber的想法。

# calculates the decimal difference between adjacent (1 digit difference) 
# binary digits of length n, starting with 2.
diffs <- function(n) {
    if (n == 1) {
        return(n)
    } else {
        k <- Recall(n - 1)
        c(k, 2^(n-1), rev(-k))
    }
}

get.mat2 <- function(ncols) {
    adj.ints <- rev(cumsum(c(0, diffs(ncols)))) # get all differences
    mat32 <- matrix(rev(as.integer(intToBits(adj.ints))), ncol=32, byrow=TRUE) # convert to binary representation in matrix
    mat32[, (33-ncols):32] # remove extraneous columns
}

如果您将行视为十进制整数,我很好奇图案是什么:

m <- get.mat(8)
ints <- strtoi(apply(m, 1, paste, collapse=''), 2)
plot(ints, type='b')

enter image description here

这显然是一种模式。它看起来非常稳定&#34;所以我采取了第一个区别:

diffs <- diff(strtoi(apply(m, 1, paste, collapse=''), 2))
plot(diffs, type='b')

enter image description here

在检查此图表几n后,上面的算法跳出来了。作为次要说明,这种方法似乎没有明显更快:

ncols <- 20
system.time(josilber <- get.mat(ncols))
#   user  system elapsed 
#   1.90    0.13    2.05 
system.time(plourde <- get.mat2(ncols))
#   user  system elapsed 
#   1.61    0.19    1.81 
josilber <- matrix(as.integer(josilber), ncol=ncol(josilber))
identical(josilber, plourde)
# TRUE