将 Excel 数字日期转换为 R 日期,但在某些行中只有给定的年份,例如“2018”而不是“43465”
Convert Excel numeric dates to R dates, but in some rows there is only the year given, e.g. "2018" instead of "43465"
我读入了一个 Excel 文件,其中一列包含日期。在某些行中没有完整的日期,但只给出了年份,例如 2018 年。
我在 R 中得到的是
> df$date
[1] NA NA 43465 43465 43465 43465 2018 NA 43465 43465 43465 43465
我想将这些行转换为完整日期的日期格式,即在我的示例中只有带有 43465
的行并保持其他行不变,即 NA
应该保持 NA
和 2018
应该保持 2018
.
我知道我可以按如下方式转换 Excel 日期 as.Date(df$date, origin="1899-12-30")
但是以下两个想法给我错误的输出
> as.Date(df$date, origin="1899-12-30")
[1] NA NA "2018-12-31" "2018-12-31" "2018-12-31" "2018-12-31" "1905-07-10" NA "2018-12-31" "2018-12-31" "2018-12-31"
[12] "2018-12-31"
当然"1905-07-10"
不是我所期望的
> ifelse(df$date == 2018, 2018, as.Date(df$date, origin="1899-12-30"))
[1] NA NA 17896 17896 17896 17896 2018 NA 17896 17896 17896 17896
这里错误的输出很明显。
一个向量不能有多个class。您可以在其中包含数字或日期 class。解决方法是使用最通用的字符 class。
x <- c(NA,NA,43465,43465,43465,43465,2018,NA,43465,43465, 43465, 43465)
ifelse(x == 2018, "2018", as.character(as.Date(x, origin="1899-12-30")))
# [1] NA NA "2018-12-31" "2018-12-31" "2018-12-31" "2018-12-31" "2018"
# [8] NA "2018-12-31" "2018-12-31" "2018-12-31" "2018-12-31"
然而,一个列表可以有多个 class,所以如果您可以将数据存储在列表中,我们可以使用 lapply
lapply(x, function(y)
if (y == 2018 | is.na(y)) y else as.Date(y, origin="1899-12-30"))
根据@Ronak 的回答,您可以使用正则表达式确定一个四位数字,然后用四个尾随零填充。
x <- c(NA,NA,43465,43465,43465,43465,2018,NA,43465,43465, 43465, 43465)
ifelse(grepl('^\d{4}$', x, perl = TRUE),
as.integer(paste0(x, '0000')),
as.integer(format(as.Date(x, origin='1899-12-30'), '%Y%m%d')))
[1] NA NA 20181231 20181231 20181231 20181231 20180000 NA 20181231 20181231 20181231 20181231
您会收到一些关于 NA
的警告消息,如果它困扰您,您可以添加额外的 ifelse
来控制 NA。这里我们使用逻辑 grep 测试来查看是否只有四个数字(一年),然后我们创建一个整数值。这允许您仍然使用 >
、<
、==
等数学运算符并保留所有信息。
您可以根据数据或用例将 paste0()
调用期间的 '0000'
更改为更合适的数字。
我读入了一个 Excel 文件,其中一列包含日期。在某些行中没有完整的日期,但只给出了年份,例如 2018 年。 我在 R 中得到的是
> df$date
[1] NA NA 43465 43465 43465 43465 2018 NA 43465 43465 43465 43465
我想将这些行转换为完整日期的日期格式,即在我的示例中只有带有 43465
的行并保持其他行不变,即 NA
应该保持 NA
和 2018
应该保持 2018
.
我知道我可以按如下方式转换 Excel 日期 as.Date(df$date, origin="1899-12-30")
但是以下两个想法给我错误的输出
> as.Date(df$date, origin="1899-12-30")
[1] NA NA "2018-12-31" "2018-12-31" "2018-12-31" "2018-12-31" "1905-07-10" NA "2018-12-31" "2018-12-31" "2018-12-31"
[12] "2018-12-31"
当然"1905-07-10"
不是我所期望的
> ifelse(df$date == 2018, 2018, as.Date(df$date, origin="1899-12-30"))
[1] NA NA 17896 17896 17896 17896 2018 NA 17896 17896 17896 17896
这里错误的输出很明显。
一个向量不能有多个class。您可以在其中包含数字或日期 class。解决方法是使用最通用的字符 class。
x <- c(NA,NA,43465,43465,43465,43465,2018,NA,43465,43465, 43465, 43465)
ifelse(x == 2018, "2018", as.character(as.Date(x, origin="1899-12-30")))
# [1] NA NA "2018-12-31" "2018-12-31" "2018-12-31" "2018-12-31" "2018"
# [8] NA "2018-12-31" "2018-12-31" "2018-12-31" "2018-12-31"
然而,一个列表可以有多个 class,所以如果您可以将数据存储在列表中,我们可以使用 lapply
lapply(x, function(y)
if (y == 2018 | is.na(y)) y else as.Date(y, origin="1899-12-30"))
根据@Ronak 的回答,您可以使用正则表达式确定一个四位数字,然后用四个尾随零填充。
x <- c(NA,NA,43465,43465,43465,43465,2018,NA,43465,43465, 43465, 43465)
ifelse(grepl('^\d{4}$', x, perl = TRUE),
as.integer(paste0(x, '0000')),
as.integer(format(as.Date(x, origin='1899-12-30'), '%Y%m%d')))
[1] NA NA 20181231 20181231 20181231 20181231 20180000 NA 20181231 20181231 20181231 20181231
您会收到一些关于 NA
的警告消息,如果它困扰您,您可以添加额外的 ifelse
来控制 NA。这里我们使用逻辑 grep 测试来查看是否只有四个数字(一年),然后我们创建一个整数值。这允许您仍然使用 >
、<
、==
等数学运算符并保留所有信息。
您可以根据数据或用例将 paste0()
调用期间的 '0000'
更改为更合适的数字。