In R, how to define a function with undefined arguments of the same nature

Asked

Viewed 399 times

3

Dear friends, I am defining one function from another. However, I want to define my new function with several arguments of the same nature. For example

My basic function is well-defined

funcaobase(data, argumento1)

But my new function I want you to do this several times in a determined way in the argument. That is, at the time of defining, something like this

NovaFuncao(data, argumento1, argumento2, argumento3, ...)
{

  data<- funcaobase(data, argumento1)
  data<- funcaobase(data, argumento2)     
  data<- funcaobase(data, argumento3)
  ...

  return(data)
 }  

But I’d like a function in order for this to work

 NovaFuncao(data, argumento1, argumento2, argumento3, argumento4 , argumento5)

I don’t know how to give this procedure.

PS: Actually I want to modify this question I asked before. so that I can modify several levels at the same time - remaining in the same variable- that is, something like Function(dat, variablefixed, levls1, newLevls2 , levls2, newLevls2 , levls3, newLevls3, ...) In R, create a function to change some levels of a variable

  • Notice that in your NovaFuncao you give, in each line, a new value to data, so that you replace the value to each new row and therefore, your return(data) will only return the last value associated with data. That’s exactly what you intend?

  • I give a new value, but I would not like this feat to be lost.

  • If you want it to return all the values, just create a list that stores these values and return the list to the end. If you can give us a reproducible example, it is much easier to help you. The solution may depend, for example, on your data structure (data is a data.frame? an array? a list? ) and what its function does.

  • There is no way to use the three points (...) to avoid repeating the arguments?

  • Come on. Actually I want to modify this question that I asked before. so that I can modify several levels at the same time, the u is, something like Function(dat, variable, levls1, newLevls2 , levls2, newLevls2) http://answall.com/questions/48767/em-r-crea-uma-fun%C3%A7%C3%A3o-to-change-some-levels-of-a-variable

1 answer

4


First by answering your specific problem, based on your comment.

The example function you put up handles "non-standard" Evaluation, which makes it harder to program with functional (such as the lapply). Thus, I will create another equivalent function to illustrate your case.

The function below takes an array of texts and replaces certain words (or regular Expressions) with others:

mgsub <- function(replacement, pattern, x){
  aux <- data.frame(replacement, pattern)
  for(i in 1:nrow(aux)) x <- gsub(aux[i,1], aux[i,2], x)
  x
}

In the data example iris, let’s exchange the species "setosa" and "virginica" for "new":

iris$Species <- mgsub(c("setosa", "virginica"), "novo", iris$Species)

Okay, we have a function that does this for one vector at a time. Now we just need a function that does this for multiple vectors at the same time. We will therefore create a new function with Vectorize().

NovaFuncao <- function(dados, variaveis, levels, novosLevels){
  dados[variaveis] <- Vectorize(mgsub, SIMPLIFY = FALSE)(levels, novosLevels, dados[variaveis])
  dados
}

Now our function accepts a data.frame, an array with the name of the variables that will be replaced, a list with the old levels and a list with the new levels. Creating a test database:

df <- data.frame(fator1 = c("a", "b", "c"),
                 fator2 = c("f", "g", "h"),
                 fator3 = c("i", "j", "k"))
df
  fator1 fator2 fator3
1      a      f      i
2      b      g      j
3      c      h      k

NovaFuncao(df, 
           variaveis = c("fator1", "fator2"), 
           levels = list(c("a", "b"), 
                         c("f")),
           novosLevels = list(c("novo1", "novo2"),
                              c("novo3"))
           )
 fator1 fator2 fator3
1  novo1  novo3      i
2  novo2      g      j
3      c      h      k

Good, keeping down the previous generic response:


Suppose this is your basic function:

funcaobase <- function(data, argumento1){
  paste(data, argumento1)
}

Testing the function:

data <- "teste"
funcaobase(data, 1)
[1] "teste 1"

What you want is to vector it on argumento1 (the function paste is already vectored, so you wouldn’t need to do this, but just for illustration let’s assume that it wasn’t).

NovaFuncao <- Vectorize(funcaobase, vectorize.args = "argumento1", SIMPLIFY = FALSE)

Now you can use several arguments instead of one:

argumentos <- 1:5
NovaFuncao(data, argumentos)
[[1]]
[1] "teste 1"

[[2]]
[1] "teste 2"

[[3]]
[1] "teste 3"

[[4]]
[1] "teste 4"

[[5]]
[1] "teste 5"

In more detail, Vectorize uses the lapply or mapply. For example, you can do the same thing with a lapply in arguments keeping data fixed:

lapply(argumentos, funcaobase, data=data)
[[1]]
[1] "teste 1"

[[2]]
[1] "teste 2"

[[3]]
[1] "teste 3"

[[4]]
[1] "teste 4"

[[5]]
[1] "teste 5"

So, you can turn this command into a new function:

NovaFuncao <- function(data, argumentos){
  lapply(argumentos, funcaobase, data=data)
}

NovaFuncao(data, argumentos)
[[1]]
[1] "teste 1"

[[2]]
[1] "teste 2"

[[3]]
[1] "teste 3"

[[4]]
[1] "teste 4"

[[5]]
[1] "teste 5"

This is the basic logic. You can do this too with a for loop or using other family functions apply depending on the case.

  • In my case, my basic function depends on two variables. Actually my base function I called join, and it works like this: join(dat, variable, levls, newLevls). Where dat is my database, variable is a column, levels are some levels of the column(variable) that I want to modify and newLevls are the new levels. That is, I want something like this: Novafuncao(dat, variavel, levls1, novosLevls2, levls2, novosLevls2, ... ). I could put it all at once. Only I want to do it by groups.

  • That is, I want something like: Change this group of levels by this group. This other group of levels by this other group.. and so on and so forth

  • Or is there already some function ready for this?

  • @Vasco yes you can do with these same functions that I passed, now I’m on mobile, soon put an example

  • @Vasco put a specific example for his case.

  • Oops, your answer was great and will be very helpful. I would like to be pertinent with my initial question. I want to work with only one variable. For example, suppose I have a variable with leveles: "a", "b", "c", "d", "e", "f". I want something like this, Novafuncao(date, variable, c("a", "b", "e"), "novo1", c("c","d"), "novo2") so that my new levels are "novo1", "novo2", "f". Actually I’m not interested in the levels but in the relative frequencies. So I want to specify several groups to be changed in a very determined way.

  • I could do this using the base function twice. But I want to avoid this because I find it more practical

  • To stay in the same variable, I tried this: Novafuncao(df, variables = c("factor1", "factor1"),....) But gave error!

  • I could do this by doing one, but I always avoid avoiding.

  • @Vasco, I think I understand what you want to do. Actually it’s much simpler so you can use only the mgsub by separating with |. Example fator <- c("a" , "b" , "c" , "d" , "e" , "f") and mgsub(c("a|b|e", "c|d"), c("novo1", "novo2"), fator)

  • 1

    It’s simple, however your option to do the same thing with several variables is great. I liked

Show 6 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.