as.Date 来自 'YYYY.mm' 格式

as.Date from 'YYYY.mm' format

我有一个数据框,其中日期存储为 double 例如,1993.09 1993.10 1993.11 1993.12

我想将其转换为日期格式 '%Y %m %d'(天总是 1)。

据我了解,as.Date() 需要字符串输入。但是,出于某种原因,当我将日期转换为字符串 sapply(dates, as.character) 后的零消失时,有效地将十月转换为一月,导致每年有两个一月。

dates
1993.07 1993.08 1993.09 1993.10 1993.11 1993.12
sapply(dates, as.character)
sub("[.]", " ", dates)
"1993 07" "1993 08" "1993 09" "1993 1"  "1993 11" "1993 12"

是否有更直接的方法来转换日期?或者我哪里搞砸了?

输出:

c(1993.01, 1993.02, 1993.03, 1993.04, 1993.05, 1993.06, 1993.07, 
1993.08, 1993.09, 1993.1, 1993.11, 1993.12)

使用 paste0 添加日期并从 ?strptime 中查找日期格式的值。如果你对双字符串格式有问题,你可以使用 formatC:

txtfield <- c(1993.01, 1993.02, 1993.03, 1993.04, 1993.05, 1993.06, 1993.07, 
  1993.08, 1993.09, 1993.1, 1993.11, 1993.12)

as.Date(paste0(formatC(txtfield, digits=2, format="f"),".01"), "%Y.%m.%d")

解释:

paste0paste 的 shorthand 版本,它不会在粘贴的元素之间插入空格。
formatC,digits 中指定小数点后的位数(在我们的例子中我们想要 2. format 告诉 R 使用哪个数字格式,在我们的例子中 "f" 给出了所需 xxx.xxx 格式的数字。
as.Date 转换为本机 R 日期格式,其中“%Y.%m.%d”指定完整年份(4 位数字)后跟一个点,然后是数字月份(2 位数字)后跟一个点,其次是数字日。

结果:

[1] "1993-01-01" "1993-02-01" "1993-03-01" "1993-04-01" "1993-05-01" "1993-06-01"
[7] "1993-07-01" "1993-08-01" "1993-09-01" "1993-10-01" "1993-11-01" "1993-12-01"

您需要对字符串进行一些调整。最明显的方法(对我*)是 "pad" 值的右侧带零。

* 这是一个很大的警告

dates <- c(1993.01, 1993.02, 1993.03, 1993.04, 1993.05, 1993.06, 1993.07, 
1993.08, 1993.09, 1993.10, 1993.11, 1993.12)

library(magrittr)
library(stringr)
dates %<>%
  str_pad(width = 7, side = "right", pad = "0") %>%
  paste0(".01") %>%
  as.Date(format = "%Y.%m.%d")

dates

你的问题是你有一些字符串,但看起来像一个数字,你在导入过程中没有处理这个问题。 R 不区分 1993.11993.10。两者是相同的号码。因此,as.character(1993.10) returns "1993.1"。您需要使用格式化函数来确保在句点之后得到两位数字,因为 as.Date "1993.1""1993.01" 是同一个月。

x <- c(1993.09, 1993.10, 1993.11, 1993.12)
as.Date(sprintf("%.2f.01", x), format = "%Y.%m.%d")
#[1] "1993-09-01" "1993-10-01" "1993-11-01" "1993-12-01"

当然,x应该作为字符导入。

如果你真的只是想把它转换成 "Date" class 使用一个月的第一天,那么 Roland 的解决方案似乎是最直接的,但还有一些其他的考虑因素,比如你是否想要使用月末或者您是否真的想首先使用日期来表示年月。

zoo 包有一个 "yearmon" class 可以直接表示年月而不用将它们转换为日期,还有 as.Date.yearmon 方法有一个 frac=如果您确实需要 "Date" class.

,则可以使用参数指定要转换为的月份的分数

首先,确保日期是字符串。问题中的输入显示 1993.10 作为输入之一,因此我们必须确保有尾随零。 (如果输入已经是尾随零的字符,那么这不是问题。我们在这里假设最坏的情况是数字,因此如果需要,我们需要将它们显式转换为尾随 0 的字符串。)现在使用 as.yearmon 格式为 "%Y.%m"。最后用as.Date.yearmon转换成"Date"class。

也许这种方法的最大优点是我们可以将结果留在 "yearmon" class 中(即省略 "as.Date" 部分,例如 as.yearmon(sprintf("%.2f", dates)) 或者如果日期已经是字符串,dates.ch,在 "1993.10" 的情况下尾随 0,然后只是 as.yearmon(dates.ch, "%Y.%m"),这确实代表了你拥有的更好的东西,因为这一天并不是真正有意义的开始时不存在。"yearmon" 可以按预期方式绘制和排序对象。

这里是 "Date" class 使用 "yearmon" 的转换:

library(zoo)

dates <- c(1993.07, 1993.08, 1993.09, 1993.1, 1993.11, 1993.12) # test input 


 as.Date(as.yearmon(sprintf("%.2f", dates), "%Y.%m")) # 1st of month
 ## [1] "1993-07-01" "1993-08-01" "1993-09-01" "1993-10-01" "1993-11-01" "1993-12-01"

 as.Date(as.yearmon(sprintf("%.2f", dates), "%Y.%m"), frac = 1) # last of month
 ## [1] "1993-07-31" "1993-08-31" "1993-09-30" "1993-10-31" "1993-11-30" "1993-12-31"

或者如果测试输入如下所示:

dates.ch <- c("1993.07", "1993.08", "1993.09", "1993.10", "1993.11", "1993.12") # input 

as.Date(as.yearmon(dates.ch, "%Y.%m"))

as.Date(as.yearmon(dates.ch, "%Y.%m"), frac = 1)