首页 > 解决方案 > 仅针对其副作用逐行运行表达式

问题描述

我经常想在 tibble 的每一行上运行一个表达式或调用一个函数,纯粹是为了产生副作用,而对返回值没有任何兴趣。例如,我可能有一个 tibble,其中包含我想使用字符列中的文件名保存的数据列表列。当然有无数种方法可以做到这一点,但我更愿意像 dplyr (1.0) 中的其他按行操作一样优雅地做到这一点。本质上,我正在寻找 rowwisemutate()purrr::walk(). 这是我想要做的一个丑陋的近似:

library(tidyverse)
dat <- 
  tibble(file = c("iris.csv", "mtcars.csv"),
         data = list(iris, mtcars))
dat %>% rowwise() %>% mutate(x = list(write_csv(data, file))) %>% invisible()

有没有一种方法可以消除x = list(…)返回值的内容和显式隐藏,同时保持对函数调用中“数据变量”的轻松访问(没有丑陋的东西.x$data[[1]])?假设有这样一个函数(walk_rows()?)我希望像这样使用它:

dat %>% walk_rows(write_csv(data, file)))

我知道我可以这样做:

dat %>% pwalk(function(dat, file) write_csv(dat, file))

但是必须写两次数据变量的名称是不雅的。

标签: rdplyrtidyverse

解决方案


我不清楚您是否正在寻找已经在 tidyverse 中允许您想要的东西,或者您是否正在寻找walk_rows. 我不知道 tidyverse 中的任何内容完全符合您的要求,但这里有一个实现walk_rows

walk_rows <- function(dat, expr)
{
  `%>%` <- dplyr::`%>%`
  m <- as.list(match.call())[-(1:2)]
  dummy <- dat %>% 
    dplyr::rowwise() %>% 
    dplyr::summarize(x = list(eval(m$expr)), .groups = "drop")
}

所以你可以这样做:

dat %>% walk_rows(write.csv(data, file))

它悄悄地写你的文件。或者,例如:

dat %>% walk_rows(print(paste0(file, ": ", nrow(data))))
#> [1] "iris.csv: 150"
#> [1] "mtcars.csv: 32"

推荐阅读