petergensler
petergensler

Reputation: 342

Function to convert POSIXct to Date class

Hello I am trying to write a function that takes in a dataframe, and that will convert all POSIXct or POSIXlt types to Date type in R. I have created part of the function, but I am stuck on iterating over the elements at each index.

#Basic Data Frame
patientID <- c(1, 2, 3, 4)
AdmDate <- as.POSIXct(c('2010-10-11','2008-3-25','2016-4-23','2011-6-12'))
diabetes <- c("Type1", "Type2", "Type1", "Type2")
status <- c("Poor", "Improved", "Excellent", "Poor")
patientdata <- data.frame(patientID, AdmDate, diabetes, status)


convertallPOSIXct <- function(data){
 if(getdata[[is.POSIXt()=='TRUE']])
   getdata[[]] <- class(as.Date()) 
}

getdata <- function(x) {
  chr_test <- x %>%
    map_chr(~ paste(class(.), collapse = "/"))
}

The get data function seems to work, but I am not sure how to take each element from getdata and transform it to a Date class in R. Thanks!

Upvotes: 3

Views: 6339

Answers (2)

alistaire
alistaire

Reputation: 43344

If you're using purrr and lubridate, you could just write

library(purrr)
library(lubridate)

patientdata <- data.frame(
    patientID = c(1, 2, 3, 4),
    AdmDate = as.POSIXct(c("2010-10-11", "2008-03-25", "2016-04-23", "2011-06-12")),
    diabetes = c("Type1", "Type2", "Type1", "Type2"),
    status = c("Poor", "Improved", "Excellent", "Poor")
)

patientdata %>% modify_if(is.POSIXt, as.Date)

which will return something that looks the same as the original, but with the classes changed as you can see if you call str on it:

patientdata %>% modify_if(is.POSIXt, as.Date) %>% str()
#> 'data.frame':    4 obs. of  4 variables:
#>  $ patientID: num  1 2 3 4
#>  $ AdmDate  : Date, format: "2010-10-11" "2008-03-25" "2016-04-23" ...
#>  $ diabetes : Factor w/ 2 levels "Type1","Type2": 1 2 1 2
#>  $ status   : Factor w/ 3 levels "Excellent","Improved",..: 3 2 1 3

Note that you need modify so purrr will keep the list a data.frame, and the *_if version, which takes a predicate function to determine which columns/elements to call the main function on.

If you don't want to use lubridate just for is.POSIXt, you could equivalently write

patientdata %>% modify_if(~'POSIXt' %in% class(.x), as.Date)

or the dplyr version:

library(dplyr)

patientdata %>% mutate_if(~'POSIXt' %in% class(.x), as.Date)

which with lubridate::is.POSIXt is as nice as the original:

patientdata %>% mutate_if(is.POSIXt, as.Date)

Upvotes: 4

nrussell
nrussell

Reputation: 18602

Here's one option with lapply:

df <- patientdata

df[] <- lapply(df, function(x) {
    if (inherits(x, "POSIXt")) as.Date(x) else x
})

str(df)
# 'data.frame': 4 obs. of  4 variables:
#  $ patientID: num  1 2 3 4
#  $ AdmDate  : Date, format: "2010-10-11" "2008-03-25" ...
#  $ diabetes : chr  "Type1" "Type2" "Type1" "Type2"
#  $ status   : chr  "Poor" "Improved" "Excellent" "Poor"

The [] is necessary to preserve the data.frame structure, else you would end up with an ordinary list. Using inherits instead of class(object) == "some_class" is preferred because if the object has multiple classes -- which POSIXt objects do -- you still get a single logical result:

class(patientdata[,2]) == "POSIXt"
#[1] FALSE  TRUE

inherits(patientdata[,2], "POSIXt")
#[1] TRUE

Upvotes: 5

Related Questions