问题
I have a function with mixed data types. It takes a data frame and string variable as the input parameter.
library(dplyr)
myfunc <- function (dat=NULL,species=NULL,sepal_thres=NULL) {
dat %>%
filter(Species==species & Sepal.Length <= sepal_thres)
}
myfunc(dat=iris,species="virginica",sepal_thres=5)
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1 4.9 2.5 4.5 1.7 virginica
But I want to apply it with list of vectors
species_vecs <- c("virginica","setosa")
sepal_thres_vecs <- c(5, 6)
purrr::pmap(list(dat=iris, species=species_vecs, sepal_thres=sepal_thres_vecs), myfunc)
I got this error:
Error: Element 2 has length 2, not 1 or 5.
What's the right way to do it?
Not that the species
and sepal_tres
parameters are taken from this combination:
> expand.grid(species_vecs,sepal_thres_vecs) %>% rename(species=Var1, sepal_thres=Var2)
species sepal_thres
1 virginica 5
2 setosa 5
3 virginica 6
4 setosa 6
but dat
as parameter is fixed.
回答1:
pmap
will use recycling if you have a length-1 element as part of your bigger list. In this case, you can pass iris
as a list element within the full list to use it for each species-sepal combination.
Note that pmap
goes through list elements with multiple values in the order they appear. If you want every combination of the species and sepal vectors in pmap
you would need to create and give the full vectors as list elements (i.e., you would have to do the crossing yourself).
purrr::pmap(list(dat = list(iris), species = rep(species_vecs, 2),
sepal_thres = rep(sepal_thres_vecs, each = 2) ), myfunc)
[[1]]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 4.9 2.5 4.5 1.7 virginica
[[2]]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
5 4.6 3.4 1.4 0.3 setosa
6 5.0 3.4 1.5 0.2 setosa
...
回答2:
You can use this solution :
expand.grid(species_vecs,sepal_thres_vecs) %>%
rename(species=Var1, sepal_thres=Var2) %>%
as.tibble() %>%
mutate(sum = map2(as.character(species), sepal_thres,myfunc,dat = iris)) %>%
unnest(sum)
回答3:
You could use Vectorize
input <- expand.grid(species_vecs,sepal_thres_vecs,stringsAsFactors = F) %>% rename(species=Var1, sepal_thres=Var2)
# species sepal_thres
# 1 virginica 5
# 2 setosa 5
# 3 virginica 6
# 4 setosa 6
output <- Vectorize(myfunc,c("species","sepal_thres"),SIMPLIFY=F)(dat=iris,species=input[[1]],sepal_thres=input[[2]])
output[[1]]
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 4.9 2.5 4.5 1.7 virginica
output[[3]]
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 5.8 2.7 5.1 1.9 virginica
# 2 4.9 2.5 4.5 1.7 virginica
# 3 5.7 2.5 5.0 2.0 virginica
# 4 5.8 2.8 5.1 2.4 virginica
# 5 6.0 2.2 5.0 1.5 virginica
# 6 5.6 2.8 4.9 2.0 virginica
# 7 6.0 3.0 4.8 1.8 virginica
# 8 5.8 2.7 5.1 1.9 virginica
# 9 5.9 3.0 5.1 1.8 virginica
来源:https://stackoverflow.com/questions/46902461/how-to-pass-a-dataframe-and-uneven-vectors-as-parameters-in-purrr-map