我正要问一个与此非常相似的问题。基本上,询问如何使用pmap
insidemutate
而不必多次使用变量名。相反,我会将它作为“答案”发布在这里,因为它包括一个代表和一些我发现的选项,其中没有一个让我完全满意。希望其他人可以根据需要回答如何执行此操作。
在使用带有列表列的 data.frame 时,我经常想使用purrr::pmap
inside 。dplyr::mutate
有时这涉及到变量名的大量重复。我希望能够更简洁地做到这一点,使用匿名函数,以便变量在传递给pmap
's.f
参数时只使用一次。
以这个小数据集为例:
library('dplyr')
library('purrr')
df <- tribble(
~x, ~y, ~z,
c(1), c(1,10), c(1, 10, 100),
c(2), c(2,20), c(2, 20, 200),
)
说我要应用于每一行的功能是
func <- function(x, y, z){c(sum(x), sum(y), sum(z))}
在实践中,函数会更复杂,有很多变量。该函数只需要一次,所以我不想明确命名它并阻塞我的脚本和我的工作环境。
这是选项。每个都创建完全相同的 data.frame 但以不同的方式。包含avg`` will be come clear.
Note I'm not considering position matching using
..1 ,
..2` 等的原因很容易搞砸。
# Explicitly create a function for `.f`.
# This requires using the variable names (x, y, z) three times.
# It's completely clear what it's doing, but needs a lot of typing.
# It might sometimes fail - see https://github.com/tidyverse/purrr/issues/280
df_explicit <- df %>%
mutate(
avg = x - mean(x),
a = pmap(.l = list(x, y, z), .f = function(x, y, z){ c(sum(x), sum(y), sum(z)) })
)
# Pass the whole of `df` to `.l` and add `...` in an explicit function to deal with any unused columns.
# variable names are used twice.
# `df` will have to be passes explicitly if not using pipes (eg, `mutate(.data = df, a = pmap(.l = df, ...`).
# This is probably inefficient for large datasets.
df_dots <- df %>%
mutate(
avg = x - mean(x),
a = pmap(.l = ., .f = function(x, y, z, ...){ c(sum(x), sum(y), sum(z)) })
)
# Use `pryr::f` (as discussed in https://stackoverflow.com/a/51123520/4269699).
# Variable names are used twice.
# Potentially unexpected behaviour.
# Not obvious to the casual reader why the extra `pryr::f` is needed and what it's doing
df_pryrf <- df %>%
mutate(
avg = x - mean(x),
a = pmap(.l = list(x,y,z), .f = pryr::f({c(sum(x), sum(y), sum(z))} ))
)
# Use `rowwise()` similar to this: https://stackoverflow.com/a/47734073/4269699
# Variable names are used once.
# It will mess up any vectorised functions used elsewhere in mutate, hence the two `mutate()`s
df_rowwise <- df %>%
mutate( avg = x - mean(x) ) %>%
rowwise() %>%
mutate( a = list( {c(sum(x), sum(y), sum(z))} ) ) %>%
ungroup()
# Use Romain Francois' neat {rap} package.
# Variable names used once.
# Like `rowwise()` it will mess up any vectorised functions so it needs two `mutate()`s for this particular problem
#
library('rap') #devtools::install_github("romainfrancois/rap")
df_rap <- df %>%
mutate( avg = x - mean(x) ) %>%
rap( a = ~ c(sum(x), sum(y), sum(z)) )
# Another solution discussed here https://stackoverflow.com/a/51123520/4269699 doesn't seem to work inside `mutate()`, but maybe could be tweaked?
# Like the `pryr::f` solution, it's not immediately obvious what the purpose of the `with(list(...` bit is.
df_with <- df %>%
mutate(
avg = x-mean(x),
a = pmap(.l = list(x,y,z), .f = ~with(list(...), { c(sum(x), sum(y), sum(z))} ))
)
据我所知,这些是选项,不包括位置匹配。
理想情况下,可能会出现以下情况,其中函数知道从传递给s参数的对象qmap
中查找(按行)变量x
,y
和。z
mutate
.data
df_new <- df %>%
mutate(
avg = x-mean(x),
a = qmap( ~c(sum(x), sum(y), sum(z)) )
)
但我不知道该怎么做,所以这只是部分答案。
相关问题: