"R" Warning message: In mapply longer argument not a multiple of length of shorter

Viewed 260

I am trying to make a simple function to reverse code multiple columns in my R dataframe. I am using lapply and mapply in the function, which seems to give me the expected outcome, except for the warning message

Warning message:
In mapply("-", max_value, data[, rev]) :
  longer argument not a multiple of length of shorter

To illustrate, here is some sample data

{
A = c(3, 3, 3, 3, 3, 3, 3, 3, 3, 3)
B = c(9, 2, 3, 2, 4, 0, 2, 7, 2, 8)
C = c(2, 4, 1, 0, 2, 1, 3, 0, 7, 8)

df1 = data.frame(A, B, C)
print(df1)
}
   A B C
1  3 9 2
2  3 2 4
3  3 3 1
4  3 2 0
5  3 4 2
6  3 0 1
7  3 2 3
8  3 7 0
9  3 2 7
10 3 8 8

The function to reverse-code is below:

## columns to reverse-code
revcode_cols = c("A", "B")

## function to reverse code variables
reverseCode <- function(data, rev){
  
  # get maximum value per column 
  max_value = lapply(data, max)
  
  # subtract values in designated cols from max value plus 1
  data[, rev] = mapply("-", max_value, data[, rev]) + 1
  
  return(data)
  
}

reverseCode(df1, revcode_cols)

   A  B C
1  1  1 2
2  1  8 4
3  1  7 1
4  1  8 0
5  1  6 2
6  1 10 1
7  1  8 3
8  1  3 0
9  1  8 7
10 1  2 8

and it gives the right output, but for the warning message. Just wondering which part of my script I need to fix to get rid of the warning message.

2 Answers

The unit for a data.frame is a column and for a vector is a single element. In the mapply/Map, we are passing two input, but in the OP's code, the max is calculated on the whole dataset creating a the 'max_value' as a list of 3 elements, which the data[, rev] is of length 2. We just need to subset the data for calculating the max

reverseCode <- function(data, rev){
  
  # get maximum value per column 
  max_value = lapply(data[rev], max)
  
  # subtract values in designated cols from max value plus 1
  data[, rev] = mapply("-", max_value, data[, rev]) + 1
  
  return(data)
  
}

-testing

reverseCode(df1, revcode_cols)
   A  B C
1  1  1 2
2  1  8 4
3  1  7 1
4  1  8 0
5  1  6 2
6  1 10 1
7  1  8 3
8  1  3 0
9  1  8 7
10 1  2 8

Instead of using two apply loops you can do this in one lapply.

reverseCode <- function(data, rev){
  data[rev] <- lapply(data[rev], function(x) max(x) - x + 1)
  data
}

reverseCode(df1, c("A", "B"))

#   A  B C
#1  1  1 2
#2  1  8 4
#3  1  7 1
#4  1  8 0
#5  1  6 2
#6  1 10 1
#7  1  8 3
#8  1  3 0
#9  1  8 7
#10 1  2 8
Related