Search code examples
rmergenested-loops

Merge nested looping of dataframes in R


If I want to do looping and nested looping from list of dataframes. How can I merge dataframes of the nested looping to the main looping dataframes?

coba2 <- data.frame(y=c(1,2,3,4),
                    x1=c(0.0976,0.1118,0.0943,0.0453),
                    x2=c(0.0976,0.2,0.3,0.05),
                    x3=c(0.0976,0.3,0.1,0.06))
coba3 <- data.frame(y=c(1,2,3,4),
                    x1=c(0.09276,0.11218,0.09243,0.04523),
                    x2=c(0.0976,0.2,0.3,0.05),
                    x3=c(0.0976,0.3,0.1,0.06)) 
coba4 <- data.frame(y=c(1,2,3,4),
                    x1=c(0.05943,0.05453,0.05976,0.15118),
                    x2=c(0.0976,0.2,0.3,0.05),
                    x3=c(0.0976,0.3,0.1,0.06))
coba5 <- data.frame(y=c(1,2,3,4),
                    x1=c(0.09773,0.04853,0.1976,0.2118),
                    x2=c(0.09776,0.12,0.333,0.045),
                    x3=c(0.09776,0.23,0.122,0.036))

card2 <- data.frame(y=c(1,2,3,4),
                    x1=c(0.0976,0.1118,0.0943,0.0453),
                    x2=c(0.0976,0.2,0.3,0.05),
                    x3=c(0.0976,0.3,0.1,0.06))
card3 <- data.frame(y=c(1,2,3,4),
                    x1=c(0.09276,0.11218,0.09243,0.04523),
                    x2=c(0.0976,0.2,0.3,0.05),
                    x3=c(0.0976,0.3,0.1,0.06)) 
card4 <- data.frame(y=c(1,2,3,4),
                    x1=c(0.05943,0.05453,0.05976,0.15118),
                    x2=c(0.0976,0.2,0.3,0.05),
                    x3=c(0.0976,0.3,0.1,0.06))
card5 <- data.frame(y=c(1,2,3,4),
                    x1=c(0.09773,0.04853,0.1976,0.2118),
                    x2=c(0.09776,0.12,0.333,0.045),
                    x3=c(0.09776,0.23,0.122,0.036))
data_list = list(coba2, coba3, coba4, coba5)
card_list = list(card2, card3, card4, card5)
for (i in data_list[1:2]){
        for(j in card_list[i+1:i+2]){
             j %>% select(x1,y) %>% rename(x1_1 = x1)
    }
 i %>% merge(j, by = "y")
}
  • so data coba2 will be merge with coba3 and coba4 by y
  • data coba3 will be merge with coba4 and coba5 by y

and so on.

The code didn't work it

Thank you

example expected answer I want: enter image description here

So the answer from the picture: data coba2 merge with card3 and card4 data coba3 merge with card4 and card5


Solution

  • I've tried to create a general solution based on merging data_list[[i]] with data_list[[i+1]] and data_list[[i+2]]:

    First we create a list of the lists we are merging, renaming the columns as we go.

    library(dplyr)
    
    # As we are merging with next 2 the output length will be input length - 2
    list_of_lists  <- vector(mode = "list", length = length(data_list)-2)
    
    for(i in seq_along(data_list)) {
            
            # Do not try to merge past the end of the list
            if(i+2 > length(data_list)) break()
            
            list_to_reduce  <- list(
                data_list[[i]],
                select(data_list[[i+1]], y, x1_1 = x1), 
                select(data_list[[i+2]], y, x_1 = x1)
            )
            list_of_lists[[i]]  <- list_to_reduce
    }
    

    Each element of list_of_lists is a list which contains the three data frames that will be merged together, e.g.:

    list_of_lists[[1]]
    [[1]]
      y     x1     x2     x3
    1 1 0.0976 0.0976 0.0976
    2 2 0.1118 0.2000 0.3000
    3 3 0.0943 0.3000 0.1000
    4 4 0.0453 0.0500 0.0600
    
    [[2]]
      y    x1_1
    1 1 0.09276
    2 2 0.11218
    3 3 0.09243
    4 4 0.04523
    
    [[3]]
      y     x_1
    1 1 0.05943
    2 2 0.05453
    3 3 0.05976
    4 4 0.15118
    

    Then we simply Reduce the dplyr::left_join() function to each element of each sublist, which returns a list of the desired dataframes:

    lapply(
        list_of_lists,
        \(sub_list) {
            Reduce(
            \(x,y) left_join(x,y, by = "y"),
            sub_list
        )
        }
    )
    

    Output:

    [[1]]
      y     x1     x2     x3    x1_1     x_1
    1 1 0.0976 0.0976 0.0976 0.09276 0.05943
    2 2 0.1118 0.2000 0.3000 0.11218 0.05453
    3 3 0.0943 0.3000 0.1000 0.09243 0.05976
    4 4 0.0453 0.0500 0.0600 0.04523 0.15118
    
    [[2]]
      y      x1     x2     x3    x1_1     x_1
    1 1 0.09276 0.0976 0.0976 0.05943 0.09773
    2 2 0.11218 0.2000 0.3000 0.05453 0.04853
    3 3 0.09243 0.3000 0.1000 0.05976 0.19760
    4 4 0.04523 0.0500 0.0600 0.15118 0.21180
    

    Update: merging two lists

    In response to your update, if you want to merge data_list[[i]] with card_list[[i+1]] and card_list[[i+2]], and so on, you can do:

    merge_two_dataframes <- function(data_list_1, data_list_2, n_dataframes = 2) {
    
        # As we are merging with next 2 the output length will be input length - 2
        list_of_lists <- vector(mode = "list", length = length(data_list_1) - n_dataframes)
    
        for (i in seq_along(data_list_1)) {
    
            # Do not try to merge past the end of the list
            if (i + n_dataframes > length(data_list_1)) break
    
            list_to_reduce <- list(
                data_list_1[[i]],
                select(data_list_2[[i + 1]], y, x1_1 = x1),
                select(data_list_2[[i + 2]], y, x_1 = x1)
            )
            list_of_lists[[i]] <- list_to_reduce
        }
    
        lapply(
            list_of_lists,
            \(sub_list) {
                Reduce(
                    \(x, y) left_join(x, y, by = "y"),
                    sub_list
                )
            }
        )
    }
    
    merge_two_dataframes(
        data_list_1 = data_list,
        data_list_2 = card_list
    )
    

    Then it is straightforward to apply this to any list:

    merge_two_dataframes(
        data_list_1 = data_list,
        data_list_2 = card_list
    )
    

    Output:

    [[1]]
      y     x1     x2     x3    x1_1     x_1
    1 1 0.0976 0.0976 0.0976 0.09276 0.05943
    2 2 0.1118 0.2000 0.3000 0.11218 0.05453
    3 3 0.0943 0.3000 0.1000 0.09243 0.05976
    4 4 0.0453 0.0500 0.0600 0.04523 0.15118
    
    [[2]]
      y      x1     x2     x3    x1_1     x_1
    1 1 0.09276 0.0976 0.0976 0.05943 0.09773
    2 2 0.11218 0.2000 0.3000 0.05453 0.04853
    3 3 0.09243 0.3000 0.1000 0.05976 0.19760
    4 4 0.04523 0.0500 0.0600 0.15118 0.21180