Nathan123
Nathan123

Reputation: 763

how to covert column type of data frames that are inside a list?

I have the following two data frames that in a list called df.list

df1 <- data.frame(name=c("a","b","c"),total=c("1","2","3"),other=c("100","200","300"))
df2 <- data.frame(name=c("d","e","f"),total=c("4","5","6"),other=c("100","200","300"))



df.list <- list(df1,df2)

[[1]]
  name total other
1    a     1   100
2    b     2   200
3    c     3   300

[[2]]
  name total other
1    d     4   100
2    e     5   200
3    f     6   300

I want to be able to go through each data frame in the list and covert the total and other columns to be numeric, and assign it back to df.list

I tried the following but it does not seem to work

lapply(df.list, function(x) as.numeric(x[2:3]))

Upvotes: 3

Views: 55

Answers (3)

Anoushiravan R
Anoushiravan R

Reputation: 21918

Or maybe this one:

library(purrr)

df.list %>%
        map(., ~mutate(.x, across(c(other, total), ~as.numeric(.x)))) %>%
        str()

List of 2
 $ :'data.frame':   3 obs. of  3 variables:
  ..$ name : chr [1:3] "a" "b" "c"
  ..$ total: num [1:3] 1 2 3
  ..$ other: num [1:3] 100 200 300
 $ :'data.frame':   3 obs. of  3 variables:
  ..$ name : chr [1:3] "d" "e" "f"
  ..$ total: num [1:3] 4 5 6
  ..$ other: num [1:3] 100 200 300

Upvotes: 3

Marcelo Avila
Marcelo Avila

Reputation: 2374

you can create a function that works for each data frame such as the following functional_as_numeric() and then apply to each element in the list with map() from {purrr}. Personally I find {purrr}'s interface more consistent and easier to follow than the traditional _apply() functions.

library(purrr)

functional_as_numeric <- function(df) {
  df %>% mutate(
    total = as.numeric(total), 
    other = as.numeric(other)
  )
}

df.list.result <- df.list %>% 
  purrr::map(functional_as_numeric)

str(df.list.result)
List of 2
 $ :'data.frame':   3 obs. of  3 variables:
  ..$ name : chr [1:3] "a" "b" "c"
  ..$ total: num [1:3] 1 2 3
  ..$ other: num [1:3] 100 200 300
 $ :'data.frame':   3 obs. of  3 variables:
  ..$ name : chr [1:3] "d" "e" "f"
  ..$ total: num [1:3] 4 5 6
  ..$ other: num [1:3] 100 200 300

Upvotes: 2

akrun
akrun

Reputation: 887128

We may use type.convert directly on the list

df.list2 <- type.convert(df.list, as.is = TRUE) 

-checking the structure

 str(df.list2)
List of 2
 $ :'data.frame':   3 obs. of  3 variables:
  ..$ name : chr [1:3] "a" "b" "c"
  ..$ total: int [1:3] 1 2 3
  ..$ other: int [1:3] 100 200 300
 $ :'data.frame':   3 obs. of  3 variables:
  ..$ name : chr [1:3] "d" "e" "f"
  ..$ total: int [1:3] 4 5 6
  ..$ other: int [1:3] 100 200 300

If we want to loop, then as.integer/as.numeric works on vectors. So, we need to loop again

df.list2 <- lapply(df.list, function(x) {
             x[2:3] <- lapply(x[2:3], as.integer)
             x})

Upvotes: 3

Related Questions