【问题标题】:R: Naming matrix rows/columns in a for-loop works in console, but not when knittingR:在for循环中命名矩阵行/列在控制台中有效,但在编织时无效
【发布时间】:2020-09-28 01:45:14
【问题描述】:

我正在尝试使用for 循环通过以下代码重命名矩阵的行和列:

Z = matrix(c(1:120), 15, 8)
for (i in 1:15) {
  rownames(Z)[i] = paste0("[", format((-1)*(4-(i/10)), nsmall=1), "]")
}
for (j in 1:8) {
  colnames(Z)[j] = paste0("[", (j-1)/100, "]")
}

当输入到控制台时,这将按预期工作,并生成以下矩阵Z

       [.00] [.01] [.02] [.03] [.04] [.05] [.06] [.07]
[-3.9]     1    16    31    46    61    76    91   106
[-3.8]     2    17    32    47    62    77    92   107
[-3.7]     3    18    33    48    63    78    93   108
[-3.6]     4    19    34    49    64    79    94   109
[-3.5]     5    20    35    50    65    80    95   110
[-3.4]     6    21    36    51    66    81    96   111
[-3.3]     7    22    37    52    67    82    97   112
[-3.2]     8    23    38    53    68    83    98   113
[-3.1]     9    24    39    54    69    84    99   114
[-3.0]    10    25    40    55    70    85   100   115
[-2.9]    11    26    41    56    71    86   101   116
[-2.8]    12    27    42    57    72    87   102   117
[-2.7]    13    28    43    58    73    88   103   118
[-2.6]    14    29    44    59    74    89   104   119
[-2.5]    15    30    45    60    75    90   105   120

但是,我需要将其包含在一个编织成 PDF 的 R Markdown 文档中,就像在这个 MWE 中一样:

---
title: "Title"
author: "Author"
date: "1970-01-01"
output: pdf_document
---

```{r}
Z = matrix(c(1:120), 15, 8)
for (i in 1:15) {
  rownames(Z)[i] = paste0("[", format((-1)*(4-(i/10)), nsmall=1), "]")
}
for (j in 1:8) {
  colnames(Z)[j] = paste0("[", (j-1)/100, "]")
}
```

尝试编织此文档时,R Markdown 返回错误

Error in dimnames(x) <- dn : length of 'dimnames' [1] not equal to array extent

然后执行停止。

我发现上述错误已被广泛讨论,但错误的原因是尝试为行数或列数提供太少或太多名称时。但是,这里不应该是这样,而且由于代码在进入控制台时没有返回这个错误,所以我一直无法找到 Markdown 拒绝它的原因。

(我意识到将向量分配给行名和列名是首选,尤其是因为名称是已知的;但这是为了让我熟悉循环的大学课堂作业,因此作业需要一切都必须在循环内完成。)

我在 Windows 10 版本 1909 build 18363.1082 上使用 R 版本 3.6.2 和 RStudio 版本 1.2.5033。任何帮助表示赞赏!

编辑 1:@Wil 要求的sessionInfo() 的输出:

R version 3.6.2 (2019-12-12)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)

Matrix products: default

Random number generation:
 RNG:     Mersenne-Twister 
 Normal:  Inversion 
 Sample:  Rounding 
 
locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] compiler_3.6.2  htmltools_0.4.0 tools_3.6.2     yaml_2.2.0      Rcpp_1.0.3     
 [6] rmarkdown_2.0   knitr_1.26      digest_0.6.23   xfun_0.12       rlang_0.4.4    
[11] evaluate_0.14  

【问题讨论】:

  • 当我尝试加载您的起始示例代码(定义 Z 和行/列名)时,我收到了 sae Error in dimnames(x) 错误。在我尝试编织任何东西之前。尝试清理您的环境 - 看起来问题出在编织的上游。
  • 您能否将sessionInfo() 的输出添加到您的问题中?
  • @andrew_reece 我清除了我的环境,现在错误发生在控制台上,正如您所指出的。那意味着什么?在清除环境之前,我能够修改循环代码以将名称更改为任何内容。
  • @Shaman 请参阅下面的答案,for 循环不适用于您使用的方法。
  • @Wil 我已将输出添加到我的问题中。

标签: r


【解决方案1】:

对于没有任何定义的行名或列名的矩阵Zrownames(Z)colnames(Z) 的值为NULL。您收到此错误是因为您尝试将 [i] 子集化为 NULL,但这是行不通的。

Z = matrix(c(1:120), 15, 8)
rownames(Z) # NULL
rownames(Z)[1] # NULL 
rownames(Z)[1] <- "foo" 
# Error in dimnames(x) <- dn : length of 'dimnames' [1] not equal to array extent

请注意,colnames()/rownames() 的基本 R 文档中对此进行了讨论:

结构如

rownames(x)[3] &lt;- "c"

除非 x 已经有 dimnames,否则可能无法工作,因为这将从 rownames(x) 的 NULL 值创建一个长度为 3 的值。

可以使用矢量化输入分配行名,例如:

rownames(Z) <- paste0("[", format((-1)*(4-(1:15/10)), nsmall=1), "]")

但从你的帖子看来,这个练习的重点是for-loops。根据文档,这不是在新矩阵上设置名称的可行选项。

如果您不能使用纯矢量化方法,我能想到的涉及for-loop 的最接近的解决方案是将行名值循环到一个向量中,然后将该向量分配为rownames(Z)。但这似乎是一个不必要的中间步骤,所以我不确定它是否真的是一个有用的学习模式。

new_rownames <- vector(mode = "character", length = nrow(Z))

for (i in 1:15) {
  new_rownames[i] = paste0("[", format((-1)*(4-(i/10)), nsmall=1), "]")
}

rownames(Z) <- new_rownames

另一种选择可能是将一组空值分配给Z 的行名/列名:

Z = matrix(c(1:120), 15, 8, dimnames = list(1:15, 1:8))

然后您可以按预期使用原始循环。

【讨论】:

  • 我发现我可以通过分配一次名称来解决该错误,即rownames(Z) = c(1:15),之后循环将起作用,Markdown 将正确编织。如何将我的解决方案发布到我自己的问题?对不起,我是新用户!
  • @Shaman 请注意,我刚刚进行了更新,它基本上提供了您的解决方案。您在原始帖子中写道根本不允许向量分配,这就是为什么 rownames(Z) = 1:15 方法似乎是禁止的,因为它是向量分配。但是,如果您的家庭作业可以接受,那么我在回答中提到的内容涵盖了这种方法。
  • 非常感谢您的帮助!我很抱歉未能很好地传达需求;这在作业中是可以接受的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-23
  • 1970-01-01
相关资源
最近更新 更多