R has lexical scope; a variable that is not assigned in a function is resolved against its static environment. In your case, f1 sees the value of c in your global environment, which is 2. Within f2, c == 3 because it is passed as an argument which masks the global c, but when f1 is called, it still sees c==2 from its enclosing environment. You expected dynamic scoping, where c would take the value of its runtime environment (i.e., within f2). You can set c <- 3 outside the functions, before f2, or you can do this to copy the local value passed as 'c' in f2 to the global environment:
f2 = function(a,b,c){
c <<- c # local argument c copied to global c
f1(a,b)
}
more discussion of lexical scope in R: https://darrenjw.wordpress.com/2011/11/23/lexical-scope-and-function-closures-in-r/
Answer from chaslewis on Stack OverflowYou are right that you can't use "x4":"x4", as this isn't valid use of the : operator in this context. To get this to work in a tidyverse-style, your variables variable needs to be selectively unquoted inside select. Fortunately, the tidyverse has the curly-curly notation {{variables}} for handling exactly this situation:
NMISSfunc <- function (dataFrame, variables) {
dataFrame %>%
select({{variables}}) %>%
apply(1, function(x) sum(is.na(x)))
}
Now we can use x1:x4 (without quotes) and the function works as expected:
NMISSfunc(data, x1:x4)
#> [1] 1 1 0 0
Created on 2022-12-13 with reprex v2.0.2
Why not simply,
data %>%
mutate(NMISS = rowSums(is.na(select(., x1:x4))))
x1 x2 x3 x4 NMISS
1 NA 7 9 3 1
2 1 1 NA 4 1
3 5 1 4 1 0
4 1 5 9 2 0