如何在R中修复损坏的日期?

时间:2018-09-12 01:31:39

标签: r date

我有一个数据集,如下所示:

19/9/1997 1997/9/22 1997年23月9日 1997年9月24日 1997年9月25日 1997年9月26日 29/9/1997 1997/9/30

35440 35471 35499 35591 35621 35652 35683 35713

1997年10月13日 1997年10月14日 15/10/1997 1997年10月16日 1997年10月17日 1997年10月20日 1997年10月21日 1997年10月22日 1997年10月23日 1997年10月24日 1997年10月27日 1997年10月28日 1997年10月29日 30/10/1997 1997年10月31日

35500 35531 35561 35592 35622 35714 35745 35775

1997年11月13日 1997年11月14日 1997年11月17日 1997年11月18日 1997/11/19 1997年11月20日 1997年11月21日 1997年11月24日...

此处应包含的数据(用于按要求复制) 1997年9月19日 1997/9/22 1997年23月9日 1997年9月24日 1997年9月25日 1997年9月26日 29/9/1997 1997年9月30日 1997年10月1日 10/02/1997 1997年10月3日 10/06/1997 1997年10月7日 1997年10月8日 1997年10月9日 1997/10/10 1997年10月13日 1997年10月14日 15/10/1997 1997年10月16日 1997年10月17日 1997年10月20日 1997年10月21日 1997年10月22日 1997年10月23日 1997年10月24日 1997年10月27日 1997年10月28日 1997年10月29日 30/10/1997 1997年10月31日 1997年11月3日 1997年11月4日 1997年11月5日 11/06/1997 1997年11月7日 1997年11月10日 1997/11/11 1997年11月12日 1997年11月13日 1997年11月14日 1997年11月17日 1997年11月18日 1997/11/19 1997年11月20日 1997年11月21日 1997年11月24日

我有5149行日期,其中日期位置有数字。我尝试使用此方法来修复丢失的日期: 修订前尝试1:

  rm (list = ls(all=TRUE))
    graphics.off()
    library(readxl)
    Dates <- read_excel("F:/OneDrive - University of Tasmania/Mardi Meetings/Dataset/Dates.xlsx")
    x<-Dates[,1]
    library(date)
    library(datetime)
    ans <- Reduce(function(prev, curr) {
      f1 <- as.Date(curr, "%d/%m/%Y")
      f2 <- as.Date(curr, "%m/%d/%Y")
      if (is.na(f1)) return(f2)
      if (is.na(f2)) return(f1)
      if (prev < f1 && prev < f2) return(min(f1, f2))
      if (prev < f1) return(f1)
      if (prev < f2) return(f2)
    }, x[-1], init=as.Date(x[1], "%d/%m/%Y"), accumulate=TRUE)

    as.Date(ans, origin="1970-01-01")

但是我遇到以下错误:

+ }, x[-1], init=as.Date(x[1], "%d/%m/%Y"), accumulate=TRUE)
Error in Reduce(function(prev, curr) { : object 'x' not found
> 
> as.Date(ans, origin="1970-01-01")
Error in as.Date(ans, origin = "1970-01-01") : object 'ans' not found

任何建议将不胜感激。

好的,我建议您在修订后修改代码尝试2

    > rm (list = ls(all=TRUE))
    > graphics.off()
    > library(readxl)
    > Dates <- read_excel("F:/OneDrive - University of Tasmania/Mardi Meetings/Dataset/Dates.xlsx")
    > dput(head(Dates))
    structure(list(Date = c("33274", "33302", "33394", "33424", "33455", 
    "33486")), row.names = c(NA, -6L), class = c("tbl_df", "tbl", 
    "data.frame"))
    > x<-Dates[[1]] 
    > library(date) 
    > library(datetime) 

    Attaching package: ‘datetime’

    The following object is masked from ‘package:date’:

        as.date

    > dates <- as.Date(x, format="%d/%m/%Y")
    > dput(head(dates))
    structure(c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
    NA_real_), class = "Date")
    > head(dates,10)
     [1] NA           NA           NA           NA           NA           NA           NA          
     [8] "1991-05-13" "1991-05-14" "1991-05-15"
As you can see I have lost the corrupted dates completely

今天28号,我再次尝试了

> rm (list = ls(all=TRUE))
> graphics.off()
> library(readxl)
> Dates <- read_excel("F:/OneDrive - University of Tasmania/Mardi Meetings/Dataset/Dates.xlsx")
> x<-Dates[[1]] 
> 
> library(date) 
> library(datetime) 

Attaching package: ‘datetime’

The following object is masked from ‘package:date’:

    as.date

> formats <- c("%m/%d/%Y", "%d/%m/%Y", "%Y/%m/%d")
> dates <- as.Date(rep(NA, length(x)))
> for (fmt in formats) {
+   nas <- is.na(dates)
+   dates[nas] <- as.Date(as.integer(x[nas], format=fmt))
+ }
Error in as.Date.numeric(as.integer(x[nas], format = fmt)) : 
  'origin' must be supplied
In addition: Warning message:
In as.Date(as.integer(x[nas], format = fmt)) : NAs introduced by coercion
> dates <- as.Date(x, format="%d/%m/%Y")
> head(dates)
[1] NA NA NA NA NA NA
> head(dates, 10)
 [1] NA           NA           NA           NA           NA           NA           NA          
 [8] "1991-05-13" "1991-05-14" "1991-05-15"

1 个答案:

答案 0 :(得分:3)

您不需要加载的任何软件包,也不需要使用Reduce,因为我们在这里使用的功能自然是“矢量化的”。

这是您的数据示例。 (一个很好的问题包括诸如容易这样的复制格式的数据。)

x <- c("19/9/1997", "22/9/1997", "23/9/1997", "24/9/1997", "25/9/1997",
       "26/9/1997", "29/9/1997", "30/9/1997",
       "35440", "35471", "35499", "35591", "35621",
       "35652", "35683", "35713")

dates <- as.Date(x, format="%d/%m/%Y")
dates
#  [1] "1997-09-19" "1997-09-22" "1997-09-23" "1997-09-24" "1997-09-25"
#  [6] "1997-09-26" "1997-09-29" "1997-09-30" NA           NA          
# [11] NA           NA           NA           NA           NA          
# [16] NA          

毫不奇怪,给定format="%d/%m/%Y",日期的后半部分未被识别。您提到了在问题中使用"%m/%d/%Y"的情况,因此我们可以(1)对这种格式进行字面的二次遍历(此示例未使用,但仍与您的工作相关吗?):

dates[is.na(dates)] <- as.Date(x[is.na(dates)], format="%m/%d/%Y")

其中[is.na(dates)]仅适用于未转换的元素。

(2)如果我们有多种其他格式,则始终可以使用它们的向量并在它们上循环。 (为此,我将重新开始,因为此循环将替换/增强上面的第一步。)

formats <- c("%m/%d/%Y", "%d/%m/%Y", "%Y/%m/%d")
dates <- as.Date(rep(NA, length(x)))
for (fmt in formats) {
  nas <- is.na(dates)
  dates[nas] <- as.Date(x[nas], format=fmt)
}
dates
#  [1] "1997-09-19" "1997-09-22" "1997-09-23" "1997-09-24" "1997-09-25"
#  [6] "1997-09-26" "1997-09-29" "1997-09-30" NA           NA          
# [11] NA           NA           NA           NA           NA          
# [16] NA          

这仍然使我们有NA s个整数的值。对于这些,您需要指定origin=才能弄清楚(以及转换为整数)。 R通常使用"1970-01-01"的原点,您可以通过以下方式确认

as.integer(Sys.Date())
# [1] 17787
Sys.Date() - 17787
# [1] "1970-01-01"

但是您的日期似乎是"1900-01-01"的原点,我认为这是Excel的默认日期存储方式(但在这里无关紧要):

x[9]    # the first integer-looking element
# [1] "35440"
dates[1] - as.integer(x[9])
# [1] "1900-09-08"

(我假设您的日期来自相同的相对时间段。)

从这里:

nas <- is.na(dates)
dates[nas] <- as.Date(as.integer(x[nas]), origin="1900-01-01")
dates
#  [1] "1997-09-19" "1997-09-22" "1997-09-23" "1997-09-24" "1997-09-25"
#  [6] "1997-09-26" "1997-09-29" "1997-09-30" "1997-01-12" "1997-02-12"
# [11] "1997-03-12" "1997-06-12" "1997-07-12" "1997-08-12" "1997-09-12"
# [16] "1997-10-12"

(仅处理NA个元素的索引是相对有效的,因为它只能处理并替换尚未匹配的条目。如果没有其他东西可以调用{{1 }},它仍然会调用它,但是使用长度为0的参数,函数可以有效地工作,我认为添加条件as.Date不会有帮助,但是如果还有其他方法,则需要可能会更“昂贵”,您可以考虑一下。)