Dynamic arguments to expand.grid
expand.grid
can take a list
as its input, so what about replicate
?
expand.grid(replicate(3, v, simplify=FALSE))
For fun, as a function (though I know you would know how to do this):
new.expand.grid <- function(input, reps) {
expand.grid(replicate(reps, input, simplify = FALSE))
}
new.expand.grid(c(1, 2), 4)
# Var1 Var2 Var3 Var4
# 1 1 1 1 1
# 2 2 1 1 1
# 3 1 2 1 1
# 4 2 2 1 1
# 5 1 1 2 1
# 6 2 1 2 1
# 7 1 2 2 1
# 8 2 2 2 1
# 9 1 1 1 2
# 10 2 1 1 2
# 11 1 2 1 2
# 12 2 2 1 2
# 13 1 1 2 2
# 14 2 1 2 2
# 15 1 2 2 2
# 16 2 2 2 2
R- expand.grid given a data.frame of parameter names and sequence definitions
Going off CPak's answer, you could use
my_table <- expand.grid(apply(dfParameterValues, 1, function(x) seq(as.numeric(x['seqFrom']), as.numeric(x['seqTo']), as.numeric(x['seqBy']))))
names(my_table) <- c("ParameterA", "ParameterB", "ParameterC")
my_table <- my_table[order(my_table$ParameterA, my_table$ParameterB), ]
Expand grid with unknown dimension in R
expand.grids <- function(x,d) {
expand.grid(replicate(d, x, simplify=FALSE))
}
expand.grids(1:2,4)
Var1 Var2 Var3 Var4
1 1 1 1 1
2 2 1 1 1
3 1 2 1 1
4 2 2 1 1
5 1 1 2 1
6 2 1 2 1
7 1 2 2 1
8 2 2 2 1
9 1 1 1 2
10 2 1 1 2
11 1 2 1 2
12 2 2 1 2
13 1 1 2 2
14 2 1 2 2
15 1 2 2 2
16 2 2 2 2
Expand.grid with unknown number of columns
We can split the 3rd column by the 'LDGroup' and apply the expand.grid
out <- expand.grid(split(df$ComboNum, df$LDGroup))
names(out) <- paste0("Var", names(out))
Expand Grid With Unknown Number of Vectors - R
Usually the best way to do the same operation on multiple objects is to put them in a list. Once you've got the data arranged in this way, do.call
can be used, so you might end up with something like:
dfs <- list(df1, df2, df3, df4, df5)
matrix <- do.call(expand.grid, dfs[1:n])
In the specific case of expand.grid
, the functionality is built in, so that you can just do
matrix <- expand.grid(dfs[1:n])
Note that if df1...
really are data.frames, your code and this code produce a warning and possibly unexpected results. To avoid the warning df1...
should be vectors.
How to provide dynamic number of arguments to a function inside a function in R?
If the change the apply
to do.call
, it would work as expected. Note that apply
with MARGIN = 2
, loop over the columns of 'df' individually, whereas the 'f1' needs the values of all those available columns (or else use the default values) to calculate the ((a + b) * c
)
f2 <- function(...){
arglist = list(...)
df = expand.grid(arglist)
do.call(f1, df)
}
and the f1
f1 <- function(a=1,b=1,c=2){
(a+b)*c
}
-testing
> f2(a = 10)
[1] 22
> f2(c = 10)
[1] 20
> f2(a = 5, c= c(5, 10))
[1] 30 60
using purrr with expand.grid to loop over formulas for a t.test while conditioning on another variable
Your 1st code worked because formula
& cond
were considered lists by map2_df
. However it wasn't the case when you put them in the pipe
that created a data frame. You cannot do .x$frm
or .x$Var2
.
To make it work, you can use pmap_df
to loop through each row of the data frame created inside the pipe
and refer to the order of the columns by using ..1, ..2, ..3
and so on
library(tidyverse)
library(broom)
df <- data.frame(y = rnorm(100), x1 = sample(0:1, 100, replace = TRUE),
x2 = sample(0:1, 100, replace = TRUE),
x3 = sample(0:1, 100, replace = TRUE),
x4 = sample(0:1, 100, replace = TRUE),
z = sample(0:1, 100, replace = TRUE))
ivs <- c("x1", "x2", "x3", "x4")
med <- c(0, 1)
models <- expand.grid(ivs, med) %>%
mutate(frm = paste0("y ~ ", Var1))
formula <- models$frm
cond <- models$Var2
models <- map2_df(formula, cond, ~ tidy(t.test(as.formula(.x), data = df[df$z == .y, ])))
# using pmap to loop through the columns of the data frame (essentially list of columns)
models2 <- expand.grid(ivs, med) %>%
mutate(frm = paste0("y ~ ", Var1)) %>%
pmap_df(., ~ tidy(t.test(as.formula(..3), data = df[df$z == ..2, ])))
models2
#> estimate estimate1 estimate2 statistic p.value parameter
#> 1 0.2039970 -0.002158780 -0.20615579 0.6372003 0.52724597 44.68250
#> 2 -0.4488714 -0.341650359 0.10722106 -1.4646944 0.15052718 41.56782
#> 3 -0.3016148 -0.246980034 0.05463477 -0.9189260 0.36427350 35.86492
#> 4 0.2601315 -0.004184604 -0.26431615 0.8668975 0.39031605 47.94586
#> 5 -0.2303647 -0.099116913 0.13124775 -0.8420942 0.40422649 44.61732
#> 6 0.5992558 0.385767243 -0.21348854 2.0517453 0.04957898 28.21589
#> 7 0.5027880 0.243581778 -0.25920622 1.9502349 0.05803462 40.84076
#> 8 -0.2735021 -0.101687239 0.17181481 -0.9498541 0.34888013 34.04935
#> conf.low conf.high method alternative
#> 1 -0.440936247 0.8489303 Welch Two Sample t-test two.sided
#> 2 -1.067524893 0.1697821 Welch Two Sample t-test two.sided
#> 3 -0.967373762 0.3641441 Welch Two Sample t-test two.sided
#> 4 -0.343220972 0.8634841 Welch Two Sample t-test two.sided
#> 5 -0.781476516 0.3207472 Welch Two Sample t-test two.sided
#> 6 0.001181137 1.1973304 Welch Two Sample t-test two.sided
#> 7 -0.017929386 1.0235054 Welch Two Sample t-test two.sided
#> 8 -0.858637554 0.3116335 Welch Two Sample t-test two.sided
identical(models, models2)
#> [1] TRUE
Created on 2018-03-25 by the reprex package (v0.2.0).
pasing multiple variable arguments to a function with the apply family
I made a little progress in undertanding mapply so I believe I can answer my own question
wavelet<-c("d2","s2")
n.level<-c(1,2)
schirnkfun <- c("soft", "hard", "mid")
threshfun<-c("universal", "adaptive", "minimax")
threshscale<-c(0.25,1.25)
x<-c(1,2,3,4,5,7,6,7,8,9,8,7,6,4,5,3,2,2,3,4,5,6,6,7,7,7,5,6,7,7,8,8,9,0,9,0,8,7,5,4,3,3,4,4,4,4,3,2,2,1,2,3,4,5,6,5,7,8,8,9,9,0,2,3,4,2,3,5,5,2,4,6,7)
w1<- expand.grid(wavelet=wavelet,n.level=n.level,schirnkfun= schirnkfun,threshfun= threshfun,threshscale= threshscale, stringsAsFactors=FALSE)
result<-mapply(function(m,k,p,u,l,x) (wavShrink(x, wavelet= m,n.level=k,shrink.fun= p,thresh.fun=u, threshold=NULL,thresh.scale= l, xform="modwt", noise.variance=-1, reflect=TRUE)), w1$wavelet, w1$n.level , w1$schirnkfun, w1$ threshfun, w1$threshscale ,MoreArgs=list(x=x))
colnames(result)=c(rownames(w1))
The number of colums is equal to the number of rows of w1, every row from expand,grid is evaluated by the function.
Replicate number of arguments in function call?
do.call()
is the way to go as per @nograpes. As the error implies rep()
has no method for the symbol
class.
But what if you really want the n_args(ids,5,expand.grid)
syntax? I thought I'd try to come up with something.
Alternative solution?
Using parse()
-type functions I came up with:
n_parse <- function(var,n,fun) {
args_v <- rep(deparse(var),n)
args_sep <- paste0(args_v,collapse=",")
fxn_name <- deparse(fun)
expr <- parse(text=paste0(fxn_name,"(",args_sep,")",collpase=""))
out <- eval.parent(expr)
out
}
Which gives the something close to the desired syntax:
result <- n_parse( quote(var), 5, quote(expand.grid) )
and a version with string inputs:
n_parse_string <- function(var,n,fun) {
args_v <- rep(var,n)
args_sep <- paste0(args_v,collapse=",")
expr <- parse(text=paste0(fun,"(",args_sep,")",collpase=""))
out <- eval.parent(expr)
out
}
which is used:
results <- n_parse_string( "ids", 5, "expand.grid")
to give expected output. At the least it's a little practice in non-standard evaluation.
Related Topics
Error with Ggplot2 Mapping Variable to Y and Using Stat="Bin"
Ggplot Graphing of Proportions of Observations Within Categories
How to Correctly Interpret Ggplot's Stat_Density2D
How to Create Datatable with Complex Header in R Shiny
Visualise Distances Between Texts
How to Split a Data Frame by Rows, and Then Process the Blocks
Arrange Plots in a Layout Which Cannot Be Achieved by 'Par(Mfrow ='
Using Grid and Ggplot2 to Create Join Plots Using R
Difference Between Read.Csv() and Read.Csv2() in R
Remove Parenthesis from a Character String
Extract Non Null Elements from a List in R
Geom_Boxplot() from Ggplot2:Forcing an Empty Level to Appear
R Dplyr Join by Range or Virtual Column
Sum Nlayers of a Rasterstack in R
Generate Observers for Dynamic Number of Inputs
Dodging Points and Error Bars with Ggplot
R 3.4.1 "Single Candle" Personal Library Path Error: Unable to Create 'Na'