为财政年度分配日期
Assigning Dates to Fiscal Year
我正在尝试编写一些代码来查看日期,然后将其分配给财政年度。我完全卡住了。
我有一个包含 POSIXct 格式日期的变量:
df$Date
#2015-05-01 CST
#2015-04-30 CST
#2014-09-01 CST
我需要做的是获取这些日期和 return 财政年度,从 5 月 1 日到 4 月 30 日。例如,2016 财政年度从 2015-05-01 到 2016 -04-30。结果看起来像这样:
df$Date df$FiscalYear
#2015-05-01 CST #FY2016
#2015-04-30 CST #FY2015
#2014-09-01 CST #FY2015
有什么简单的方法吗?
您可以将 seq
与 POSIXct 对象一起使用来生成 "cutpoints" 或跨越数据的年份的会计年度第一天的列表,然后使用 findInterval
来计算特定日期属于哪个区间:
> dates <- as.POSIXct( c('2015-05-01','2015-04-30','2014-09-01'))
> fy.tmp <- seq( as.POSIXct('2000-05-01'), length=25, by='year')
> fiscalYear <- (2001:2025)[ findInterval(dates,fy.tmp) ]
> fiscalYear
[1] 2016 2015 2015
如果您想要一个因子作为结果,您也可以使用 cut
函数而不是 findInterval
。
这里有一些备选方案。它们都是 return 数字年份,但如果您确实需要以 FY 开头的字符串,则使用 paste0("FY", result)
,其中 result
是以下任何结果。它们都支持向量输入,即输入 dates
可以是向量。
1) zoo::as.yearmon zoo 包有一个 "yearmon"
class 表示 year/months 作为年份 + 分数其中 fraction = 0 表示 1 月,1/12 表示 2 月,2/12 表示 3 月等等。
用这一行就可以了。它减去 4/12(因为 4 月是年底)并加 1(即加一年)。然后得到年份取整数部分:
library(zoo)
as.integer(as.yearmon(dates) - 4/12 + 1)
## [1] 2016 2015 2015
2) POSIXlt 这是一个不使用任何包的解决方案。将日期转换为 POSIXlt class。它的 mo
组件表示一月为 0,二月为 1,等等。所以如果我们是五月或更晚(mo
是 4 或更多)那么财政年度是下一个日历年,否则它是当前公历年。 POSIXlt 对象的 year
部分是自 1900 年以来的年数,因此如果我们在 5 月或更晚,则将年份加到 1900 加 1:
lt <- as.POSIXlt(dates)
lt$year + (lt$mo >= 4) + 1900
## [1] 2016 2015 2015
3) 格式 如果月份大于或等于 5,则将年份加到 1(否则加到零)。这也不使用包:
as.numeric(format(dates, "%Y")) + (format(dates, "%m") >= "05")
## [1] 2016 2015 2015
4) substr。我们可以使用 substr
提取年份,转换为数字并在提取的月份(也使用 substr
提取)为“05”或更大时加 1。同样没有使用包。
as.numeric(substr(dates, 1, 4)) + (substr(dates, 6, 7) >= "05")
## [1] 2016 2015 2015
5) read.table 这也没有使用包。
with(read.table(text = format(dates), sep = "-"), V1 + (V2 >= 5))
## [1] 2016 2015 2015
注:我们用这个作为输入dates
:
dates <- as.Date(c("2015-05-01", "2015-04-30", "2014-09-01"))
尝试修改这个:
Federal.FY <- function(x,firstMonth=10, # I've altered this line to follow the federal fiscal year, October
fy.prefix='FY',
quarter.prefix='Q',
sep='-',
level.range=c(min(x), max(x)) ) {if(level.range[1] > min(x) | level.range[2] < max(x)) {
warning(paste0('The range of x is greater than level.range. Values ',
'outside level.range will be returned as NA.'))}
quarterString <- function(d) {
year <- as.integer(format(d, format='%Y'))
month <- as.integer(format(d, format='%m'))
y <- ifelse(firstMonth > 1 & month >= firstMonth, year+1, year)
q <- cut( (month - firstMonth) %% 12, breaks=c(-Inf,2,5,8,Inf),
labels=paste0(quarter.prefix, 1:4))
return(paste0(fy.prefix, y, sep, q))}
vals <- quarterString(x)
levels <- unique(quarterString(seq(
as.Date(format(level.range[1], '%Y-%m-01')),
as.Date(format(level.range[2], '%Y-%m-28')), by='month')))
return(factor(vals, levels=levels, ordered=TRUE))}
d <- as.Date("2016-10-02")
Federal.FY(d)
##[1] FY2017-Q1
##Levels: FY2017-Q1
加入 G. Grothendieck 的精彩回应。随着 lubridate
:
year(dates) + (month(dates) >= 5)
我正在尝试编写一些代码来查看日期,然后将其分配给财政年度。我完全卡住了。
我有一个包含 POSIXct 格式日期的变量:
df$Date
#2015-05-01 CST
#2015-04-30 CST
#2014-09-01 CST
我需要做的是获取这些日期和 return 财政年度,从 5 月 1 日到 4 月 30 日。例如,2016 财政年度从 2015-05-01 到 2016 -04-30。结果看起来像这样:
df$Date df$FiscalYear
#2015-05-01 CST #FY2016
#2015-04-30 CST #FY2015
#2014-09-01 CST #FY2015
有什么简单的方法吗?
您可以将 seq
与 POSIXct 对象一起使用来生成 "cutpoints" 或跨越数据的年份的会计年度第一天的列表,然后使用 findInterval
来计算特定日期属于哪个区间:
> dates <- as.POSIXct( c('2015-05-01','2015-04-30','2014-09-01'))
> fy.tmp <- seq( as.POSIXct('2000-05-01'), length=25, by='year')
> fiscalYear <- (2001:2025)[ findInterval(dates,fy.tmp) ]
> fiscalYear
[1] 2016 2015 2015
如果您想要一个因子作为结果,您也可以使用 cut
函数而不是 findInterval
。
这里有一些备选方案。它们都是 return 数字年份,但如果您确实需要以 FY 开头的字符串,则使用 paste0("FY", result)
,其中 result
是以下任何结果。它们都支持向量输入,即输入 dates
可以是向量。
1) zoo::as.yearmon zoo 包有一个 "yearmon"
class 表示 year/months 作为年份 + 分数其中 fraction = 0 表示 1 月,1/12 表示 2 月,2/12 表示 3 月等等。
用这一行就可以了。它减去 4/12(因为 4 月是年底)并加 1(即加一年)。然后得到年份取整数部分:
library(zoo)
as.integer(as.yearmon(dates) - 4/12 + 1)
## [1] 2016 2015 2015
2) POSIXlt 这是一个不使用任何包的解决方案。将日期转换为 POSIXlt class。它的 mo
组件表示一月为 0,二月为 1,等等。所以如果我们是五月或更晚(mo
是 4 或更多)那么财政年度是下一个日历年,否则它是当前公历年。 POSIXlt 对象的 year
部分是自 1900 年以来的年数,因此如果我们在 5 月或更晚,则将年份加到 1900 加 1:
lt <- as.POSIXlt(dates)
lt$year + (lt$mo >= 4) + 1900
## [1] 2016 2015 2015
3) 格式 如果月份大于或等于 5,则将年份加到 1(否则加到零)。这也不使用包:
as.numeric(format(dates, "%Y")) + (format(dates, "%m") >= "05")
## [1] 2016 2015 2015
4) substr。我们可以使用 substr
提取年份,转换为数字并在提取的月份(也使用 substr
提取)为“05”或更大时加 1。同样没有使用包。
as.numeric(substr(dates, 1, 4)) + (substr(dates, 6, 7) >= "05")
## [1] 2016 2015 2015
5) read.table 这也没有使用包。
with(read.table(text = format(dates), sep = "-"), V1 + (V2 >= 5))
## [1] 2016 2015 2015
注:我们用这个作为输入dates
:
dates <- as.Date(c("2015-05-01", "2015-04-30", "2014-09-01"))
尝试修改这个:
Federal.FY <- function(x,firstMonth=10, # I've altered this line to follow the federal fiscal year, October
fy.prefix='FY',
quarter.prefix='Q',
sep='-',
level.range=c(min(x), max(x)) ) {if(level.range[1] > min(x) | level.range[2] < max(x)) {
warning(paste0('The range of x is greater than level.range. Values ',
'outside level.range will be returned as NA.'))}
quarterString <- function(d) {
year <- as.integer(format(d, format='%Y'))
month <- as.integer(format(d, format='%m'))
y <- ifelse(firstMonth > 1 & month >= firstMonth, year+1, year)
q <- cut( (month - firstMonth) %% 12, breaks=c(-Inf,2,5,8,Inf),
labels=paste0(quarter.prefix, 1:4))
return(paste0(fy.prefix, y, sep, q))}
vals <- quarterString(x)
levels <- unique(quarterString(seq(
as.Date(format(level.range[1], '%Y-%m-01')),
as.Date(format(level.range[2], '%Y-%m-28')), by='month')))
return(factor(vals, levels=levels, ordered=TRUE))}
d <- as.Date("2016-10-02")
Federal.FY(d)
##[1] FY2017-Q1
##Levels: FY2017-Q1
加入 G. Grothendieck 的精彩回应。随着 lubridate
:
year(dates) + (month(dates) >= 5)