【问题标题】:How to fill in a three dimensional array using for nested loop如何使用 for 嵌套循环填充三维数组
【发布时间】:2020-02-25 14:37:53
【问题描述】:

我想使用嵌套循环创建一个三维数组,问题是循环似乎不起作用。 代码是:

s = array(NA,dim=c(5,5,4),dimnames=list(0:4,0:4,1:4))
for (i in 1:4)
{
  for (j in 0:i )
  {
    for (k in 0:i)
    {
      s[j,k,i]=(j+i+k)
    }
  }
}

我希望矩阵中的每个元素(例如元素(j,k,i)都可以是(j + k + i),但是最终结果中有很多NA,我该如何更改我的代码来实现它工作吗?

【问题讨论】:

  • (1) 当您使用[j,k,i] 进行索引时,您将索引数字列,而不是您分配的名称。如果你想使用名字,它们必须是字符,例如s[as.character(j),as.character(k),as.character(i)](这将解决"0"飞机被错过的问题。(2)NAs的其余部分是因为你的循环。你期待吗零?
  • (换句话说,s[1,1,1] 是在每个轴的第一个位置抓取第一个单元格,而 s["1","1","1"] 是根据您的暗角抓取第二行、第二列、第一个 z 平面-名称。)
  • 谢谢你的回答,因为这个数组会组成三个矩阵,我希望第一个矩阵,第1行和第2列的元素是0+1+1(j=0,k=1 ,i=1),但我编写的循环创建了一个 NA。
  • 我认为你错过了我的观点。行1、列2、平面1中的元素与行"1"、列"2"、平面"1"中的元素不同。当您使用字符串而不是数字时,它对我来说很好。 (s[1,2,1] == 2 对我来说是真的。)

标签: r arrays for-loop


【解决方案1】:

与其他一些语言不同,在 R 中,原始基本结构中没有零元素。因此,尝试分配第 0 个元素不会分配(有趣的是不会引发警告或错误)。因此,作为@r2evans cmets,您需要通过分配的dimnames 进行引用,这些dimnames 始终被强制转换为字符值。

此外,要填充所有 NA,对于所有可能的组合,内部 for 循环需要扩展到值的全长,而不是在 i 处终止

### BY DIMNAMES
s1 <- array(NA, dim=c(5,5,4), dimnames=list(0:4,0:4,1:4))

for (i in 1:4)
{
  for (j in 0:4)     # DO NOT END AT i
  {
    for (k in 0:4)   # DO NOT END AT i
    {
      s1[as.character(j),as.character(k),as.character(i)] <- (j+i+k)
    }
  }
}

但是,您可以通过适当的索引向每个内部循环添加1 进行引用,当然还要调整添加内容以与第一个对齐。事实上,对于下面每个时间的更多迭代,这往往比上面更快。

### BY INDEX
s2 <- array(NA, dim=c(5,5,4), dimnames=list(0:4,0:4,1:4))
for (i in 1:4)
{
  for (j in 1:5)
  {
    for (k in 1:5)
    {
      s2[j,k,i] <- as.integer((j-1) + (i-1) + k)
    }
  }
}

identical(s1, s2)
#[1] TRUE

或者,考虑使用mapply 进行循环隐藏的应用 解决方案,首先使用expand.grid() 生成所有可能的组合,然后逐个元素地遍历向量。而不是按索引分配并担心dimnames,而是使用[] 分配所有元素:

s3 <- array(NA, dim=c(5,5,4), dimnames=list(0:4,0:4,1:4))

prms <- expand.grid(j=0:4, k=0:4, i=1:4)
s3[] <- mapply(function(i,j,k) (j+i+k), prms$j, prms$k, prms$i)

identical(s1, s3)
#[1] TRUE

small iterationsmapplyfor 版本稍长。但在larger iterations,它与索引方法相当或略快。


当然,如果您始终可以实现矢量化,那么您的示例可以通过简单的 + 算术通过添加所有组合向量而不使用 forapply 循环来实现。这将是最快的方法。见上面的演示链接:

s4 <- array(NA, dim=c(5,5,4), dimnames=list(0:4,0:4,1:4))

prms <- expand.grid(j=0:4, k=0:4, i=1:4)
s4[] <- prms$j + prms$k + prms$i

identical(s1, s4)
#[1] TRUE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 2021-12-03
    • 1970-01-01
    相关资源
    最近更新 更多