rlistloopsclassfor-loop

Changing the Class of Multiple Dataframes' Columns with For Loop in R


I have many dataframes imported from csv files, all having one similar column name: ActivityHour. Its class was imported as character, but I want to change it to date and time with the lubridate mdy_hms() function in R. So, I created a list of the dataframes and ran a for loop so that I do not write the code for each dataframe. However, whenever I try to run class() for ActivityHour for any of these dataframes in the terminal after running the for loop, the output is still character. Interestingly, if I include the class() function inside the for loop, the class of ActivityHour does become POSIXct. I would really appreciate your help! Thank you!

Here is the code I tried to run; I will use sample data:

hourlyIntensities1 <- data.frame(
    Id = c(1,2,3,4),
    ActivityHour = c("3/12/2016 12:00:00 AM","3/12/2016 2:00:00 AM","3/12/2016 4:00:00 PM","3/13/2016 1:00:00 AM"),
    Intensity = c(2,5,3,9)
)
hourlyIntensities2 <- data.frame(
    Id = c(1,2,3,4),
    ActivityHour = c("4/12/2016 12:00:00 AM","4/12/2016 2:00:00 AM","4/12/2016 4:00:00 PM","4/13/2016 1:00:00 AM"),
    Intensity = c(7,4,8,2)
)
hourlySteps1 <- data.frame(
    Id = c(1,2,3,4),
    ActivityHour = c("3/12/2016 12:00:00 AM","3/12/2016 2:00:00 AM","3/12/2016 4:00:00 PM","3/13/2016 1:00:00 AM"),
    Steps = c(950, 784, 631, 982)
)
hourlySteps2 <- data.frame(
    Id = c(1,2,3,4),
    ActivityHour = c("3/12/2016 12:00:00 AM","3/12/2016 2:00:00 AM","3/12/2016 4:00:00 PM","3/13/2016 1:00:00 AM"),
    Steps = c(740, 650, 875, 265)
)
hourly <- list(hourlyIntensities1, hourlyIntensities2, hourlySteps1, hourlySteps2)
for (df in hourly) {
    df$ActivityHour <- mdy_hms(df$ActivityHour)
    print(class(df$ActivityHour))
}

I got the following result:

[1] "POSIXct" "POSIXt" 

[1] "POSIXct" "POSIXt" 

[1] "POSIXct" "POSIXt" 

[1] "POSIXct" "POSIXt" 

Then, I ran the following...

print(class(hourlyIntensities1$ActivityHour))

...only to get this:

[1] "character"


Solution

  • If you (think you) need to change objects in your global environment in such way, you can loop through a list of object names and use get() & assign():

    (hourly <- ls(pattern = "^hourly.*"))
    #> [1] "hourlyIntensities1" "hourlyIntensities2" "hourlySteps1"      
    #> [4] "hourlySteps2"
    
    str(hourlyIntensities1$ActivityHour)
    #>  chr [1:4] "3/12/2016 12:00:00 AM" "3/12/2016 2:00:00 AM" ...
    
    for (df in hourly){
      message("Updating ", df)
      assign(df, transform(get(df), ActivityHour = lubridate::mdy_hms(ActivityHour)))
    }
    #> Updating hourlyIntensities1
    #> Updating hourlyIntensities2
    #> Updating hourlySteps1
    #> Updating hourlySteps2
    
    str(hourlyIntensities1$ActivityHour)
    #>  POSIXct[1:4], format: "2016-03-12 00:00:00" "2016-03-12 02:00:00" "2016-03-12 16:00:00" ...
    

    More idiomatic approach would be building your workflow on top of lists and lapply() / purrr::map() & friends, perhaps just few threads to start with (it's also worth checking answers with latest updates, not just with highest number of votes) :
    How to import multiple .csv files at once?
    How do I make a list of data frames?