Home > OS >  How to replace a for loop with map_dl in R
How to replace a for loop with map_dl in R

Time:05-01

i wanted to modify the values of a column whithin a table (dataframe that has 2 column and multiple rows) applying a condition for every row of the second column which, if verified, copyes the values of that cell and paste it into the same row of the first column.

So i wrote a code that does exactly that using a for loop that runs for every row (i) of the table.

The code works well but i would like to learn how to do the same thing with tidyverse, in particular using the map_dl function. I searched everywhere but i didn't manage to understad properly how to use the map_df function.

Here's the code with the for loop:

library(tidyverse)

df <- tibble (Color  = "A",
                  Names = c("Jane Yellow", "Max", "Jeff", "Andy", "Lux Yellow", "Elizabeth", "Susan", "David Yellow", "Thomas", "Lisa"))

col_color <- function(df) { 
  
  for(i in 1:nrow(df)){
    if(grepl("Yellow", df[i,2], fixed=TRUE) == TRUE)
    {df[i,1]<- str_extract(df[i,2], "^(?!.*\bYellow\b).*$")}}
  
  for(i in 2:nrow(df)){
    if(df[i,1] == "A") 
    {df[i,1] <- df[i-1,1]}}
  return(df)
}
df <- col_color(df)

I tried to do it with map_dl with the code below but it doesn't work:

library(tidyverse)

df <- tibble (Color  = "A",
                  Names = c("Jane Yellow", "Max", "Jeff", "Andy", "Lux Yellow", "Elizabeth", "Susan", "David Yellow", "Thomas", "Lisa"))

modify_first_column <- function(i) {
  
  if(grepl("Yellow", df[i,2], fixed=TRUE) == TRUE)
  {df[i,1]<- str_extract(df[i,2], "^(?!.*\bYellow\b).*$")}
  
  if(df[i,1] == "A") 
  {df[i,1] <- df[i-1,1]}
  return(df)
}

modify_first_column <- as.tibble(modify_first_column)
df <- map_df(i = 1:nrow(df), modify_first_column)

Can someone help me figure it out? Thanks

CodePudding user response:

A possible solution to your problem, though without loop or map. But it is within the tidyverse.

library(tidyverse)

Your data:

# A tibble: 10 x 2
   color names       
   <chr> <chr>       
 1 A     Jane Yellow 
 2 A     Max         
 3 A     Jeff        
 4 A     Andy        
 5 A     Lux Yellow  
 6 A     Elizabeth   
 7 A     Susan       
 8 A     David Yellow
 9 A     Thomas      
10 A     Lisa    

First condition:

df <- df %>%
  mutate(color = case_when(str_detect(names, "Yellow") ~ names,
                           TRUE ~ color))
# A tibble: 10 x 2
   color        names       
   <chr>        <chr>       
 1 Jane Yellow  Jane Yellow 
 2 A            Max         
 3 A            Jeff        
 4 A            Andy        
 5 Lux Yellow   Lux Yellow  
 6 A            Elizabeth   
 7 A            Susan       
 8 David Yellow David Yellow
 9 A            Thomas      
10 A            Lisa   

Second condition:

df %>%
  mutate(color = replace(color, color == "A", NA)) %>%
  fill(color)

# A tibble: 10 x 2
   color        names       
   <chr>        <chr>       
 1 Jane Yellow  Jane Yellow 
 2 Jane Yellow  Max         
 3 Jane Yellow  Jeff        
 4 Jane Yellow  Andy        
 5 Lux Yellow   Lux Yellow  
 6 Lux Yellow   Elizabeth   
 7 Lux Yellow   Susan       
 8 David Yellow David Yellow
 9 David Yellow Thomas      
10 David Yellow Lisa     
  • Related