RyanMe321
RyanMe321

Reputation: 197

R How to set a data frame for a function?

I'm trying my hand at writing a package for R, I was going to do this in excel but I figured learning how to make a basic package would be interesting, and good knowledge to have.

I've gotten the function working, however each variable has to be referenced as a column form the data set individually eg. DATA$D1 etc. I would like to know how to make it cleaner so the function has data has its own an argument, that way the name of the data set only needs to be given once. In the same way say the aov {stats} package works, where the columns are listed and the data frame is set. AOV example (Val, Location are columns of data set starlings):

aov(Val~Location, data=starlings)

My Function:

#' Run PCQ Density Calculation
#' Take four distance measurements and specified area and estimate density.
#' @param A = Specified Area (i.e. 1m^2 or 1 hectare (10,000 m^2))
#' @param D1 = Quarter 1 Distance
#' @param D2 = Quarter 2 Distance
#' @param D3 = Quarter 3 Distance
#' @param D4 = Quarter 4 Distance
#' @return The density esitmation 
#' @export
PCQ <- function(A,D1,D2,D3,D4){
  return(A^2/((D1+D2+D3+D4)/4)^2)
}

My Function in use (D1,D2,D3,D4 are columns of the data set dat):

PCQ(1,dat$D1,dat$D2,dat$D3,dat$D4)

I've tried having the function have a variable "D" what would hold the data sets name, then have the $D1 etc. in the function but that didn't work.

PCQ <- function(D,A,D1,D2,D3,D4){
      return(A^2/((D$D1+D$D2+D$D3+D$D4)/4)^2)
    } 

Sorry for the lack of clarity on the first edit.

Upvotes: 1

Views: 98

Answers (3)

inscaven
inscaven

Reputation: 2584

To pass multiple column names to the function without quoting them we can use advantages of package lazyeval

dat <- as.data.frame(matrix(1:50, ncol = 10, dimnames = list(NULL, paste0("C", 1:10))))
#   C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
# 1  1  6 11 16 21 26 31 36 41  46
# 2  2  7 12 17 22 27 32 37 42  47
# 3  3  8 13 18 23 28 33 38 43  48
# 4  4  9 14 19 24 29 34 39 44  49
# 5  5 10 15 20 25 30 35 40 45  50
PCQ <- function(D, A, ...)
{
  require("lazyeval")
  cols <- lazy_dots(...)
  cols_names <- unlist(lapply(cols, function(x) as.character(x$expr)))

  return( A^2 / (rowSums(D[,cols_names])/4)^2 )
} 

PCQ(dat, 100, C1, C5, C7, C10)
# [1] 16.32486 15.08153 13.97502 12.98596 12.09830

But more beautiful solution may be created with function select from dplyr package.

PCQ2 <- function(D, A, ...)
{
  require("dplyr")

  return( A^2 / (rowSums(select(D, ...))/4)^2 )
}

PCQ2(dat, 100, C1, C5, C7, C10)
# [1] 16.32486 15.08153 13.97502 12.98596 12.09830

Upvotes: 0

lukeA
lukeA

Reputation: 54267

Or try this

dat <- data.frame(P.1st = 1:10)
PCQ <- function(df, var1) {
  col <- deparse(substitute(var1))    
  return(cumsum(df[, col]))
}
PCQ(dat, P.1st)
# [1]  1  3  6 10 15 21 28 36 45 55

Upvotes: 1

Koundy
Koundy

Reputation: 5555

Try this

PCQ <- function(data,A,D1,D2,D3,D4){
  return(A^2/((data[,D1] + data[,D2] + data[,D3] + data[,D4])/4)^2)
  }

This function can be used as

PCQ(data = dat,1,"P.1st","P.2nd","P.3rd","P.4th")

Upvotes: 0

Related Questions