如何修复R中的损坏日期? [英] How can I fix corrupted dates in R?

查看:48
本文介绍了如何修复R中的损坏日期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a dataset as follows:

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

19/9/1997 22/9/1997 23/9/1997 24/9/1997 25/9/1997 26/9/1997 29/9/1997 30/9/1997

3544035471354993559135621356523568335713

35440 35471 35499 35591 35621 35652 35683 35713

13/10/19971997年10月14日15/10/19971997年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日1997年10月30日1997年10月31日

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

3550035531355613559235622357143574535775

35500 35531 35561 35592 35622 35714 35745 35775

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

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

此处应包含的数据(用于按要求复制)1997年9月19日1997/9/221997年23月9日1997年9月24日1997年9月25日1997年9月26日1997年9月29日1997年9月30日1997年10月1日1997年10月2日1997年10月3日10/06/19971997年10月7日1997年10月8日1997年10月9日1997/10/101997年10月13日1997年10月14日15/10/19971997年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日1997年10月30日1997年10月31日1997年11月3日1997年11月4日1997年11月5日11/06/19971997年11月7日1997年11月10日1997/11/111997年11月12日1997年11月13日1997年11月14日1997年11月17日1997年11月18日1997/11/191997年11月20日1997年11月21日1997年11月24日

The Data that should be here are (for reproduction as requested) 19/9/1997 22/9/1997 23/9/1997 24/9/1997 25/9/1997 26/9/1997 29/9/1997 30/9/1997 10/01/1997 10/02/1997 10/03/1997 10/06/1997 10/07/1997 10/08/1997 10/09/1997 10/10/1997 13/10/1997 14/10/1997 15/10/1997 16/10/1997 17/10/1997 20/10/1997 21/10/1997 22/10/1997 23/10/1997 24/10/1997 27/10/1997 28/10/1997 29/10/1997 30/10/1997 31/10/1997 11/03/1997 11/04/1997 11/05/1997 11/06/1997 11/07/1997 11/10/1997 11/11/1997 11/12/1997 13/11/1997 14/11/1997 17/11/1997 18/11/1997 19/11/1997 20/11/1997 21/11/1997 24/11/1997

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

I have 5,149 rows of dates where there are numbers in places of dates. I tried fixing the missing dates with this: ATTEMPT 1 BEFORE REVISION:

  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")

但是我遇到了以下错误:

But I am getting the following error:

+ }, 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

OK AS PER ADVICE I REVISED THE CODE ATTEMPT 2 AFTER REVISION

    > 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号,我再次尝试了

Today on 28th I tried again

> 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"

推荐答案

您不需要加载任何软件包,也不需要使用 Reduce ,因为我们在此处使用的功能是自然的向量化".

You need none of the packages you've loaded, nor do you need to use Reduce, as functions we're using here are naturally "vectorized".

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

Here's a sample of your data. (A good question includes data in an easily copied format such as this.)

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)对这种格式进行一次字面的二次遍历(此示例未使用,但是还是与您的工作相关?):

Not surprisingly, the second-half of the dates are not recognized given format="%d/%m/%Y". You mentioned the use of "%m/%d/%Y" in your question, so we can (1) do a literal second-pass for this format (un-utilized with this example, but still relevant for your work?):

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

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

where [is.na(dates)] only works on the un-converted elements.

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

(2) If we have more than one other format, you can always use a vector of them and loop over them. (For this, I'll start over, since this loop would replace/augment the first steps above.)

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" 的原点一起使用,您可以通过以下方式进行确认

This still leaves us with NAs for the integer-looking ones. For these you need to specify the origin= to be able to figure it out (as well as converting to an integer). R typically works with an origin of "1970-01-01", which you can confirm with

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

但是您的日期似乎起源于"1900-01-01" ,我认为这是Excel的默认日期存储方式(但这并不重要):

but it appears that your dates have an origin of "1900-01-01", I think that's Excel's default storage of dates (but it doesn't matter here):

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

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

(I'm assuming that your dates are from the same relative period of time.)

从这里:

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 个元素的索引相对有效,因为它仅可处理并替换尚未匹配的条目. as.Date ,它仍然会调用它,但是带有长度为0的参数,该函数可以有效地工作.我不认为添加条件条件 if(any(nas))... 会有所帮助,但是如果您需要其他可能更昂贵"的方法,则可以考虑.)

(Working on the indices of only NA elements is relatively efficient in that it only works on and replaces the not-yet-matched entries. If there is nothing left when it gets to another call to as.Date, it does still call it but with an argument of length 0, with which the function works rather efficiently. I don't think adding a conditional of if (any(nas)) ... would help, but if there are further methods you need that might be more "expensive", you can consider it.)

这篇关于如何修复R中的损坏日期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆