简体   繁体   中英

Trouble applying function with multiple optional arguments

I would like the function 'count' to count the number of entries in 'data' that meet 'critvalue' by the 'operator' = 1 (<), =2 (=), = 3 (>).

count = function(data,critvalue,operator=2) { 
    if (operator == 1){
        sum(data < critvalue)}
    if (operator == 2){ 
        sum(data == critvalue)}
    if (operator == 3){
        sum(data > critvalue)}}

It works on a vector of values:

count(rep(6,10),critvalue=5,operator=1)

When I apply this function to a matrix to count by row, it doesn't work:

m = rbind(1:10,1:10,1:10)
apply(m, 1, count, critvalue = 6)

But when I define the function 'count' to not take the operator argument, it somehow works

count = function(data,critvalue,operator=2) {
     sum(data == critvalue)}

apply(m, 1, count, critvalue = 6)

Any help in figuring out why this doesn't work in the apply function would be greatly appreciated.

Also, I would definitely be interested in base functions that already count like this. I tried 'sum', but don't know how to use it in apply.

sum(m == 6)  #works

apply(m,1,sum,   #no idea how set the criteria for being equal to 6

I would use switch :

m <- matrix(c(1:10,1:10,1:10),ncol=3)

count <- function(data,critvalue,operator=2) { 
  switch(operator,
         sum(data < critvalue),
         sum(data == critvalue),
         sum(data > critvalue))
}

apply(m, 1, count, critvalue = 6)
#[1] 0 0 0 0 0 3 0 0 0 0

apply(m, 1, count, critvalue = 6, operator = 3)
#[1] 0 0 0 0 0 0 3 3 3 3

Edit: Why your function does not work.

From ?return :

If the end of a function is reached without calling return, the value of the last evaluated expression is returned.

The last expression of your function is if (operator == 3){ sum(data > critvalue)} .

From ?if :

if returns the value of the expression evaluated, or NULL invisibly if none was (which may happen if there is no else).

So, in case operator != 3 your function returns NULL :

apply(m, 1, count, critvalue = 6)
#NULL

You fix that by using return :

count <- function(data,critvalue,operator=2) { 
  if (operator == 1){
    return(sum(data < critvalue))}
  if (operator == 2){ 
    return(sum(data == critvalue))}
  if (operator == 3){
    return(sum(data > critvalue))}}    

apply(m, 1, count, critvalue = 6)
#[1] 0 0 0 0 0 3 0 0 0 0

However, switch is more convenient here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM