using purrr to affect single columns of each dataf

2019-06-20 08:53发布

问题:

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(?????)

回答1:

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)


回答2:

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))