Joshua
Joshua

Reputation: 15

Create factor for multiple dataframes using Loop function

I have mutliple data frames (different size of rows, however, same columns). I want to create a factor in each of them using a loop.

list.dfs <- list(d1, d2, d3, d4, d5, d6, d7, d8)

for (i in 1:length(list.dfs)){
  d[i]$Gender <- factor(d[i]$Gender,
  levels = c(1, 2, 3),
  labels = c("female", "male", "divers")
)
}

This is not working

Upvotes: 1

Views: 161

Answers (2)

maarvd
maarvd

Reputation: 1284

R would not read d[i] as the object d1 if i = 1. You can access items of a list using [[i]]. Note that class(list.dfs[1]) is list while class(list.dfs[[1]]) is data.frame.

As an example

#example data
list.dfs <- list(structure(list(gender = c(1, 2, 3)), class = "data.frame", row.names = c(NA, 
-3L)), structure(list(gender = c(1, 2, 3)), class = "data.frame", row.names = c(NA, 
-3L)))

#check first item
list.dfs[[1]]

  gender
1      1
2      2
3      3

#use for loop to access all items of the list, apply function
for(i in 1:length(list.dfs)){
  list.dfs[[i]]$gender <- factor(list.dfs[[i]]$gender, levels = c(1, 2, 3),
                             labels = c("female", "male", "diverse"))

}

You also might want to read into lapply which applies a function on every object in the list.

#example using lapply
lapply(list.dfs, FUN = function(x) x$gender <- factor(x$gender, levels = c(1,2,3), labels = c("female", "male", "diverse")))

Regarding your comment (assign objects in the list to global environment).

#say we used that lapply function before and end up with this list
list.dfs <- list(structure(1:3, .Label = c("female", "male", "diverse"), class = "factor"), 
    structure(1:3, .Label = c("female", "male", "diverse"), class = "factor"))

Then we can add names to the list according to the order the items were put in the list and assign list objects to global environment.

#add names (will be the object names later)
names(list.dfs) <- c("d1", "d2")

#assign to global environment
for(i in 1:length(list.dfs)){
  assign(names(list.dfs)[i], list.dfs[[i]])
}

Note, I am not a fan of assigning objects like that. Personally I would probably write a function and use that function 8 times. E.g.

#create function
gender_fun <- function(x){
  #read data.frame
  dt1 <- x
  
  #set gender
  dt1$gender <- factor(dt1$gender, levels = c(1,2,3), labels = c("female", "male", "diverse"))

  #return
  return(dt1)
}

#apply function on the data.frames
dt1 <- gender_fun(dt1)
dt2 <- gender_fun(dt2)
#etc...

Upvotes: 1

Rui Barradas
Rui Barradas

Reputation: 76595

Call your factor instruction in a lapply loop and assign the result back to list.dfs.

list.dfs <- list(structure(list(Gender = c(1, 2, 3)), 
                           class = "data.frame", row.names = c(NA, -3L)), 
                 structure(list(Gender = c(1, 2, 3)), 
                           class = "data.frame", row.names = c(NA, -3L)))

list.dfs <- lapply(list.dfs, \(x) {
  x$Gender <- factor(x$Gender, levels = c(1, 2, 3), labels = c("female", "male", "divers"))
  x
})

list.dfs
#> [[1]]
#>   Gender
#> 1 female
#> 2   male
#> 3 divers
#> 
#> [[2]]
#>   Gender
#> 1 female
#> 2   male
#> 3 divers

Created on 2022-05-24 by the reprex package (v2.0.1)

Upvotes: 1

Related Questions