Dynamic Arguments to Expand.Grid

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



Leave a reply



Submit