Search code examples
rfor-loopapplylapplysapply

How to replace loop by apply function


How to I do this using apply() functions ?

c <- c(df$Station, REF$Secteur, ETAT$Secteur) #three character type columns
for (i in c) {
  i <- toupper(i)
}
sapply(c,toupper)

This provides me with a list, but I would like the modifications to be applied to the original dataframes.


Solution

  • Here is a way with mapply, test data at the end.
    Firs, put the data.frames in a list and the names of the column to be changed in a list or in a vector, below they are in a vector.

    df_list <- list(df, REF, ETAT)
    cols_vec <- c("Station", "Secteur", "Secteur")
    
    mapply(\(x, col) toupper(x[[col]]), df_list, cols_vec, SIMPLIFY = FALSE)
    #> [[1]]
    #> [1] "A" "B" "C"
    #> 
    #> [[2]]
    #> [1] "ABC" "DEF" "XYZ" "U"  
    #> 
    #> [[3]]
    #> [1] "ABC" "DEF" "XYZ"
    

    Created on 2023-02-09 with reprex v2.0.2

    Now, to assign these results back to the data in the list, change function a bit, make it return the df's.

    df <- data.frame(x = 1:3, Station = letters[1:3])
    REF <- data.frame(Secteur = c("Abc", "def", "xyz", "u"))
    ETAT <- data.frame(Secteur = c("Abc", "def", "xyz"), x = 1:3, y = 4:6)
    df_list <- list(df, REF, ETAT)
    cols_vec <- c("Station", "Secteur", "Secteur")
    
    mapply(\(x, col) {
      x[[col]] <-  toupper(x[[col]])
      x
    }, df_list, cols_vec, SIMPLIFY = FALSE)
    #> [[1]]
    #>   x Station
    #> 1 1       A
    #> 2 2       B
    #> 3 3       C
    #> 
    #> [[2]]
    #>   Secteur
    #> 1     ABC
    #> 2     DEF
    #> 3     XYZ
    #> 4       U
    #> 
    #> [[3]]
    #>   Secteur x y
    #> 1     ABC 1 4
    #> 2     DEF 2 5
    #> 3     XYZ 3 6
    

    Created on 2023-02-09 with reprex v2.0.2


    If you want the original data.frames to change, try the following.

    df_list <- mget(c("df", "REF", "ETAT"), envir = .GlobalEnv)
    df_list <- mapply(\(x, col) {
      x[[col]] <-  toupper(x[[col]])
      x
    }, df_list, cols_vec, SIMPLIFY = FALSE)
    
    list2env(df_list, envir = .GlobalEnv)
    #> <environment: R_GlobalEnv>
    
    df
    #>   x Station
    #> 1 1       A
    #> 2 2       B
    #> 3 3       C
    REF
    #>   Secteur
    #> 1     ABC
    #> 2     DEF
    #> 3     XYZ
    #> 4       U
    ETAT
    #>   Secteur x y
    #> 1     ABC 1 4
    #> 2     DEF 2 5
    #> 3     XYZ 3 6
    

    Created on 2023-02-09 with reprex v2.0.2


    Test data

    df <- data.frame(x = 1:3, Station = letters[1:3])
    REF <- data.frame(Secteur = c("Abc", "def", "xyz", "u"))
    ETAT <- data.frame(Secteur = c("Abc", "def", "xyz"), x = 1:3, y = 4:6)
    df_list <- list(df, REF, ETAT)
    cols_vec <- c("Station", "Secteur", "Secteur")
    

    Created on 2023-02-09 with reprex v2.0.2