I just started programming in R. I'm working at code which execute operations on arrays. It works when I put there a variable but if i wrap it into a function something is wrong. When I try to recall list_matrices[i] i got NULL.
F <- function(x){
list_matrices=c()
for(i in 1:dim(x)[1]){
list_matrices[[i]] <- t(rbind(x[i,1:dim(x)[2],1:dim(x)[3]]))}
}
It has already been pointed out in the comments that the problem is that the function does not return list_matrices so here we will point out that there is some question of whether you really need to do this in the first place. If the reason to create the list is to later iterate over it with some function g, it would be possible to do that directly over 'x' using apply. These two are the same:
# test inputs
x <- array(1:24, 2:4)
g <- function(x) sum(x*x)
# 1
f <- function(x) {
list_matrices <- c()
for(i in 1:dim(x)[1]) {
list_matrices[[i]] <- t(rbind(x[i,1:dim(x)[2],1:dim(x)[3]]))
}
list_matrices
}
L <- f(x)
sapply(L, g)
## [1] 2300 2600
# 2
apply(x, 1, g)
## [1] 2300 2600
Also note that F is used for FALSE in R and could result in subtle errors if used as the name of an object so above we have renamed the function f.
Related
I am trying to use R to create a function that takes two lists as input, and returns common elements, but without using the intersect function. I am still struggling with a few things as I learn R:
lists vs. vectors vs. dataframes
how to keep/store the results from for loops and functions
how to use sapply/mapply/etc.
Here is what I have so far. I thought it worked at first when the only common element was '5', but when I added more common numbers it still only returns '5'.
** Note - I realized after writing this that it is only necessary to run this in one direction (is anything in list_a also in list_b) but now I'm curious how to get this version running from a programming perspective.
a <- list(1,2,3,4,5)
b <- list(3,4,5,6,7,8,9,10,11)
a_match <- numeric()
b_match <- numeric()
ab <- function(list_a, list_b) {
for (i in list_a) {
results <- if(i %in% list_b) {i}
a_in_b <- c(a_match, results)
}
for (i in list_b) {
results <- if(i %in% list_a) {i}
b_in_a <- c(b_match, results)
}
combined <- c(a_in_b, b_in_a)
unique(combined)
}
ab(a, b)
Is there a way to use an 'apply' here? and:
return a vector that is not the same length as the input (limitation of sapply)
can take in multiple inputs that aren't the same length (limitation of mapply)
Your a_match and b_match is outside declared outside the function. I have fixed your example Check below:
a <- list(1,2,3,4,5)
b <- list(3,4,5,6,7,8,9,10,11)
ab <- function(list_a, list_b) {
a_match <- numeric()
b_match <- numeric()
for (i in list_a) {
results <- if(i %in% list_b) {i}
a_match <- c(a_match, results)
}
for (i in list_b) {
results <- if(i %in% list_a) {i}
b_match <- c(b_match, results)
}
combined <- c(a_match,b_match)
unique(combined)
}
ab(a, b)
we could just use the %in% function to get elements that are in a and b => a %in% b is a logical vector we use it to subset the original list.
a %in% b
#> [1] FALSE FALSE TRUE TRUE TRUE
unique(a[a %in% b])
[[1]]
[1] 3
[[2]]
[1] 4
[[3]]
[1] 5
Mind you that most of the operators (functions) in baseR are vectorised thus no need to use the apply family in this one.
unlist(unique(a[a %in% b]))
#> [1] 3 4 5
Consider the following Matlab code to approximate integrals using simulation.
function f
numSim = 1000000;
points = rand(numSim,1);
r3 = mean(feval('func3', points));
points1 = rand(numSim,1);
r8 = mean(feval('func8', points, points1));
disp([r3, r8,]);
end %f
%%%%%%%%%% Nested funcitons %%%%%%%%%%%%
function y = func3(x)
y = exp(exp(x));
end %func3
function z = func8(x,y)
z = exp((x+y).^2);
end %func8
What I've tried in R
f <- function (func3,func8){
numSim <- 1000000
points <- runif(numSim)
r3 <- mean(evaluate(points, func3))
points1 <- runif(numSim)
r8 <- mean(evaluate( points1,func8))
newList<-list(r3,r8)
return(newList)
}
# Nested functions
func3<-function(x) {
func3 <- exp(exp(x))
return(func3)
}
func8 <- function(x,y) {
func8<-exp((x+y)^2)
return(func8)
}
The first problem was a warning message:
In mean.default(evaluate(points,function)) :
argument is not numeric or logical:returning NA
I added r3 <- mean(evaluate(points, func3),na.rm=TRUE)
and when I type r3 the output is [1] NA,
why is it not working correctly?
Additionally,
there was a comment about -Nested functions-, I don't understand how to do that in R.
This appears to work:
f <- function (func3,func8){
numSim <- 1000000
vals <- runif(numSim) ## changed the name: 'points' is a built-in function
r3 <- mean(sapply(vals, func3))
vals2 <- runif(numSim)
## use mapply() to evaluate over multiple parameter vectors
r8 <- mean(mapply(func8, vals, vals2))
newList <- list(r3,r8)
return(newList)
}
I simplified the function definitions.
func3 <- function(x) {
return(exp(exp(x)))
}
func8 <- function(x,y) {
return(exp((x+y)^2))
}
Try it out:
f(func3,func8)
I have no idea if this is correct, but I think it's a correct translation of your MATLAB code. Note that the implementation could be much faster by using vectorization: replace the sapply() and mapply() with mean(func3(vals)) and mean(func8(vals,vals2)) respectively (this only works if the functions to be evaluated are themselves appropriately vectorized, which they are in this case).
I would like to create a bunch of functions with a particular structure in the variable name as a crude workaround for what should be one function with multiple arguments (this I cannot do directly). Let's consider the following analogous example:
for(i in 1:3){
for(j in 1:2){
temp_fun <- function(x){
(x+i)^j
}
assign(paste0("fun", paste0("_plus_", i, "_pow_", j)), temp_fun)
}
}
This loop creates 6 functions that have x as dependent variable only
fun_plus_1_pow_1
fun_plus_1_pow_2
fun_plus_2_pow_1
fun_plus_2_pow_2
fun_plus_3_pow_1
fun_plus_3_pow_2
For instance fun_plus_2_pow_1(2) should return (2+2)^1 = 4, however it returns 25. I know what happens here, the values for i and j get updated while the loop is running and eventually i=3 and j=2are taken resulting in (2+3)^2 = 25.
But how can I make them local?
Here is one option. I also changed that assign stuff (creating a bunch of systematically named objects in the global environment is a clear sign to use a list instead).
funs <- matrix(list(), 3, 2, dimnames = list(paste0("plus", 1:3),
paste0("pow", 1:2)))
for(i in 1:3){
for(j in 1:2){
create_fun <- function(i, j){
#force evaluation so that the values are stored in the closure
force(i); force(j)
function(x) (x+i)^j
}
funs[i, j][[1]] <- create_fun(i, j)
}
}
funs["plus2", "pow1"][[1]](2)
#[1] 4
Why do you need to do this? Would it be sufficient to just define one function fun(x, i, j) and then use partial application:
library(pryr)
fun <- function(x, i, j) (x + i)^j
partial(fun, i = 2, j = 1)(2)
## [1] 4
# an example of passing partial(...) as a function to another function, i.e. to sapply
sapply(1:10, partial(fun, i = 2, j = 1))
## [1] 3 4 5 6 7 8 9 10 11 12
Note that partial(fun, i = i, j = j) for particular values of i and j is a function of x alone.
I'm trying to wrap my head around the R scoping rules, and I'm having trouble understanding the force function's example in the R documentation
f <- function(y) function() y
lf <- vector("list", 5)
for (i in seq_along(lf)) lf[[i]] <- f(i)
lf[[1]]() # returns 5
g <- function(y) { force(y); function() y }
lg <- vector("list", 5)
for (i in seq_along(lg)) lg[[i]] <- g(i)
lg[[1]]() # returns 1
Why does
lf[[1]]()
return 5 instead of 1?
I have a basic understanding of scoping rules from Hadley's advance R but I can't figure out how it applies here
How to handle a variable matrix index and row/column as indices in a single function argument?
m <- matrix(1:9, 3)
fn <- function(m, subsetArg) {
stopifnot(m[subsetArg] == 6)
}
I'd like to be able to use both situations:
a <- matrix(FALSE, 3, 3)
a[2,3] <- TRUE
# yielding
# F F F
# F F T
# F F F
fn(m, subsetArgument = a) # works
and
fn(m, subsetArgument = tuple(2,3)) # <- does not work logically
Note that I would also be after using a range, for example tuple(2, 1:3)
I understand this could be done very explicitly by testing for either 1 or 2 variables given, but I feel there might be an easier way.
Just slurp all the arguments up and pass them into a call to [:
fn <- function(...) {
stopifnot(do.call(`[`, list(...)) == 6)
}
Everything in R is a function, including subsetting :-)
You can subset a matrix using an integer matrix. For example, instead of
m <- matrix(1:9, 3)
fn <- function(m, subsetArg) {
(m[subsetArg])
}
a <- matrix(FALSE, 3, 3)
a[2,3] <- TRUE
fn(m,subsetArg=a)
You could simply write:
n <- matrix(ncol=2, byrow=TRUE, c(2,3))
m[n]
Which would also work in your function, and returns the same result:
fn(m,subsetArg=n)
If you create your index matrix correct you can get the result that you're looking for in the tuple example:
n.tuple <- as.matrix(expand.grid(x=2, y=1:3))
m[n.tuple]
Of course you could write a tuple function which does it for you, which would work as expected:
tuple <- function(x,y) {
as.matrix(expand.grid(x=x, y=y))
}
fn(m, subsetArg = tuple(2,3)) # 8
fn(m, subsetArg = tuple(2,1:3)) # 2 5 8