列出 knitr 环境(在 R 块中使用 list2env 时出现 R-markdown 错误)

Listing to knitr environment (R-markdown error when using list2env in R chunks)

编辑:我发现问题源于 yaml 代码。它来自将此解决方案应用于 。我相信它在 knitr 代码中创建了一个父环境,因此 list2env 产生了意想不到的行为

需要说明的是,下面的代码 运行 在 R 中是完美的。

我在 knitr 代码中使用 list2envenvir = .GlobalEnv。这不起作用,因为它在 knitr 环境之外创建对象(当我在 R-markdown 中 运行 我的 R 代码时,我收到错误 ,因为创建的对象仅存在于全局环境中)。我正在尝试找到 list2env 的替代方法或告诉 list2env 列出当前 knitr 环境的方法。

R 中的准备工作

# setwd to an empty folder
setwd("C:/../testing_environment")

library(writexl)
library(readxl)

# Example data
write_xlsx(mtcars, "mt_cars.xlsx")
write_xlsx(mtcars, "mt_car_s.xlsx")

在 R-markdown 中编织的代码(link 用于安装):

---
title: thetitle
author: myinititals
output:
  word_document
date: "`r Sys.Date()`"
knit: (function(inputFile, encoding) { 
          out_dir <- 'test';
          rmarkdown::render(inputFile,
                            encoding=encoding, 
                            output_file=file.path(dirname(inputFile), out_dir, 'analysis.docx')) })
```{r}

library(writexl)
library(readxl)

setwd("C:/../testing_environment")

paths <- list.files(pattern="*.xlsx")
read_all_sheets <- 
  function(path) sapply(excel_sheets(path), read_excel, path = path, USE.NAMES = TRUE, simplify = FALSE)
xl_list <- sapply(paths, read_all_sheets, USE.NAMES = TRUE, simplify = FALSE)

# List to environment - ISSUE
for (i in seq_along(xl_list)) {
  list2env(xl_list[[i]], envir = .GlobalEnv)
}

# THIS LINE CRASHES THE CODE
names(mt_car_s)  

```

错误:

我已经通过删除 names(mt_car_s) 并执行以下操作来检查会发生什么:

list2env(xl_list, envir = .GlobalEnv)
## <environment: R_GlobalEnv>
ls()
## [1] "i"               "paths"           "read_all_sheets"          
## [4] "xl_list"

但它根本没有列出 xl_list.

中的对象

有什么办法可以把这些文件放到环境中吗?例如写入创建的 knitr 环境的代码?如果不是,还有什么其他可能的解决方案可以防止这种行为?

编辑 2,您可以执行以下操作:

for (i in seq_along(xl_list)) {
    n <- names(xl_list[[i]])
    print(n)
    for (j in seq_along(n)) {
      assign(n[j], xl_list[[i]][[j]])
  }
}

使用assign()(默认进入当前环境)大概可以达到你想要的效果。在这里,我从列表 xl_list 中的名称中删除“.xlsx”,以便嵌套列表的第一层具有您希望成为当前环境中的对象的名称,以及 [=15= 中的名称]那些对象是sheet个名字

---
title: "Sample Document"
output:
  word_document
---
    
```{r}
library(writexl)
library(readxl)

setwd("C:/../testing_environment")

paths <- list.files(pattern="*.xlsx")
read_all_sheets <-function(path) sapply(excel_sheets(path), read_excel, path = path, USE.NAMES = TRUE, simplify = FALSE)
xl_list <- sapply(paths, read_all_sheets, USE.NAMES = TRUE, simplify = FALSE)

# remove file extension from e.g. mt_car_s.xlsx
names(xl_list) <- gsub("\.xlsx", "", names(xl_list))

# assign each element of the list 
# (itself a list of sheets/data frames)
# an object name in current environment
for (i in seq_along(xl_list)) {
  n <- names(xl_list[i])
  assign(n, xl_list[[i]])
}

names(mt_car_s)
names(mt_car_s$Sheet1)
```

渲染 R Markdown 文档的环境可以通过 envir 选项更改为 rmarkdown::render()。通常,无法保证渲染环境是全局环境或其子环境——因此您不应尝试分配给 .GlobalEnv.

相反,通过在 list2env() 调用中将 .GlobalEnv 替换为 environment() 来分配给当前环境。