Pertanyaan Mengapa dplyr bermutasi () mengubah format waktu?


saya menggunakan readr untuk membaca data yang terdiri dari kolom tanggal dalam format waktu. Saya bisa membacanya dengan benar menggunakan col_types opsi dari readr.

library(dplyr)
library(readr)

sample <- "time,id
2015-03-05 02:28:11,1674
2015-03-03 13:10:59,36749
2015-03-05 07:55:48,NA
2015-03-05 06:13:19,NA
"

mydf <- read_csv(sample, col_types="Ti")
mydf
                 time    id
1 2015-03-05 02:28:11  1674
2 2015-03-03 13:10:59 36749
3 2015-03-05 07:55:48    NA
4 2015-03-05 06:13:19    NA

Ini bagus. Namun, jika saya ingin memanipulasi kolom ini dengan dplyr, kolom waktu kehilangan formatnya.

mydf %>% mutate(time = ifelse(is.na(id), NA, time))
        time    id
1 1425522491  1674
2 1425388259 36749
3         NA    NA
4         NA    NA

Kenapa ini terjadi?

Saya tahu saya dapat mengatasi masalah ini dengan mengubahnya menjadi karakter sebelumnya, tetapi akan lebih mudah tanpa mengubah bolak-balik.

mydf %>% mutate(time = as.character(time)) %>% 
    mutate(time = ifelse(is.na(id), NA, time))

10
2017-09-01 16:36


asal


Jawaban:


Itu sebenarnya ifelse() yang menyebabkan masalah ini, tidak dplyr::mutate(). Contoh masalah pengupasan atribut ditunjukkan dalam help(ifelse) -

## ifelse() strips attributes
## This is important when working with Dates and factors
x <- seq(as.Date("2000-02-29"), as.Date("2004-10-04"), by = "1 month")
## has many "yyyy-mm-29", but a few "yyyy-03-01" in the non-leap years
y <- ifelse(as.POSIXlt(x)$mday == 29, x, NA)
head(y) # not what you expected ... ==> need restore the class attribute:
class(y) <- class(x)

Jadi begitulah. Ini sedikit kerja ekstra jika Anda ingin menggunakannya ifelse(). Berikut dua kemungkinan metode yang akan membawa Anda ke hasil yang Anda inginkan tanpa ifelse(). Yang pertama sangat sederhana dan digunakan is.na<-.

## mark 'time' as NA if 'id' is NA
is.na(mydf$time) <- is.na(mydf$id)

## resulting in
mydf
#                  time    id
# 1 2015-03-05 02:28:11  1674
# 2 2015-03-03 13:10:59 36749
# 3                <NA>    NA
# 4                <NA>    NA

Jika Anda tidak ingin memilih rute itu, dan ingin melanjutkan dengan dplyr metode, Anda dapat menggunakan replace() dari pada ifelse().

mydf %>% mutate(time = replace(time, is.na(id), NA))
#                  time    id
# 1 2015-03-05 02:28:11  1674
# 2 2015-03-03 13:10:59 36749
# 3                <NA>    NA
# 4                <NA>    NA

Data:

mydf <- structure(list(time = structure(c(1425551291, 1425417059, 1425570948, 
1425564799), class = c("POSIXct", "POSIXt"), tzone = ""), id = c(1674L, 
36749L, NA, NA)), .Names = c("time", "id"), class = "data.frame", row.names = c(NA, 
-4L))

19
2017-09-01 16:51



Ada versi lain dari if_else oleh @hadley di dplyr. Ini benar mengelola variabel waktu. Melihat masalah github ini demikian juga.


1
2018-06-28 07:04