Home > Software engineering >  Add string to list of dfs in R
Add string to list of dfs in R

Time:09-22

I have a list of dataframes with varying rows and columns. Here is an example:

> df_input_list
[[1]]
   Feature    Method                              
1    Feat1  Variant1                                                   
2    Feat2  Variant2 

[[2]]
   Feature2  Method2 Attribute
1     Feat3 Variant3     Attr1
2     Feat4 Variant4     Attr2
3     Feat5 Variant5     Attr3

Now I want to add strings to the entire dataframes in a list with lengt n, however, with varying strings to the respective dfs. Like this:

> df_input_list
[[1]]
           Feature            Method                              
1    String1_Feat1  String1_Variant1                                                   
2    String1_Feat2  String1_Variant2 

[[2]]
          Feature2          Method2      Attribute
1    String2_Feat3 String2_Variant3  String2_Attr1
2    String2_Feat4 String2_Variant4  String2_Attr2
3    String2_Feat5 String2_Variant5  String2_Attr3

I tried for loops with paste(), but I can not figure out the correct way.

CodePudding user response:

Using base R

Map(\(x, i) {
 x[] <- paste0('String', i, as.matrix(x))
x
}
, df_input_list, seq_along(df_input_list))

CodePudding user response:

With imap (created a mock dataset first):

library(purrr)
l <- list(head(cars), head(cars))

imap(l, \(x, y) map_dfr(x, \(z) paste0("String", y, "_", z)))

output

[[1]]
# A tibble: 6 × 2
  speed     dist      
  <chr>     <chr>     
1 String1_4 String1_2 
2 String1_4 String1_10
3 String1_7 String1_4 
4 String1_7 String1_22
5 String1_8 String1_16
6 String1_9 String1_10

[[2]]
# A tibble: 6 × 2
  speed     dist      
  <chr>     <chr>     
1 String2_4 String2_2 
2 String2_4 String2_10
3 String2_7 String2_4 
4 String2_7 String2_22
5 String2_8 String2_16
6 String2_9 String2_10

CodePudding user response:

Here's an option with purrr::map2() so you can use both the original list as .x and use .y as seq_along(.x) so you can also keep track of where you are in the list.

Note there are nested lambda functions that each use .x as the argument which works but may be confusing at first glance.

library(tidyverse)

l <- list(
  tibble(
    feature = paste0("feature", 1:2),
    method = paste0("variant", 1:2)
  ),
  tibble(
    feature2 = paste0("feature", 3:5),
    method2 = paste0("variant", 3:5),
    attribute = paste0("attr", 1:3)
  )
)

l %>% 
  map2(.y = seq_along(.),
       ~mutate(.x, across(everything(), ~paste0("String", .y, "_", .x))))
#> [[1]]
#> # A tibble: 2 × 2
#>   feature          method          
#>   <chr>            <chr>           
#> 1 String1_feature1 String1_variant1
#> 2 String1_feature2 String1_variant2
#> 
#> [[2]]
#> # A tibble: 3 × 3
#>   feature2         method2          attribute    
#>   <chr>            <chr>            <chr>        
#> 1 String2_feature3 String2_variant3 String2_attr1
#> 2 String2_feature4 String2_variant4 String2_attr2
#> 3 String2_feature5 String2_variant5 String2_attr3

Created on 2022-09-21 by the reprex package (v2.0.1)

CodePudding user response:

Double for loop solution.

s <- c('String1', 'String2')
for (i in seq_along(df_input_list)) {
  for (j in seq_along(df_input_list[[i]])) {
    df_input_list[[i]][[j]] <- paste(s[i], df_input_list[[i]][[j]], sep='_')
  }
}
df_input_list
# [[1]]
# Feature           Method
# 1 String1_Feat1 String1_Variant1
# 2 String1_Feat2 String1_Variant2
# 
# [[2]]
# Feature2          Method2     Attribute
# 1 String2_Feat3 String2_Variant3 String2_Attr1
# 2 String2_Feat4 String2_Variant4 String2_Attr2
# 3 String2_Feat5 String2_Variant5 String2_Attr3

Data:

df_input_list <- list(structure(list(Feature = c("Feat1", "Feat2"), Method = c("Variant1", 
"Variant2")), class = "data.frame", row.names = c("1", "2")), 
    structure(list(Feature2 = c("Feat3", "Feat4", "Feat5"), Method2 = c("Variant3", 
    "Variant4", "Variant5"), Attribute = c("Attr1", "Attr2", 
    "Attr3")), class = "data.frame", row.names = c("1", "2", 
    "3")))
  •  Tags:  
  • r
  • Related