Define $ Right Parameter with a Variable in R

define $ right parameter with a variable in R

Use [[ instead of $. x$y is short hand for x[["y"]].

my_helper <- function (my_param) {
levels(diamond[[my_param]])
}
my_helper("cut")

R: specifying variable name in function parameter for a function of general (universal) use

Let's investigate (see the comments I added) you original function and call, assuming you mean to pass the names of you columns of interest to the function:

myfun <- function (dataframe, varA, varB) {
#on this next line, you use A and B. But this should be what is
#passed in as varA and varB, no?
daf2 <- data.frame (A = dataframe$A*dataframe$B, B=dataframe$C*dataframe$D)
#so, as a correction, we need:
colnames(daf2)<-c(varA, varB)
#the first argument to lm is a formula. If you use it like this,
#it refers to columns with _names_ varA and varB, not as names
#the _contents_ of varA and varB!!
anv1 <- lm(varA ~ varB, daf2)
#so, what we really want, is to build a formula with the contents
#of varA and varB: we have to this by building up a character string:
frm<-paste(varA, varB, sep="~")
anv1 <- lm(formula(frm), daf2)
print(anova(anv1))
}
#here, you pass A and B, because you are used to being able to do that in a formula
#(like in lm). But in a formula, there is a great deal of work done to make that
#happen, that doesn't work for most of the rest of R, so you need to pass the names
#again as character strings:
myfun (dataframe = dataf, varA = A, varB = B)
#becomes:
myfun (dataframe = dataf, varA = "A", varB = "B")

Note: in the above, I left the original code in place, so you may have to remove some of that to avoid the errors you were originally getting. The essence of your problems is that you should always pass column names as characters, and use them as such. This is one of the places where the syntactic sugar of formulas in R gets people into bad habits and misunderstandings...

Now, as for an alternative: the only place the variable names are actually used, are in the formula. As such, you can simplify matters further if you don't mind some slight cosmetic differences in the results that you can clean up later: there is no need for you to pass along the column names!!

myfun <- function (dataframe) {
daf2 <- data.frame (A = dataframe$A*dataframe$B, B=dataframe$C*dataframe$D)
#now we know that columns A and B simply exist in data.frame daf2!!
anv1 <- lm(A ~ B, daf2)
print(anova(anv1))
}

As a final piece of advice: I would refrain from calling print on your last statement: if you don't, but use this method directly from the R command line, it will perform the print for you anyway. As an added advantage, you can perform further work with the object returned from your method.

Cleaned Function with trial:

dataf <- data.frame (A= 1:10, B= 21:30, C= 51:60, D = 71:80)
myfun <- function (dataframe, varA, varB) {
frm<-paste(varA, varB, sep="~")
anv1 <- lm(formula(frm), dataframe)
anova(anv1)
}
myfun (dataframe = dataf, varA = "A", varB = "B")
myfun (dataframe = dataf, varA = "A", varB = "D")
myfun (dataframe = dataf, varA = "B", varB = "C")

R, pass-by-value inside a function

You can create a function which uses a locked binding and creates a function to complete your purpose. The former value of a will be used for w which will be stored in the environment of the function and will not be replaced by further values changes of a.

a <- 1
j <- new.env() # create a new environment
create.func <- function () {
j$w <<- a
function (x) {
x+ j$w
}
}
f <- create.func()
a <- 2
f(2)
[1] 3 # if w was changed this should be 4

Credits to Andrew Taylor (see comments)

EDIT: BE CAREFUL: f will change if you call create.func, even if you do not store it into f. To avoid this, you could write this code (it clearly depends on what you want).

a <- 1
create.func <- function (x) {
j <- new.env()
j$w <- a
function (x) {
x + j$w
}
}
f <- create.func()
f(1)
[1] 2
a <- 2
q <- create.func()
q(1)
[1] 3
f(1)
[1] 2

EDIT 2: Lazy evaluation doesn't apply here because a is evaluated by being set to j$w. If you had used it as an argument say:

function(a)
function(x)
#use a here

you would have to use force before defining the second function, because then it wouldn't be evaluated.

EDIT 3: I removed the foo <- etc. The function will return as soon as it is declared, since you want it to be similar to the code factories defined in your link.

EDIT by OPJust to add to the accepted answer that in spirit of
Function Factory in R
the code below works:

funs.gen <- function(n) {
force(n)
function(x) {
x + n
}
}

funs = list()
for (i in seq(length(names))) {
n = names[i]
funs[[n]] = funs.gen(i)
}

How to user define filtering parameters in R?

Either define filter variables in your DF and (re-)use those variables in filter.

DF %>%
mutate(
filterA = between(EMTAK, 200, 232) |
between(EMTAK, 400, 450),
filterB = between(EMTAK, 250, 260) |
EMTAK == 500)
)

New_DF <- DF %>%
filter(Filter_A |
Filter_B,
SECTOR == "Metal" |
SECTOR == "Plastic")

Or define functions for your filters. Note that when calling the functions you don't need the == because the functions already return a logical vector.

filterA <- function(x){
between(x, 200, 232) |
between(x, 400, 450)
}

filterB <- function(x){
between(x, 250, 260) |
x == 500)
}

New_DF <- DF %>%
filter(filterA(EMTAK) |
filterB(EMTAK),
SECTOR == "Metal" |
SECTOR == "Plastic")


Related Topics



Leave a reply



Submit