Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using purrr to affect single columns of each dataframe in a list

Tags:

r

purrr

tidyverse

still getting used to purrr and I have one of those questions that I think should be easy, but I don't know how to do it. All I want to do is convert the datetimes in the below, to dates with as.Date(). it's a list of dataframes. Been playing around but haven't found something that works yet... any help appreciated.

df <- data.frame(Date = seq.POSIXt(Sys.time(), Sys.time() + hours(24), by = "hour"),
             useless = "ignore me")
df2 <- data.frame(Date = seq.POSIXt(Sys.time(), Sys.time() + hours(1), by = "min"),
                    useless = "ignore me")
mylist <- list(df,df2)
mylist %<>% map(?????)
like image 656
jsg51483 Avatar asked Apr 04 '17 22:04

jsg51483


2 Answers

The canonical way to achieve your goal would be to combine map with some verb from dplyr, like mutate_at. Currently purrr still has the function dmap_at, but it will be removed from purrr in the future.

Hence, you would map over your list, and then modify the date column with mutate_at:

library(purrr)
library(lubridate)
library(dplyr)

mylist %>%
  map(~mutate_at(.x, "Date", as.Date))

You could also use at_depth, which in the case of at_depth(1, ...) is equal to map and is therefore not necessary:

mylist %>%
  at_depth(1, ~mutate_at(.x, "Date", as.Date))

The original approach, staying within purrr, was to use dmap_at:

mylist %>%
  map(~dmap_at(.x, "Date", as.Date))

But since we now have mutate_at and mutate_all and friends, it is recommended to use them instead of dmap, dmap_at and so forth.

Data

df <- data.frame(Date = seq.POSIXt(Sys.time(), Sys.time() + hours(24), by = "hour"),
                 useless = "ignore me")
df2 <- data.frame(Date = seq.POSIXt(Sys.time(), Sys.time() + hours(1), by = "min"),
                  useless = "ignore me")
mylist <- list(df,df2)
like image 87
Thomas K Avatar answered Oct 18 '22 03:10

Thomas K


You can combine map() with mutate() from the dplyr package (also tidyverse). map() can be used to apply mutate() each data frame in your list. mutate() can apply as.Date() to the Date column. You'd write it like this:

map(mylist, mutate, Date = as.Date(Date))

This line is saying:

  • map()/apply the mutate() function to each object in mylist
  • Each time mutate() is applied to an object, do it as if you were writing mutate(object, Date = as.Date(Date))

Full code:

library(lubridate)
library(purrr)
library(dplyr)

df <- data.frame(Date = seq.POSIXt(Sys.time(), Sys.time() + hours(24), by = "hour"),
                 useless = "ignore me")
df2 <- data.frame(Date = seq.POSIXt(Sys.time(), Sys.time() + hours(1), by = "min"),
                  useless = "ignore me")
mylist <- list(df,df2)
mylist <- map(mylist, mutate, Date = as.Date(Date))
like image 45
Simon Jackson Avatar answered Oct 18 '22 05:10

Simon Jackson