Reputation: 91
I am trying to pass 2 arguments for a user-defined function within the FUN argument of an apply function, as in the below example:
mat <- matrix(NA, nrow =10, ncol=3)
mat[,1] <- runif(10, 0, 1)
mat[,2] <- runif(10, 0, 1)
mat[,3] <- runif(10, 0, 1)
roundFn <- function(indata, p){
for (i in ncol(indata)){
if(is.numeric(indata[,i])){
indata[,i] <- round(indata[,i], digits = p)
}
}
}
outdata <- apply(mat, 2, roundFn, indata = mat, p = 3)
But when I run the above code I get an error message that says:
Error in FUN(newX[, i], ...) : unused argument (newX[, i])
Any tips on how to properly use the apply function in this context would be much appreciated.
Upvotes: 0
Views: 57
Reputation: 4456
Your roundFn
function loops through every column of indata
, so applying it to every column with apply
is redundant. You can either (1) apply roundFn
directly to mat
, or (2) redefine roundFn
to act on a column of mat
, and then apply it to every column with apply
.
mat = replicate(3, runif(10)) #a smarter way to create a random matrix
First method:
roundFn <- function(indata, p){
for (i in 1:ncol(indata)){ #here you missed the "1:" before "ncol(indata)"
if(is.numeric(indata[,i])){
indata[,i] <- round(indata[,i], digits = p)
}
}
return(indata) #you forgot to say what your function should return
}
outdata <- roundFn(mat, 3)
Second method:
roundFn <- function(indata.col, p){ #now, it receives a column
if(is.numeric(indata.col)){
return(round(indata.col, digits = p))
}
}
outdata <- apply(mat, 2, roundFn, p = 3)
As @Allan Cameron and @M-- pointed out in the comments, roundFn
is really similar to round
, the only difference is that it only applies to numeric columns. Thus, you can get the same output from:
Using base R:
apply(mat[,apply(mat, 2, is.numeric)], 2, round, digits = 3)
Using dplyr/tidyverse:
library(tidyverse)
mutate(as_tibble(mat), across(where(is.numeric), round, digits = 3))
Upvotes: 3