【问题标题】:R: Extract values from matrix relative to row/column positionR:从矩阵中提取相对于行/列位置的值
【发布时间】:2015-11-14 01:26:58
【问题描述】:

我的问题如下:假设我们有一个二次n*n矩阵,例如

m <- matrix(runif(n^2), n,n)

现在我想定义一个函数f=function(k),它返回所有矩阵条目的总和,其中它们的行数和列数的总和弱超过k。例如,考虑 3*3 矩阵

m.ex <- matrix(1:9, 3,3, byrow = T)

看起来像

1 2 3
4 5 6
7 8 9

那么 f(2) 应该给出 45 = 1+2+3+4+5+6+7+8+9 (对于矩阵中的每个条目,行和列位置的总和弱超过2) , f(4) = 38 = 3+5+6+7+8+9 (因为位置 (1,3), (2,2), (2,3) 的行和列位置之和弱超过 4 )、(3,1)、(3,2) 和 (3,3)),并且 f(5) = 23 = 6 + 8 + 9(因为行和列位置的总和弱超过 5 的位置(2,3)、(3,2) 和 (3,3))。等等。

【问题讨论】:

  • 你已经尝试过什么?而且 - 原谅我的无知 - 数字 h 什么时候弱超过数字 k?
  • 我目前正在解决这个问题(我需要这个作为模拟中的子功能),所以我还没有尝试太多。显然,我可以通过循环来做到这一点,但我正在寻找更优雅(更快)的东西。如果 h >= k,则数字 h 弱于数字 k。
  • 啊...抱歉...在您关于不想使用循环的评论出现之前,我发布了带有循环的快速而肮脏的解决方案。我再看看。
  • 没关系,我仍然非常感谢您的意见。感谢您试一试!
  • 这个和this关系很密切

标签: r matrix


【解决方案1】:

rowcolumn 函数使这种方式比其他解决方案更简单,如果我理解正确的话:

f <- function(k, m) sum(m[row(m) + col(m) >= k])

为您的m.ex

sapply(c(2, 4, 5), f, m = m.ex)
# [1] 45 38 23

更大的例子:

set.seed(1230)
n <- 8
> print(round(m <- matrix(runif(n^2), nrow = n), 2))
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 0.57 0.87 0.94 0.98 0.87 0.66 0.16 0.98
[2,] 0.65 0.79 0.68 0.74 0.12 0.65 0.56 0.73
[3,] 0.76 0.85 0.71 0.45 0.64 0.45 0.12 0.55
[4,] 0.26 0.09 0.67 0.66 0.58 0.48 0.54 0.20
[5,] 0.38 0.63 0.27 0.16 0.20 0.96 0.05 0.90
[6,] 0.49 0.48 0.71 0.32 0.46 0.98 0.17 0.96
[7,] 0.91 0.99 0.97 0.98 0.84 0.21 0.21 0.44
[8,] 0.62 0.08 0.80 0.88 0.85 0.30 0.61 0.42
> f(12, m)
[1] 8.028652

这可以通过注意您在右下三角形中表示的条目来确认:

   *    *    *    *    *    *    *    *
   *    *    *    *    *    *    *    *
   *    *    *    *    *    *    *    *
   *    *    *    *    *    *    * 0.20
   *    *    *    *    *    * 0.05 0.90
   *    *    *    *    * 0.98 0.17 0.96
   *    *    *    * 0.84 0.21 0.21 0.44
   *    *    * 0.88 0.85 0.30 0.61 0.42

所以总和是0.88+0.84+0.85+0.98+0.21+0.3+0.05+0.17+0.21+0.61+0.2+0.9+0.96+0.44+0.42,大约是 8.03。

【讨论】:

  • 现在这是一个非常优雅的解决方案!易于阅读和理解,并且执行迅速。我隐约记得有 rowcolumn 之类的东西存在,但我一生都记不起它们,也找不到它们。我猜是错误的搜索词。我做了一些基准测试。在填充随机数的 1000x1000 矩阵上,这个解决方案的速度大约是 Heroka 的两倍,比我的要快一千多倍。
  • 当我第一次看到这些功能时,我自己都被震撼了。超酷但隐藏良好的基本函数
  • 这个解决方案比我的要优雅得多。 @Yuri Robbers:也许最好接受这个作为答案,所以当其他人搜索相同的问题时,它会显示在最前面。
  • @Heroka:如果可以的话,我会的,但这不是我的问题,所以 Martin 必须这样做......
  • 糟糕,对谁是 OP 感到困惑。对不起。 @Martin:你能改变最佳答案吗?
【解决方案2】:

没有循环,希望有用。

library(reshape2)

#easy way to get all row and column indexes is to transform matrix to long
#has advantage of allowing vectorized computation and avoiding for-loops
myfun <- function(k, mm){
  #reshape matrix to easily get column and row numbers
  melt_m <- melt(mm, varnames=c("row","col"))
  #add row and col indixes
  melt_m$sum_row_col <- melt_m$row + melt_m$col
  #calculate result and return (sum of value when sum of rowcol>=k)
  return(sum(melt_m$value[melt_m$sum_row_col>=k]))
}

#example 1
test_m <- matrix(1:9,3,3,byrow=T)


> myfun(k=2,mm=test_m)
[1] 45
> myfun(k=4, mm=test_m)
[1] 38

melt 对矩阵的作用示例:

> test_m
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
> melt(test_m,varnames=c("row","col"))
  row col value
1   1   1     1
2   2   1     4
3   3   1     7
4   1   2     2
5   2   2     5
6   3   2     8
7   1   3     3
8   2   3     6
9   3   3     9

【讨论】:

  • 如果你想要这些值当然很容易编辑,但我读了你的描述,因为你想要返回的总和 -->。
  • 非常感谢,看起来很棒。我会看一下 melt 函数,以了解您在做什么。
  • 添加了熔化矩阵的示例输出。我的想法是将数据转换为三个向量(以避免循环):行索引、列索引和值。从那里开始,这很简单。
  • 完美,我现在明白了。感谢您提供如此出色的解决方案:)
  • 顺便说一句,我认为还有一个更简单的方法。我们可以定义一个函数 indexsums(n),它返回 matrix(1,n, n,n, byrow=T) + 1:n
【解决方案3】:

嗯,它很慢而且很丑,我相信很多人会想出更好、更快、更漂亮的解决方案,但这对你有用:

weakly_exceeds_sum <- function(m, k){
    tmp <- NULL
    for(i in 1:nrow(m)){
        for(j in 1:nrow(m)){
            if(i+j>=k){
            tmp<-c(tmp, m[i,j])
            }
        }
    }
    sum(tmp)
}

在哪里调用函数,例如:weakly_exceeds_sum(m.ex, 2)

【讨论】:

  • 非常感谢您的努力,完美运行。这也是我的方法,但理想情况下我会寻找避免循环的东西。本质上,我们只想提取位于与矩阵的非对角线平行的直线及其下方的值。
猜你喜欢
  • 2020-06-12
  • 2021-05-04
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
  • 2014-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多