Floor a year to the decade in R

Monica Heddneck picture Monica Heddneck · Feb 12, 2016 · Viewed 9.2k times · Source

I would like to floor a set of dates to the nearest decade, e.g:

1922 --> 1920,  
2099 --> 2090,  

etc.

I was hoping I could do this in Lubridate, as in:

floor_date(1922, 'decade')

But I get:

Error in match.arg(unit) : 
  'arg' should be one of “second”, “minute”, “hour”, “day”, “week”, “month”, “year”

Is there any way to do this gracefully, perhaps avoiding a bunch of if-else statement to do the binning, and hopefully avoiding a bunch of cuts to do the grouping?

Answer

Eric Leschinski picture Eric Leschinski · Feb 24, 2018

Floor a Year in R to nearest decade:

Think of Modulus as a way to extract the rightmost digit and use it to subtract from the original year. 1998 - 8 = 1990

> 1992 - 1992 %% 10 
[1] 1990
> 1998 - 1998 %% 10
[1] 1990

Ceiling a Year in R to nearest decade:

Ceiling is exactly like floor, but add 10.

> 1998 - (1998 %% 10) + 10
[1] 2000
> 1992 - (1992 %% 10) + 10
[1] 2000

Round a Year in R to nearest decade:

Integer division converts your 1998 to 199.8, rounded to integer is 200, multiply that by 10 to get back to 2000.

> round(1992 / 10) * 10
[1] 1990
> round(1998 / 10) * 10
[1] 2000

Handy dandy copy pasta for those of you who don't like to think:

floor_decade    = function(value){ return(value - value %% 10) }
ceiling_decade  = function(value){ return(floor_decade(value)+10) }
round_to_decade = function(value){ return(round(value / 10) * 10) }
print(floor_decade(1992))
print(floor_decade(1998))
print(ceiling_decade(1992))
print(ceiling_decade(1998))
print(round_to_decade(1992))
print(round_to_decade(1998))

which prints:

# 1990
# 1990
# 2000
# 2000
# 1990
# 2000

Source: https://rextester.com/AZL32693

Another way to round to nearest decade: Neat trick with Rscript core function round such that the second argument digits can take a negative number. See: https://www.rdocumentation.org/packages/base/versions/3.6.1/topics/Round

round(1992, -1)    #prints 1990
round(1998, -1)    #prints 2000

Don't be shy on the duct tape with this dob, it's the only thing holding the unit together.