【发布时间】:2019-12-23 08:05:54
【问题描述】:
在矩阵中,例如M1,行是国家,列是年份。这些国家在同一年份没有观察结果。我想找到给我最多国家的年份的“最佳”交叉点。最少年数和最少国家将被预先定义。结果中包含哪些国家/地区无关紧要,年份不必连续。
> M1
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15]
[1,] NA NA NA 2004 NA 2006 NA 2008 2009 NA 2011 2012 NA NA NA
[2,] NA 2002 NA 2004 NA NA 2007 NA NA 2010 2011 NA 2013 2014 NA
[3,] NA NA NA 2004 2005 2006 2007 2008 2009 NA NA 2012 2013 NA 2015
[4,] NA 2002 NA 2004 2005 2006 2007 2008 NA 2010 2011 NA 2013 NA NA
[5,] 2001 NA NA NA 2005 2006 2007 2008 NA 2010 NA 2012 2013 2014 NA
[6,] 2001 NA 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 NA 2014 NA
[7,] 2001 2002 NA NA 2005 NA 2007 NA 2009 NA 2011 NA NA 2014 2015
[8,] 2001 2002 NA 2004 2005 2006 NA NA NA 2010 NA NA 2013 NA 2015
[9,] NA 2002 NA 2004 2005 NA 2007 NA NA 2010 2011 NA NA NA NA
[10,] 2001 2002 NA 2004 NA NA NA NA NA 2010 NA 2012 NA 2014 2015
因为没有明显的相交,单个Reduce(intersect...) 尝试将不起作用,我通过连续排除一个国家/地区直到定义的阈值n.row 反复这样做。结果至少过滤了几年n.col。这个函数是我写的,
findBestIntersect <- function(M, min.row=5, min.col=3) {
## min.row: minimum number of rows (countries) to analyze
## min.col: minimum number of complete columns (years)
# put matrices with row combn into list (HUGE!)
L1 <- lapply(min.row:(nrow(M) - 1), function(x)
combn(nrow(M), x, function(i) M[i, ], simplify=FALSE))
# select lists w/ def. number of complete columns
slc <- sapply(L1, function(y) # numbers of lists
which(sapply(y, function(x)
sum(!(apply(x, 2, function(i) any(is.na(i))))))
>= min.col))
# list selected lists
L2 <- Map(function(x, i)
x[i], L1[lengths(slc) > 0], slc[lengths(slc) > 0])
# find intersects
L3 <- rapply(L2, function(l)
as.integer(na.omit(Reduce(intersect, as.list(as.data.frame(t(l)))))),
how="list")
return(unique(unlist(L3, recursive=FALSE)))
}
这很快就给了我想要的M1 的结果。
> system.time(best.yrs.1 <- findBestIntersect(M1))
user system elapsed
0.06 0.00 0.07
> best.yrs.1
[[1]]
[1] 2002 2004 2010
但是M2 的性能只能接受(RAM 使用量约为 1.1 GB),
> system.time(best.yrs.2 <- findBestIntersect(M2))
user system elapsed
79.90 0.39 82.76
> head(best.yrs.2, 3)
[[1]]
[1] 2002 2009 2015
[[2]]
[1] 2002 2014 2015
[[3]]
[1] 2003 2009 2010
你不想用类似于我的真实矩阵的M3(爆炸 32 GB RAM)来尝试这个:
# best.yrs.3 <- findBestIntersect(M3)
可能这个函数最大的缺陷就是L1变得太大太快了。
那么,我的问题是,有没有更好的方法也适用于M3? “奖金”将最大化国家和年份。如果可能的话,我想在没有额外软件包的情况下这样做。
数据
set.seed(42)
tf <- matrix(sample(c(TRUE, FALSE), 150, replace=TRUE), 10)
M1 <- t(replicate(10, 2001:2015, simplify=TRUE))
M1[tf] <- NA
tf <- matrix(sample(c(TRUE, FALSE), 300, replace=TRUE), 20)
M2 <- t(replicate(20, 2001:2015, simplify=TRUE))
M2[tf] <- NA
tf <- matrix(sample(c(TRUE, FALSE), 1488, replace=TRUE), 31)
M3 <- t(replicate(31, 1969:2016, simplify=TRUE))
M3[tf] <- NA
【问题讨论】:
-
@BenNutzer 你的意思是
tf^1 %*% t(tf^1)?你有什么不清楚的地方? -
不幸的是,问题源于
combn()函数,即如果我只运行combn(31,16),我会遇到内存问题。即使我从RcppAlgos包中尝试comboGeneral(),它也会再次出现问题。 -
@BenNutzer 好的,即
t(tf^1) %*% tf^1。看起来很有希望。但是我不确定我能用这个输出做什么? -
@maydin 你准确地描述了我的问题:)
-
我想尝试一下混合整数编程,但不幸的是我还没有真正理解这个问题。这里的目标和约束是什么? " find the "best" intersect of years that give me the most countries" 是什么意思?
标签: r algorithm performance intersection