Reputation: 342
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
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
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