【问题标题】:create a X % probability matrix from list of matrices从矩阵列表创建一个 X % 概率矩阵
【发布时间】:2017-07-14 16:02:26
【问题描述】:

我有一个矩阵列表(大约几十万)。我想创建一个单元格对应的单个矩阵,例如95%。我的意思是:如果例如单元格mat[1,2] 在 95% 的矩阵中为正(即 >0),它的得分为 1,如果例如单元格mat[2,1] 在 95% 的矩阵中为负数(即

#Dummy data
listX <- list()
for(i in 1:10){listX[[i]]<-matrix(rnorm(n = 25, mean = 0.5, sd = 1),5,5)}
listX2 <- listX
for(i in 1:10) { listX2[[i]] <- ifelse(listX[[i]] >0, 1, -1) }

为了获得虚拟数据,可以将 95% 更改为 60%,这样在 10 个矩阵中的 6 个中保持符号的单元格将被保留并得分为 1 或 -1,其余为 0。

我坚持这一点,因此无法提供更多代码。

【问题讨论】:

    标签: r list loops matrix probability


    【解决方案1】:

    您可以将列表更改为数组,然后对维度取平均值。

    arr <- simplify2array(listX)
    grzero = rowMeans(arr > 0, dims = 2) 
    lezero = rowMeans(arr < 0, dims = 2)  
    
    prop = 0.6
    
    1* (grzero >= prop) + -1* (lezero >= prop)
    

    【讨论】:

    • 我喜欢这个,但是将它与下面的@Chris 建议进行比较,我得到不同的输出矩阵(使用 Chris 的虚拟数据)。
    • @jO 我认为区别在于您是否使用&gt;= 与&gt; 作为您的阈值条件。改变解释了差异。
    • @chris,是的,看起来很像
    【解决方案2】:

    显示到目前为止哪些答案有效的测试用例! (编辑)

    您将在下面找到我的原始答案。它最终产生了与涉及随机种子数据的测试用例的其他答案相当的结果。为了三重检查,我创建了一个带有已知答案的小型测试数据集。事实证明,现在只有@Chris 的回答通过了(尽管如果在这个例子中使用&gt;=,@user20650 应该没问题,如 cmets 所示)。这是以防其他人想使用它:

    listX <- list(
      matrix(c(1,0,-1,1), nrow = 2),
      matrix(c(1,0,-1,1), nrow = 2),
      matrix(c(1,0, 1,0), nrow = 2)
    )
    
    # With any threshold < .67,
    # result should be...
    matrix(c(1, 0, -1, 1), nrow = 2)
    #>      [,1] [,2]
    #> [1,]    1   -1
    #> [2,]    0    1
    
    # Otherwise...
    matrix(c(1, 0, 0, 0), nrow = 2)
    #>      [,1] [,2]
    #> [1,]    1    0
    #> [2,]    0    0
    
    # @Chris answer passes
    threshold <- 0.5
    (Reduce('+',lapply(listX,function(x){x > 0}))/length(listX) >= threshold) - (Reduce('+',lapply(listX,function(x){x < 0}))/length(listX) >= threshold)
    #>      [,1] [,2]
    #> [1,]    1   -1
    #> [2,]    0    1
    
    threshold <- 1.0
    (Reduce('+',lapply(listX,function(x){x > 0}))/length(listX) >= threshold) - (Reduce('+',lapply(listX,function(x){x < 0}))/length(listX) >= threshold)
    #>      [,1] [,2]
    #> [1,]    1    0
    #> [2,]    0    0
    
    # My function fails...
    prob_matrix(listX, .5)
    #>      [,1] [,2]
    #> [1,]    1   -1
    #> [2,]    0    1
    prob_matrix(listX,  1)
    #>      [,1] [,2]
    #> [1,]    1    0
    #> [2,]    0    1
    
    # @user20650 answer fails...
    arr <- simplify2array(listX)
    grzero = rowSums(arr > 0, dims = 2) / length(listX)
    lezero = rowSums(arr < 0, dims = 2) / length(listX)
    prop = 0.5
    1* (grzero > prop) + -1* (lezero > prop)
    #>      [,1] [,2]
    #> [1,]    1   -1
    #> [2,]    0    1
    
    arr <- simplify2array(listX)
    grzero = rowSums(arr > 0, dims = 2) / length(listX)
    lezero = rowSums(arr < 0, dims = 2) / length(listX)
    prop = 1.0
    1* (grzero > prop) + -1* (lezero > prop)
    #>      [,1] [,2]
    #> [1,]    0    0
    #> [2,]    0    0
    

    原答案

    这是一种方法...

    • 结合 sign 和 Reduce 对每个单元格中的值的符号进行累积求和,返回单个矩阵。
    • 此值小于阈值数(您的概率 * 列表中的矩阵数)的任何单元格都将转换为 0。
    • 返回所有单元格的sign()。

    下面是一个带有包装函数的例子:

    玩具数据...

    set.seed(12)
    listX <- list()
    for(i in 1:10){listX[[i]]<-matrix(rnorm(n = 25, mean = 0, sd = 1), 5, 5)}
    

    功能...

    prob_matrix <- function(matrix_list, prob) {
      # Sum the signs of values in each cell
      matrix_list <- lapply(matrix_list, sign)
      x <- Reduce(`+`, matrix_list)
    
      # Convert cells below prob to 0, others to relevant sign
      x[abs(x) < (prob * length(matrix_list)) / 2] <- 0
      sign(x)
    }
    

    示例案例...

    prob_matrix(listX, .2)
    #>      [,1] [,2] [,3] [,4] [,5]
    #> [1,]   -1    1    0    1    0
    #> [2,]   -1    0   -1   -1    0
    #> [3,]    1   -1    1    1    1
    #> [4,]    0   -1    1    1   -1
    #> [5,]   -1    0   -1    0   -1
    
    prob_matrix(listX, .4)
    #>      [,1] [,2] [,3] [,4] [,5]
    #> [1,]   -1    1    0    1    0
    #> [2,]   -1    0   -1   -1    0
    #> [3,]    1   -1    1    1    1
    #> [4,]    0   -1    1    1   -1
    #> [5,]   -1    0   -1    0   -1
    
    prob_matrix(listX, .6)
    #>      [,1] [,2] [,3] [,4] [,5]
    #> [1,]    0    1    0    1    0
    #> [2,]   -1    0    0   -1    0
    #> [3,]    1   -1    0    1    1
    #> [4,]    0    0    0    1   -1
    #> [5,]   -1    0    0    0   -1
    
    prob_matrix(listX, .8)
    #>      [,1] [,2] [,3] [,4] [,5]
    #> [1,]    0    1    0    1    0
    #> [2,]   -1    0    0   -1    0
    #> [3,]    1   -1    0    1    1
    #> [4,]    0    0    0    1   -1
    #> [5,]   -1    0    0    0   -1
    

    【讨论】:

    • 感谢您的宝贵建议!不过,它们似乎都产生不同的输出,至少对于更长的列表和更高的阈值(?)
    • @jO。不知道你说的“他们都”是什么意思?顺便看一下,我只是将函数代码清理了一点,以便更好地阅读。
    • 所有三个答案都对应不同的方法。它们都有不同的输出,但至少前两个可以通过将 > 更改为 >= 来解决
    • 啊!我想我找到了问题所在。已编辑。现在适合我。看看它是否适合你。
    • 其实不用费心了。我们的结果将对应于这些测试用例,但我的功能不起作用。我将编辑此答案以显示测试用例的原因。然后任何其他答案都应该解决测试用例。
    【解决方案3】:

    我愿意:

    listX <- list()
    set.seed(20)
    # I set seed for reproducability, and changed your mean so you could see the negatives
    for(i in 1:10){listX[[i]]<-matrix(rnorm(n = 25, mean = 0, sd = 1),5,5)}
    
    threshold <- 0.7
    (Reduce('+',lapply(listX,function(x){x > 0}))/length(listX) >= threshold) - (Reduce('+',lapply(listX,function(x){x < 0}))/length(listX) >= threshold)
         [,1] [,2] [,3] [,4] [,5]
    [1,]    1    0    0   -1    1
    [2,]   -1    1   -1   -1    1
    [3,]    0    0    0    1    1
    [4,]    0    1    0    0    0
    [5,]    0    0    0    0    0
    

    这基本上检查了两个条件,并将两个检查加在一起。分解条件之一(Reduce('+',lapply(listX,function(x){x &gt; 0}))/length(listX) &gt; threshold)

    lapply(listX,function(x){x &gt; 0}) 循环遍历每个矩阵,并将其转换为每个大于零的值的真/假矩阵。

    Reduce('+',lapply(listX,function(x){x &gt; 0}))/length(listX) 然后将这些加在一起 ​​(Reduce),然后除以观察次数。如果比例大于我们的阈值,我们将该值设置为 1,否则设置为 0。

    然后,我们用x &lt; 0 作为测试减去相同的矩阵,在有足够多的子值为负的情况下,得到-1。

    【讨论】:

      猜你喜欢
      • 2018-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-05
      • 2016-07-29
      • 2016-07-14
      • 1970-01-01
      相关资源
      最近更新 更多