【问题标题】:How can I fix corrupted dates in R?如何修复 R 中损坏的日期?
【发布时间】:2018-09-12 01:31:38
【问题描述】:

我有一个数据集如下:

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

35440 35471 35499 35591 35621 35652 35683 35713

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

35500 35531 35561 35592 35622 35714 35745 35775

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

此处应有的数据是(按要求复制) 19/9/1997 1997 年 9 月 22 日 1997 年 9 月 23 日 1997 年 9 月 24 日 1997 年 9 月 25 日 1997 年 9 月 26 日 1997 年 9 月 29 日 1997 年 9 月 30 日 10/01/1997 1997 年 10 月 2 日 10/03/1997 10/06/1997 10/07/1997 10/08/1997 10/09/1997 1997 年 10 月 10 日 1997 年 10 月 13 日 1997 年 10 月 14 日 1997 年 10 月 15 日 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 日 1997 年 10 月 30 日 1997 年 10 月 31 日 1997 年 11 月 3 日 1997 年 11 月 4 日 11/05/1997 1997 年 11 月 6 日 11/07/1997 1997 年 11 月 10 日 1997 年 11 月 11 日 1997 年 11 月 12 日 1997 年 11 月 13 日 1997 年 11 月 14 日 1997 年 11 月 17 日 1997 年 11 月 18 日 19/11/1997 1997 年 11 月 20 日 1997 年 11 月 21 日 1997 年 11 月 24 日

我有 5,149 行日期,其中日期位置有数字。我尝试使用以下方法修复丢失的日期: 修订前的尝试 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"

【问题讨论】:

  • 这个问题是关于“损坏的日期”还是关于'x' not found?由于我们没有您的数据,因此很难解决这方面的问题。也许您可以在调用Reduce 之前提供dput(head(x)) 的输出?
  • 您好,感谢您的回复。 X 是日期向量。就在代码之前,您将在顶部看到列出的日期。它们是一列中的行?如您所见,在 30/09/97 之后,下一行是 3559。这就是它们损坏的原因。日期信息是从数据流中收集的。您有几行日期格式,有些日期只是变成数字。我需要按顺序排列日期中的所有行。日期不是按时间顺序排列的。它们代表一周中的某些日子,然后代表不存在的某些日子。下周再过几天。
  • 请不要在您的问题中发布rm(list = ls()) 之类的代码。我们希望能够复制和运行您的代码,而不必担心它会破坏我们计算机上正在进行的工作。
  • @Gregor,有时我想知道我是否应该在 R 沙箱中尝试这样的代码......有没有一种简单的方法可以暂时将.GlobalEnv 移开?不是万无一失,但更接近...... :-)
  • 我知道这不是一个简单的方法...我有时会打开两个 RStudio 实例,一个用于工作,一个用于堆栈溢出成瘾。

标签: r date


【解决方案1】:

你不需要你已经加载的任何包,也不需要使用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          

这仍然给我们留下了NAs 用于整数外观。对于这些,您需要指定 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 元素的索引相对有效,因为它只处理和替换尚未匹配的条目。如果在再次调用as.Date 时没有任何剩余,它仍然调用它,但使用长度为 0 的参数,该函数可以相当有效地工作。我不认为添加条件 if (any(nas)) ... 会有所帮助,但如果您需要更多方法,可能会更“昂贵” ,你可以考虑。)

【讨论】:

  • R.Islam,我现在明白了,这对我来说很明显。 readxl::read_excel 返回一个 tibble,它与 data.frame 略有不同:当使用 [,1] 索引时,一个框架将(几乎)总是返回一个向量,一个 tibble 将总是返回一个(单列)框架。尝试mtcars[,1]tbl_df(mtcars)[,1]。在这种情况下,您需要查看您的对象以了解发生了什么,class(x) 可能会说data.frame,而as.Date 只接受向量。 (我再说一遍:可重现的数据样本dput(head(x)) 的输出对我们许多人来说都是显而易见的。)
  • 所以一个答案是用x&lt;-Dates[[1]]替换x&lt;-Dates[,1]
  • R.Islam,我不太确定根本问题是什么。是不是你的函数不知道怎么处理data.frame/tibble?还是您不知道如何使用Reduce(这是错误的功能,顺便说一句)将您的列转换为Date 类型?你还在 tibble 上使用 Date[,1] 吗?
  • 看,在您提供可重现的数据之前,我真的无能为力。我知道你你已经提供了它,但你没有。请提供dput(head(Dates)) 的输出(通过编辑您的问题并添加它),我会看看。
  • @R.Islam 这些 cmets 中的主要建议似乎是您应该发布可重现的样本数据。与dput()。所以它是可复制/可粘贴的,并反映了您的实际数据结构。 他至少要了 3 次。 如果我是 r2evans,我也会觉得很卡。如果您不知道如何提供可重现的数据,请see this FAQ on making reproducible examples in R。有一次您确实使用了dput,它只捕获整数样式日期"33274", "33302", "33394", "33424", "33455", "33486"。请找到一个有代表性的子集。
猜你喜欢
  • 1970-01-01
  • 2011-09-04
  • 1970-01-01
  • 2013-05-12
  • 2010-09-25
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 2011-01-19
相关资源
最近更新 更多