Miki G.
Miki G.

Reputation: 29

Specifying R to take one argument at a time when passing multiple arguments using '...'

I am a novice in R required by my superior to do things a certain way. I am interested in determining values of descriptive statistics setup count and heavy-dominance setup count. Setup count basically counts the number of setups found within a location, while heavy-dominance setup count counts the number of setups that has dominance values of x population ≥ 50% within the said location. This is how I would normally calculate said statistics:

##Normal Approach
#Sample Data 1
v <- c(53, 2, 97) #let vector "v" represent Location 1
w <- c(7, 16, 31, 44, 16) #let vector "w" represent Location 2

#Setup Count
sc_v <- length(v)
sc_w <- length(w)
sc <- c(sc_v, sc_w)
sc

#Heavy-Dominance Setup Count
hd_v <- length(which(v >= 50))
hd_w <- length(which(w >= 50))
hd <- c(hd_v, hd_w)
hd

I am tasked with developing a function that can both determine said statistical values from raw data and concatenate the outputs into a single vector. Here are the working functions I developed:

#Setup Count (2 vectors at a time only)
setup.count <- function(x, y){
  a <- length(x)
  b <- length(y)
  d <- c(a, b)
  d
}

#Heavy-Dominance Setup Count (2 vectors at a time only)
heavy.dominance <- function(x, y){
  a <- length(which(x >= 50))
  b <- length(which(y >= 50))
  d <- c(a, b)
  d
}

y <- setup.count(v, w)
y
z <- heavy.dominance(v, w)
z

Suppose there are more than two locations:

#Sample Data 2
v <- c(53, 2, 97)
w <- c(7, 16, 31, 44, 16)
x <- c(45, 22, 96, 74) #let vector "x" represent the additional Location 3

How can I specify R to take one argument at a time when passing multiple arguments using '...'? Here are the failed attempts to revise the abovementioned functions, to give an idea:

##Attempt 1
#Setup Count (incorrect v1)
setup.count <- function(x, ...){
  data <- list(...)
  a <- length(x)
  b <- length(data) #will return the number of locations other than x, not the separate number of setups within each of these locations
  d <- c(a, b)
  d
}

#Heavy-Dominance Setup Count (incorrect v1)
heavy.dominance <- function(x, ...){
  data <- list(...)
  a <- length(which(x >= 50))
  b <- length(which(data >= 50)) #will return the error "'list' object cannot be coerced to type 'double'"
  d <- c(a, b)
  d
}

y <- setup.count(v, w, x)
y
z <- heavy.dominance(v, w, x)
z

##Attempt 2
#Setup Count (incorrect v2)
setup.count <- function(x, ...){
  data <- list(...)
  a <- length(x)
  b <- length(unlist(data)) #will return the total number of setups in all locations other than x, not as separate values
  d <- c(a, b)
  d
}

#Heavy-Dominance Setup Count (incorrect v2)
heavy.dominance <- function(x, ...){
  data <- list(...)
  a <- length(which(x >= 50))
  b <- length(which(unlist(data) >= 50)) #will return the total number of setups with dominance ≥ 50% in all locations other than x, not as separate values
  d <- c(a, b)
  d
}

y <- setup.count(v, w, x)
y
z <- heavy.dominance(v, w, x)
z

Upvotes: 1

Views: 193

Answers (1)

jay.sf
jay.sf

Reputation: 72803

You may just list() elements in the ellipsis. Use sapply() to loop over the list elements. Add a type= argument to have one function for both purposes, and a thresh= argument.

setup.fun <- function(..., type=c('count', 'dominance'), thresh=50) {
  x <- list(...)
  type <- match.arg(type)
  if (type == 'count') sapply(x, length)
  else sapply(x, function(x) length(which(x >= thresh)))
}

setup.fun(v, w, x)
# [1] 3 5 4
setup.fun(v, w, x, type='count')
# [1] 3 5 4
setup.fun(v, w, x, type='dominance')
# [1] 2 0 2
setup.fun(v, w, x, type='d')
# [1] 2 0 2
setup.fun(v, w, x, v)
# [1] 3 5 4 3
setup.fun(v)
# [1] 3
setup.fun(v, w, x, type='dominance', thresh=40)
# [1] 2 1 3

Upvotes: 1

Related Questions