在 R 中用 round_date() 舍入日期
Rounding dates with round_date() in R
我尝试仅在 R 中将日期格式 yyyymmdd 转换为 yyyy。
在 中提出了一个非常有趣的答案,因为它设法使 R 理解将润滑包中的 8 位条目 (yyyymmdd) 转换为 4 位年份 (yyyy),这对我来说非常好.
在旧代码中我使用了 round_date()
:
date2<-c('01/01/2000','08/08/2000','16/03/2001','25/12/2000','29/02/2000')
name<-c('A','B','C','D','E')
df<-data.frame(date2,name)
df2 <- df %>%
mutate(date2 = dmy(date2)) %>%
mutate(year_date = round_date(date2,'year'))
df2
str(df2)
date2<date> name<chr> year_date <date>
2000-01-01 A 2000-01-01
2000-08-08 B 2001-01-01
2001-03-16 C 2001-01-01
2000-12-25 D 2001-01-01
2000-02-29 E 2000-01-01
但是当我发现例如日期 2000-08-08 被四舍五入到 2001-01-01 年而不是我预期的 2001-01-01 时,我的统计分析开始出现问题。
这对我来说是一个非常大的问题,因为属于 2005 年的信息已移至 2006 年,考虑到我的数据库中有 1400 多行。
我注意到年中之后(6 月之后)的日期会四舍五入到下一年,这很糟糕。
如何将 2000-08-08 日期四舍五入到 2000 而不是 2001?
这个(更简单,也只有 base R)操作不是你想要的吗?
> date2 <- c('01/01/2000','08/08/2000','16/03/2001','25/12/2000','29/02/2000')
> dd <- as.Date(date2, "%d/%m/%Y")
> yd <- format(dd, "%Y-01-01")
> dt <- as.Date(yd)
> D <- data.frame(date2=date2, date=dd, y=yd, d=dt)
> D
date2 date y d
1 01/01/2000 2000-01-01 2000-01-01 2000-01-01
2 08/08/2000 2000-08-08 2000-01-01 2000-01-01
3 16/03/2001 2001-03-16 2001-01-01 2001-01-01
4 25/12/2000 2000-12-25 2000-01-01 2000-01-01
5 29/02/2000 2000-02-29 2000-01-01 2000-01-01
>
本质上我们只是从(解析为日期)Date
对象中提取年份部分并附加 -01-01
.
编辑: Date
和 Datetime
对象也有 trunc()
操作。奇怪的是,截断年份仅适用于 Datetime
(有关更多信息,请参阅 trunc.Date
的帮助页面)所以这也适用:
> as.Date(trunc(as.POSIXlt(dd), "years"))
[1] "2000-01-01" "2000-01-01" "2001-01-01" "2000-01-01" "2000-01-01"
>
编辑 2: 我们可以在 data.frame
中使用最后一步更清洁/更简单的解决方案,其中三列用于 input 数据(作为字符),parse 数据作为适当的 Date
类型和所需的 truncated 年份数据——全部使用 base R没有进一步的依赖。当然,如果你想要你可以通过管道重写它并且lubridate
通过稍微慢一点的路径重写它以获得相同的结果(这只对“大”数据很重要)。
> date2 <- c('01/01/2000','08/08/2000','16/03/2001','25/12/2000','29/02/2000')
> pd <- as.Date(date2, "%d/%m/%Y")
> td <- as.Date(trunc(as.POSIXlt(pd), "years"))
> D <- data.frame(input = date2, parsed = pd, output = td)
> D
input parsed output
1 01/01/2000 2000-01-01 2000-01-01
2 08/08/2000 2000-08-08 2000-01-01
3 16/03/2001 2001-03-16 2001-01-01
4 25/12/2000 2000-12-25 2000-01-01
5 29/02/2000 2000-02-29 2000-01-01
>
对于真正的“生产”用途,您可能不需要 data.frame
并且不需要保留导致单行的中间结果:
> as.Date(trunc(as.POSIXlt( as.Date(date2, "%d/%m/%Y") ), "years"))
[1] "2000-01-01" "2000-01-01" "2001-01-01" "2000-01-01" "2000-01-01"
>
这可能是您可以获得的最紧凑、最高效的转换。
如果您只想要年份(而不是对应于一年的第一天的日期),您可以使用 lubridate::year()
.
df %>% mutate(across(date2,dmy),
year_date=year(date2))
如果您确实想要一年的第一天,那么 floor_date()
就可以了。
df %>% mutate(across(date2,dmy),
year_date=floor_date(date2,"year"))
或者如果您只需要截断的日期,您可以直接转到 mutate(year_date=floor_date(dmy(date2)))
在 base R 中,year()
将是 format(date2, "%Y")
,如@DirkEddelbuettel 的回答所示。
如果您查阅 round_date
帮助页面,您还会看到 floor_date
:
library("lubridate")
library("dplyr")
date2 <- c('01/01/2000','08/08/2000','16/03/2001','25/12/2000','29/02/2000')
name <- c('A','B','C','D','E')
df <- data.frame(date2,name)
df2 <- df %>%
mutate(date2 = dmy(date2)) %>%
mutate(year_date = floor_date(date2,'year'))
df2
我尝试仅在 R 中将日期格式 yyyymmdd 转换为 yyyy。
在
在旧代码中我使用了 round_date()
:
date2<-c('01/01/2000','08/08/2000','16/03/2001','25/12/2000','29/02/2000')
name<-c('A','B','C','D','E')
df<-data.frame(date2,name)
df2 <- df %>%
mutate(date2 = dmy(date2)) %>%
mutate(year_date = round_date(date2,'year'))
df2
str(df2)
date2<date> name<chr> year_date <date>
2000-01-01 A 2000-01-01
2000-08-08 B 2001-01-01
2001-03-16 C 2001-01-01
2000-12-25 D 2001-01-01
2000-02-29 E 2000-01-01
但是当我发现例如日期 2000-08-08 被四舍五入到 2001-01-01 年而不是我预期的 2001-01-01 时,我的统计分析开始出现问题。
这对我来说是一个非常大的问题,因为属于 2005 年的信息已移至 2006 年,考虑到我的数据库中有 1400 多行。
我注意到年中之后(6 月之后)的日期会四舍五入到下一年,这很糟糕。
如何将 2000-08-08 日期四舍五入到 2000 而不是 2001?
这个(更简单,也只有 base R)操作不是你想要的吗?
> date2 <- c('01/01/2000','08/08/2000','16/03/2001','25/12/2000','29/02/2000')
> dd <- as.Date(date2, "%d/%m/%Y")
> yd <- format(dd, "%Y-01-01")
> dt <- as.Date(yd)
> D <- data.frame(date2=date2, date=dd, y=yd, d=dt)
> D
date2 date y d
1 01/01/2000 2000-01-01 2000-01-01 2000-01-01
2 08/08/2000 2000-08-08 2000-01-01 2000-01-01
3 16/03/2001 2001-03-16 2001-01-01 2001-01-01
4 25/12/2000 2000-12-25 2000-01-01 2000-01-01
5 29/02/2000 2000-02-29 2000-01-01 2000-01-01
>
本质上我们只是从(解析为日期)Date
对象中提取年份部分并附加 -01-01
.
编辑: Date
和 Datetime
对象也有 trunc()
操作。奇怪的是,截断年份仅适用于 Datetime
(有关更多信息,请参阅 trunc.Date
的帮助页面)所以这也适用:
> as.Date(trunc(as.POSIXlt(dd), "years"))
[1] "2000-01-01" "2000-01-01" "2001-01-01" "2000-01-01" "2000-01-01"
>
编辑 2: 我们可以在 data.frame
中使用最后一步更清洁/更简单的解决方案,其中三列用于 input 数据(作为字符),parse 数据作为适当的 Date
类型和所需的 truncated 年份数据——全部使用 base R没有进一步的依赖。当然,如果你想要你可以通过管道重写它并且lubridate
通过稍微慢一点的路径重写它以获得相同的结果(这只对“大”数据很重要)。
> date2 <- c('01/01/2000','08/08/2000','16/03/2001','25/12/2000','29/02/2000')
> pd <- as.Date(date2, "%d/%m/%Y")
> td <- as.Date(trunc(as.POSIXlt(pd), "years"))
> D <- data.frame(input = date2, parsed = pd, output = td)
> D
input parsed output
1 01/01/2000 2000-01-01 2000-01-01
2 08/08/2000 2000-08-08 2000-01-01
3 16/03/2001 2001-03-16 2001-01-01
4 25/12/2000 2000-12-25 2000-01-01
5 29/02/2000 2000-02-29 2000-01-01
>
对于真正的“生产”用途,您可能不需要 data.frame
并且不需要保留导致单行的中间结果:
> as.Date(trunc(as.POSIXlt( as.Date(date2, "%d/%m/%Y") ), "years"))
[1] "2000-01-01" "2000-01-01" "2001-01-01" "2000-01-01" "2000-01-01"
>
这可能是您可以获得的最紧凑、最高效的转换。
如果您只想要年份(而不是对应于一年的第一天的日期),您可以使用 lubridate::year()
.
df %>% mutate(across(date2,dmy),
year_date=year(date2))
如果您确实想要一年的第一天,那么 floor_date()
就可以了。
df %>% mutate(across(date2,dmy),
year_date=floor_date(date2,"year"))
或者如果您只需要截断的日期,您可以直接转到 mutate(year_date=floor_date(dmy(date2)))
在 base R 中,year()
将是 format(date2, "%Y")
,如@DirkEddelbuettel 的回答所示。
如果您查阅 round_date
帮助页面,您还会看到 floor_date
:
library("lubridate")
library("dplyr")
date2 <- c('01/01/2000','08/08/2000','16/03/2001','25/12/2000','29/02/2000')
name <- c('A','B','C','D','E')
df <- data.frame(date2,name)
df2 <- df %>%
mutate(date2 = dmy(date2)) %>%
mutate(year_date = floor_date(date2,'year'))
df2