【问题标题】:Date sequence in R spanning B.C.E. to A.DR 中跨越 B.C.E. 的日期序列到公元
【发布时间】:2013-02-19 20:40:02
【问题描述】:

我想生成公元前 10,000 年的日期序列。到现在。这对于 0 CE(或 A.D.)来说很容易:

ADtoNow <- seq.Date(from = as.Date("0/1/1"), to = Sys.Date(), by = "day")

但我对如何在 0 AD 之前生成日期感到困惑。显然,我可以在现在之前做几年,但如果能够将某些东西绘制为 BCE 和 AD,那就太好了。

【问题讨论】:

  • 鉴于?as.Date 说,“注意:公元 1 年(又称公元 1 年)之前的几年可能无法正确处理。”我认为你不会有太多的运气。
  • 仅供参考,中世纪的僧侣数学不好,将“公元前 1 年”紧接在“公元 1 年”之前,中间没有零年。所以当你读到朱利叶斯凯撒在公元前 44 年被暗杀时,他们实际上意味着他在任何理性系统中都在 -43 年被杀。 ...对不起,我没有帮助解决实际问题。
  • 只是为了不让任何人对@criticalfix 感到困惑。那是在公历系统中。天文和 ISO 系统确实包含第 0 年。这个问题的发布者从未指定使用哪个日历系统,因此该区域只有模棱两可。不同的日历库以不同的方式处理公历中的第 0 年 - 请务必检查您的日历库的工作方式以避免 1-off 错误。

标签: r date


【解决方案1】:

为了扩展 Ricardo 的建议,这里有一些关于工作原理的测试。或者不要为此工作。

我将用粗体字重复约书亚从?as.Date 中提取的警告,以供未来的搜索者使用:

“注意:1CE(又名 1AD)之前的年份可能无法正确处理。”

as.integer(as.Date("0/1/1"))
[1] -719528

as.integer(seq(as.Date("0/1/1"),length=2,by="-10000 years"))
[1]  -719528 -4371953

seq(as.Date(-4371953,origin="1970-01-01"),Sys.Date(),by="1000 years")
# nonsense
 [1] "0000-01-01" "'000-01-01" "(000-01-01" ")000-01-01" "*000-01-01"
 [6] "+000-01-01" ",000-01-01" "-000-01-01" ".000-01-01" "/000-01-01"
[11] "0000-01-01" "1000-01-01" "2000-01-01"

> as.integer(seq(as.Date(-4371953,origin="1970-01-01"),Sys.Date(),by="1000 years"))
# also possibly nonsense
 [1] -4371953 -4006710 -3641468 -3276225 -2910983 -2545740 -2180498 -1815255
 [9] -1450013 -1084770  -719528  -354285    10957

虽然这似乎在某种程度上适用于绘图:

yrs1000 <- seq(as.Date(-4371953,origin="1970-01-01"),Sys.Date(),by="1000 years")
plot(yrs1000,rep(1,length(yrs1000)),axes=FALSE,ann=FALSE)
box()
axis(2)
axis(1,at=yrs1000,labels=c(paste(seq(10000,1000,by=-1000),"BC",sep=""),"0AD","1000AD","2000AD"))
title(xlab="Year",ylab="Value")

【讨论】:

    【解决方案2】:

    自从提出这个问题以来已经过去了很长时间。随之而来的是一个新的 R 包,gregorian,它可以在 as_gregorian 方法中处理 BCE 时间值。

    这是一个分段构建日期列表的示例,该日期范围从公元前 -10000 年到当前年份。

    library(lubridate)
    library(gregorian)
    
    # Container for the dates
    dates <- c()
    starting_year <- year(now())
    # Add the CE dates to the list
    for (year in starting_year:0){
      date <- sprintf("%s-%s-%s", year, "1", "1")
      dates <- c(dates, gregorian::as_gregorian(date))
    }
    
    starting_year <- "-10000"
    # Add the BCE dates to the list
    for (year in starting_year:0){
    start_date <- gregorian::as_gregorian("-10000-1-1")
    date <- sprintf("%s-%s-%s", year, "1", "1")
    dates <- c(dates, gregorian::as_gregorian(date))
    }
    

    如何使用列表由你决定,只要知道日期对象的相关属性是year 和bce。例如,您可以遍历日期列表、解析年份并确定它是否为 BCE。

    > gregorian_date <- gregorian::as_gregorian("-10000-1-1")
    > gregorian_date$bce
    [1] TRUE
    > gregorian_date$year
    [1] 10001
    

    关于 0AD 的注释

    gregorian 包假定当您指的是第 0 年时,您实际上是在谈论第 1 年(如下所示)。我个人认为应该抛出异常,但这是映射用户需要牢记的。

    > gregorian::as_gregorian("0-1-1")
    [1] "Monday January 1, 1 CE"
    

    这也是 BCE 的情况

    > gregorian::as_gregorian("-0-1-1")
    [1] "Saturday January 1, 1 BCE"
    

    【讨论】:

    • 你能举个例子吗?
    【解决方案3】:

    正如@JoshuaUlrich 评论的那样,简短的回答是否定的。

    但是,您可以将年份拼接成单独的列,然后转换为整数。这对你有用吗?

    【讨论】:

      【解决方案4】:

      包lubridate 似乎可以处理“负”年份,尽管它确实创建了一个年份0,从上面的 cmets 看来这似乎是不准确的。试试:

      library(lubridate)
      
      start <- -10000
      
      stop <- 2013
      
      myrange <- NULL
      
      for (x in start:stop) {
      
           myrange <- c(myrange,ymd(paste0(x,'-01-01')))
      }
      

      【讨论】:

      • 不知道lubridate,我只能猜测它在某个阶段仍然使用内部R Date 对象。在这种情况下,乔希的警告可能仍然适用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-14
      相关资源
      最近更新 更多