【问题标题】:Can not set sheet name with dplyr package无法使用 dplyr 包设置工作表名称
【发布时间】:2020-07-06 16:25:33
【问题描述】:

我将列表中的多个数据框导出到一个 excel 文件中的不同工作表中,我可以使用以下代码执行此操作(以 mtcars 为例):

library(tidyverse)
library(ImportExport)

data_list <- split(mtcars, mtcars$cyl)
table_name <- names(data_list)

# Run
excel_export(data_list, "foo.xlsx", table_names = tab_name)

然后,我想用另一种方式做到这一点,因为我看到 dplyr 文档说:

.y 引用键,一个一行 tibble,每列一列 标识组的分组变量。

所以我认为.y 等于我创建的变量table_name,我这样做:

data_list %>% excel_export("foo.xlsx", table_names = .y)

然后我得到一个错误:

.jcall(wb, "Lorg/apache/poi/ss/usermodel/Sheet;", "createSheet", : 找不到对象 '.y'

有人可以解释为什么以及如何使用.y 来做到这一点。

我们将不胜感激。

【问题讨论】:

  • 您在文档中的何处找到该引文?我认为你应该使用data_list %&gt;% excel_export("foo.xlsx", table_names = tab_name)
  • 嗨@RonakShah,我认识你。几天前你在my another question 上回复我。您提供的代码purrr::imap(df1, ~dplyr::mutate(.x, from = .y)) 对我很有帮助。我不知道.x.y 到底是什么意思,然后我分别用.x.y 作为关键字搜索了dplyr 文档。我在group_map 函数中描述的第 38 页上找到了一些关于它们的信息。所以我模仿你之前的代码包含.y来解决这个问题。
  • .x.y 是要在要调用的表达式中使用的 占位符。想象在group_walk 下面是这样的:for (.y in names(thedata)) { .x &lt;- thedata[[.y]]; expr; },您提供的expression 会将.x.y 变量视为对象。

标签: r dplyr


【解决方案1】:
  1. 如果你引用一个引用,我认为使用引用引用的函数是有意义的。在这种情况下,我在 group_map 中找到了它(其中包括 group_walk,这是一个主要在副作用中运行的补充函数)。

  2. 您仍然需要group_by 数据。更具体地说,它需要在tbl_df(不是list)上运行,通常(但不总是)分组 tibble。

我既没有安装ImportExport 也没有安装xlsx(前者所依赖的),所以我将使用write.csv 代理你的操作。

library(dplyr)
mtcars %>%
  group_by(cyl) %>%
  group_walk(~ write.csv(.x, paste0(.y, ".csv")))

这样做的副作用是在当前目录中创建了三个文件,名为 4.csv6.csv8.csv

如果要对命名列表进行操作,也可以使用以下之一:

# using: data_list <- split(mtcars, mtcars$cyl)
purrr::imap(data_list,
            ~ write.csv(.x, paste0("~/Downloads/", .y, ".csv")))
Map(write.csv, data_list, paste0(names(data_list), ".csv"))

效果是一样的。

【讨论】:

    【解决方案2】:

    .x.y 不是可以在任何地方使用的全局参数,它们是为特定功能保留的。 (通常是map

    来自?map

    .f 函数、公式或向量(不一定是原子的)。

    如果是公式,例如~ .x + 2,它被转换为一个函数。引用参数的方式有以下三种:

    • 对于单参数函数,请使用 .
    • 对于两个参数的函数,使用 .x 和 .y
    • 如需更多参数,请使用 ..1、..2、..3 等

    我们来个简单的列表

    library(purrr)
    listvec1 <- list(a = 1:3, b = 4:6, c = 2:4)
    

    1) 假设我们要将列表中的每个元素都乘以 2,map 有一个参数,所以我们在这里使用 .

    map(listvec1, ~. * 2)
    #$a
    #[1] 2 4 6
    
    #$b
    #[1]  8 10 12
    
    #$c
    #[1] 4 6 8
    

    巧合的是.x 也在这里工作:

    map(listvec1, ~.x * 2)
    

    但如果你使用.y,它会报错,因为map 中没有两个参数。

    map(listvec, ~.y * 2)
    

    .f(.x[[i]], ...) 中的错误:... 列表包含的元素少于 2 个

    2) 让我们使用另一个列表,现在添加listvec1listvec2。为此,我们可以使用map2,它有两个参数,所以在这里我们将它们称为.x.y

    listvec2 <- list(a = 7, b = 8, c = 9)
    map2(listvec1,listvec2, ~.x + .y)
    #you could actually simplify this as but anyway this is just an example
    #map2(listvec1,listvec2, `+`)
    
    #$a
    #[1]  8  9 10
    
    #$b
    #[1] 12 13 14
    
    #$c
    #[1] 11 12 13
    

    同样,我们在imap 中使用.x.y,其中.x 是元素,.y 是列表的名称(如果存在)或索引。


    在上面的帖子中.y 没有任何意义,所以将其用作

    data_list %>% excel_export("foo.xlsx", table_names = .y)
    

    肯定会产生错误。您需要使用上述特定功能才能使用.x.y。所以如果你想为你的命令使用管道,你应该使用

    data_list %>% excel_export("foo.xlsx", table_names = tab_name)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多