0

I am trying to write a function in R, which contains a function from another package. The code works perfectly outside a function.

I am guessing, it might have got to do something with the package I am using (survey).


A self-contained code example:

#activating the package
library(survey)

#getting the dataset into R
tm <- read.spss("tm.sav", to.data.frame = T, max.value.labels = 5) 

# creating svydesign object (it basically contains the weights to adjust the variables (~persgew: also a column variable contained in the tm-dataset))
tm_w <- svydesign(ids=~0, weights = ~persgew, data = tm)

#getting overview of the welle-variable
#this variable is part of the tm-dataset. it is needed to execute the following steps
table(tm$welle)

# data manipulation as in: taking the v12d_gr-variable as well as the welle-variable and the svydesign-object to create a longitudinal variable which is transformed into a data frame that can be passed to ggplot
t <- svytable(~v12d_gr+welle, tm_w)
tt <- round(prop.table(t,2)*100, digits=0)
v12d <- tt[2,] 
v12d <- as.data.frame(v12d)

this is the code outside the function, working perfectly. since I have to transform quite a few variables in the exact same way, I aim to create a function to save up some time.

The following function is supposed to take a variable that will be transformed as an argument (v12sd2_gr).

#making sure the survey-object is loaded
tm_w <- svydesign(ids=~0, weights = ~persgew, data = data)

#trying to write a function containing the code from above
ltd_zsw <- function(variable1){

  t <- svytable(~variable1+welle, tm_w)
  tt <- round(prop.table(t,2)*100, digits=0)
  var_ltd_zsw <- tt[2,]
  var_ltd_zsw <- as.data.frame(var_ltd_zsw)
  return(var_ltd_zsw)
}

Calling the function:

#as v12d has been altered already, I am trying to transform another variable v12sd2_gr
v12sd2 <- ltd_zsw(v12sd2_gr)

Console output:

Error in model.frame.default(formula = weights ~ variable1 + welle, data = model.frame(design)) : 
  invalid type (closure) for variable 'variable1'
Called from: model.frame.default(formula = weights ~ variable1 + welle, data = model.frame(design))

How do I fix it? And what does it mean to dynamically build a formula and reformulating?

PS: I hope it is the appropriate way to answer to the feedback in the comments.

Update: I think I was able to trace the problem back to the argument I am passing (variable1) and I am guessing it has got something to do with the fact, that I try to call a formula within the function. But when I try to call the svytable with as.formula(svytable(~variable1+welle, tm_w))it still doesn't work. What to do?

xnhZZZ
  • 11
  • 4
  • 1
    Hi and welcome to SO! Your code example is not self contained - it seems to be dependent on the package "survey" (others too?) and some unknown values for `tm` and `v12sd2` . Can you post a self contained example, with toy values? If we could run the code we could help investigate it – Ofek Shilon Feb 24 '22 at 19:16
  • 2
    The issue is that you can't use variables for other variables in formulas. When you have `~variable1+welle` it assumes that both are column names. It doesn't know that one is a variable and one is not. You'll need to dynamically build a formula – MrFlick Feb 24 '22 at 19:56
  • 1
    for dynamic formulas, search for answers on SO using "reformulate",e.g. https://stackoverflow.com/questions/4951442/formula-with-dynamic-number-of-variables/13371468#13371468 – Ben Bolker Feb 24 '22 at 22:41
  • @OfekShilon Hi! Thank your for feedback! I edited the post, I hope I was able to contain all the information you asked for. – xnhZZZ Feb 25 '22 at 14:56
  • @xnhZZZ you got two good answers from guys who were able to see the problem without running the code… did they work for you? – Ofek Shilon Mar 05 '22 at 07:17
  • @OfekShilon no. neither did they work nor did anybody in the comment section see the problem (or identify it for that matter). As I was able to finally solve it properly myself, what is the appropriate way to update or close this question? Update the post or post my own answer in here and mark it as such? Thanks in advance! – xnhZZZ Mar 07 '22 at 16:03
  • @xnhZZZ Feel free to post your answer (in detail) and accept it - it might be of use to others. – Ofek Shilon Mar 08 '22 at 13:18

1 Answers1

0

I have found a solution to the problem.

Here is the tested and working function:

ltd_test <- function (var, x, string1="con", string2="pro") {
    print (table (var))
    x$w12d_gr <- ifelse(as.numeric(var)>2,1,0)
    x$w12d_gr <- factor(x$w12d_gr, levels = c(0,1), labels = c(string1,string2))
    print (table (x$w12d_gr))
    x_w <- svydesign(ids=~0, weights = ~persgew, data = x)
    t <- svytable(~w12d_gr+welle, x_w)
    tt <- round(prop.table(t,2)*100, digits=0)
    w12d <- tt[2,] 
    w12d <- as.data.frame(w12d)
    }

The problem appeared to be caused by the svydesgin()-fun. In its output it produces an object which is then used by the formula for svytable()-fun. Thats why it is imperative to first create the x_w-object with svydesgin() and then use the svytable()-fun to create the t-object. Within the code snippet I posted originally in the question the tm_w-object has been created and stored globally.

Thanks for the help to everyone. I hope this is gonna be of use to someone one day!

xnhZZZ
  • 11
  • 4