rfunctionloopscombn

Error by looping combn - function (multiple Dataframes)


I've have a hard time to get a function within a function for multiple Dataframes.

I have multiple Dataframes: all looks like

A <- data.frame(Date = as.character(c("Jan-22", "Dec-21", "Nov-21", "Oct-21")),
                City1 = seq(1:4),
                City2 = seq(1:8))

But some dataframes have some more Cities (3 to 8). I want to run the following code for all Dataframes:

Dates_A <- A$Date
A$Date <- NULL 
nm1 <- combn(names(A), 2, FUN = paste, collapse = "_")
A[nm1] <- combn(A, 2, FUN = function(x) abs(x[[1]]- x[[2]]))
Casava$A<- Dates_A

which works with my first Dataframe. So I tried to put all my Dataframes to a list

dfList <- list(A, B, C, D, E)

And put the code in a loop:

for (i in 1: length(dfList)) 
                  {
  Dates_i <- dfList[i]$Date
  dfList[i]$Date <- NULL 
  nm1 <- combn(names(dfList[[i]]), 2, FUN = paste, collapse = "_")
  dfList[i][nm1] <- combn(dfList[[i]], 2, FUN = function(x) abs(x[[1]]- x[[2]]))
  dfList[i] <- select(dfList[[i]], contains("_"))
  dfList[i]$Dates <- Dates_i}

but now I get the Error:

Error in x[[1]] - x[[2]] : non-numeric argument to binary operator

May can someone help? im not to familiar with loops.

Edit: sorry I corrected the first code whicht I run on a single Dataframe (3 I only had because I tried it - that will not work I now, 2 is what I want).

My Code than breaks only within the loop at the point

dfList[i][nm1] <- combn(dfList[[i]], 2, FUN = function(x) abs(x[[1]]- x[[2]]))

Solution

  • I would do it slightly differently. I would wrap everything in a function and apply, i.e.

    f1 <- function(df){
      cbind.data.frame(df, 
                       lapply(combn(df[-1], 2, simplify = FALSE), function(i) {
                         nm <- paste0(names(i[1]), '_', names(i[2]));
                         i[nm] <- i[1] - i[2]; 
                         i[3]}))
    }
    
    > f1(A)
         Date City1 City2 City3 City1_City2 City1_City3 City2_City3
    1  Jan-22     1     1     1           0           0           0
    2  Dec-21     2     2     2           0           0           0
    3  Nov-21     3     3     3           0           0           0
    4  Oct-21     4     4     4           0           0           0
    5  Jan-22     1     5     5          -4          -4           0
    6  Dec-21     2     6     6          -4          -4           0
    7  Nov-21     3     7     7          -4          -4           0
    8  Oct-21     4     8     8          -4          -4           0
    9  Jan-22     1     1     9           0          -8          -8
    10 Dec-21     2     2    10           0          -8          -8
    11 Nov-21     3     3    11           0          -8          -8
    12 Oct-21     4     4    12           0          -8          -8
    13 Jan-22     1     5    13          -4         -12          -8
    14 Dec-21     2     6    14          -4         -12          -8
    15 Nov-21     3     7    15          -4         -12          -8
    16 Oct-21     4     8    16          -4         -12          -8
    

    Then apply the function to your list, i.e.

    lapply(dfList, f1)
    

    DATA

    structure(list(Date = c("Jan-22", "Dec-21", "Nov-21", "Oct-21", 
    "Jan-22", "Dec-21", "Nov-21", "Oct-21", "Jan-22", "Dec-21", "Nov-21", 
    "Oct-21", "Jan-22", "Dec-21", "Nov-21", "Oct-21"), City1 = c(1L, 
    2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), 
        City2 = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 1L, 2L, 3L, 4L, 
        5L, 6L, 7L, 8L), City3 = 1:16), class = "data.frame", row.names = c(NA, 
    -16L))