我在lubridate
包中偶然发现了一种奇怪的行为:dmy(NA)
拖欠错误而不是仅返回NA。当我想要转换一个包含一些元素为NA的列以及一些通常在没有问题时转换的日期字符串时,这会导致我出现问题。
这是最小的例子:
library(lubridate)
df <- data.frame(ID=letters[1:5],
Datum=c("01.01.1990", NA, "11.01.1990", NA, "01.02.1990"))
df_copy <- df
#Question 1: Why does dmy(NA) not return NA, but throws an error?
df$Datum <- dmy(df$Datum)
Error in function (..., sep = " ", collapse = NULL) : invalid separator
df <- df_copy
#Question 2: What's a work around?
#1. Idea: Only convert those elements that are not NAs
#RHS works, but assigning that to the LHS doesn't work (Most likely problem::
#column "Datum" is still of class factor, while the RHS is of class POSIXct)
df[!is.na(df$Datum), "Datum"] <- dmy(df[!is.na(df$Datum), "Datum"])
Using date format %d.%m.%Y.
Warning message:
In `[<-.factor`(`*tmp*`, iseq, value = c(NA_integer_, NA_integer_, :
invalid factor level, NAs generated
df #Only NAs, apparently problem with class of column "Datum"
ID Datum
1 a <NA>
2 b <NA>
3 c <NA>
4 d <NA>
5 e <NA>
df <- df_copy
#2. Idea: Use mapply and apply dmy only to those elements that are not NA
df[, "Datum"] <- mapply(function(x) {if (is.na(x)) {
return(NA)
} else {
return(dmy(x))
}}, df$Datum)
df #Meaningless numbers returned instead of date-objects
ID Datum
1 a 631152000
2 b NA
3 c 632016000
4 d NA
5 e 633830400
总结一下,我有两个问题:1)为什么dmy(NA)不起作用?基于大多数其他函数,我认为良好的编程习惯是NA
的每个转换(例如dmy())再次返回NA
(就像2 + NA
那样)?如果出现此问题,如何通过data.frame
函数转换包含NA
的{{1}}列?
答案 0 :(得分:6)
Error in function (..., sep = " ", collapse = NULL) : invalid separator
由lubridate:::guess_format()
函数引起。在NA
的来电中,sep
正在paste()
传递,特别是在fmts <- unlist(mlply(with_seps, paste))
。您可以改进lubridate:::guess_format()
来解决此问题。
否则,您是否可以将NA
更改为字符("NA"
)?
require(lubridate)
df <- data.frame(ID=letters[1:5],
Datum=c("01.01.1990", "NA", "11.01.1990", "NA", "01.02.1990")) #NAs are quoted
df_copy <- df
df$Datum <- dmy(df$Datum)
答案 1 :(得分:3)
由于您的日期采用了相当直接的格式,因此使用as.Date
并指定适当的format
参数可能要简单得多:
df$Date <- as.Date(df$Datum, format="%d.%m.%Y")
df
ID Datum Date
1 a 01.01.1990 1990-01-01
2 b <NA> <NA>
3 c 11.01.1990 1990-01-11
4 d <NA> <NA>
5 e 01.02.1990 1990-02-01
要查看as.Date
使用的格式代码列表,请参阅?strptime