user971102
user971102

Reputation: 3075

Change the class of columns in a list of data frames

I have a list of data frames, e.g.

df1 = data.frame(ID=c("id1", "id2", "id3"), A1 = c("A", "A", "B"), A2 = c("AA", "AA", "AA"))
df2 = data.frame(ID=c("id2", "id3", "id4"), A1 = c("B", "B", "B"), A2=c("BB", "BB", "BB"))
df3 = data.frame(ID=c("id1", "id2", "id3"), A1 = c("A", "A", "A"), A2 = c("AA", "BB", "BB"))
listDF = list(df1, df2, df3)

I am wondering if there is a good way to change the class from factor to character. This is what I have tried:

d <- lapply(listDF, function(x) sapply(x[,"A1", "A2"], as.character))

This code gives me the columns I want to change, but is there a way to just change the class and not have to re-append these new columns?

Upvotes: 5

Views: 2891

Answers (4)

AndrewGB
AndrewGB

Reputation: 16836

With tidyverse, you can use a combination of purrr and across inside mutate to change particular columns in each dataframe in the list. Here, I use starts_with, but you can also supply the names too (i.e., c(A1, A2)).

library(tidyverse)

map(listDF, ~ .x %>%
      mutate(across(starts_with("A"), as.character)))

Upvotes: 0

Lorenz9
Lorenz9

Reputation: 1

The list.update function from rlist package provides a handy alternative.

  names(listDF) <- c("df1", "df2", "df3")
  d <- list.update(listDF,A1 = as.factor(A1), A2 = as.factor(A2))

Upvotes: 0

akrun
akrun

Reputation: 886998

We can use data.table

lapply(listDF, function(df) setDT(df)[, (2:3) := lapply(.SD, as.character), .SDcols = 2:3]) 

Upvotes: 1

akuiper
akuiper

Reputation: 214927

mutate_at() function from dplyr package comes handy here:

library(dplyr)
d <- lapply(listDF, function(df) mutate_at(df, .cols = 2:3, as.character))

You can also pass the column names to .cols parameter:

d <- lapply(listDF, function(df) mutate_at(df, .cols = c("A1", "A2"), as.character))

Or select the columns by regex:

# mutate columns whose names start with A
d <- lapply(listDF, function(df) mutate_at(df, vars(matches("^A")), as.character))

In base R, this could be:

d <- lapply(listDF, function(df) {df[c("A1", "A2")] <- lapply(df[c("A1", "A2")], as.character); df})

Upvotes: 5

Related Questions