Search code examples
rtidyversepurrr

How to change the class of a column in a list of a list from character to numeric in r?


The codes for producing sample dataset and converting from character to numeric is as below:

ff = data.frame(a = c('1','2','3'),b = 1:3, c = 5:7)
#data.frame is a type of list.

fff = list(ff,ff,ff,ff)

k = fff %>% map(~map(.x,function(x){x['a'] %<>% as.numeric
  return(x)}))

However, the result is something like this...: There are 3 lists appear in each of the nested list ==> 33 = 9, which is very strange. I think the result should have 3 lists in a nested list.==> 31 = 3

what I want is to convert every a in each dataframe to be numeric.

> k
[[1]]
[[1]]$a
              a 
"1" "2" "3"  NA 

[[1]]$b
          a 
 1  2  3 NA 

[[1]]$c
          a 
 5  6  7 NA 


[[2]]
[[2]]$a
              a 
"1" "2" "3"  NA 

[[2]]$b
          a 
 1  2  3 NA 

[[2]]$c
          a 
 5  6  7 NA 


[[3]]
[[3]]$a
              a 
"1" "2" "3"  NA 

[[3]]$b
          a 
 1  2  3 NA 

[[3]]$c
          a 
 5  6  7 NA 


[[4]]
[[4]]$a
              a 
"1" "2" "3"  NA 

[[4]]$b
          a 
 1  2  3 NA 

[[4]]$c
          a 
 5  6  7 NA 

I cannot understand why I cannot convert a into numeric...


Solution

  • Like this, with mutate:

    fff %>% 
      map(~ mutate(.x, a = as.numeric(a)))
    

    Or, more base R style:

    fff %>% 
      map(\(x) {x$a <- as.numeric(x$a); x})
    

    You should use map only once, because you don't have a nested list. With the first map, you access to each dataframe, and then you can convert to numeric. With a second map, you are accessing the columns of each data frame (which you don't want).

    With two maps, it's also preferable to use \ or function rather than ~ because it becomes confusing to use .x and x for different objects. In your question, .x is the dataframe, while x are columns of it.