Reputation: 163
My real goal here is to use the numeric value for a month in table 1 (i.e. January = 01, ... December =12; years are present as a separate column) and find a value in table 2 where the value returned is from one month earlier. The problem I do not know how to deal with is when the month from table 1 is January (i.e. 2014-01), how would I return the value from table 2 related to December 2013 (i.e. 2013-12)?
I'm thinking that there is a package that has a process to decrement the date/month accounting for the beginning of the year condition I describe above. I do not have an issue converting the month and year columns into actual dates to accomplish this task.
year1 <- c(2013, 2013, 2014)
year2 <- c(2013, 2013, 2014)
month1 <- c(04, 08, 01)
month2 <- c(03, 12, 08)
value1 <- c(4,6,10)
value2 <- c(6,3,8)
df1 <- data.frame(year1, month1, value1)
df2 <- data.frame(year2, month2, value2)
Given the date combination of 2014-01 from df1, the expected output from df2 would be value2 = 3 from date combination 2013-12.
Thanks in advance
Upvotes: 0
Views: 66
Reputation: 42544
I find it more convenient to work with Date
objects because it's easier to add/subtract days or months (thanks to the lubridate
package). So, the idea is to use the first day of a month as date field instead of separate fields for year and month.
In addition, I prefer data.table
for data manipulation.
# initial data
df1 <- data.frame(year1=c(2013, 2013, 2014), month1=c(04, 08, 01), value1=c(4,6,10))
df2 <- data.frame(year2=c(2013, 2013, 2014), month2=c(03, 12, 08), value2=c(6,3,8))
library(data.table) # CRAN version 1.10.4 used
library(lubridate) # CRAN version 1.6.0 used
# coerce 1st data.frame to data.table,
# create date from year and month, skip year and month columns,
# create join date which is one month earlier
DT1 <- setDT(df1)[, .(date1 = as.Date(sprintf("%4i-%02i-01", year1, month1)),
value1)][, join.date := date1 - months(1L),]
# coerce 2nd data.frame to data.table,
# create date from year and month, skip year and month columns,
DT2 <- setDT(df2)[, .(date2 = as.Date(sprintf("%4i-%02i-01", year2, month2)),
value2)]
# right join: take all rows of DT1
DT2[DT1, on = c(date2 = "join.date")]
# date2 value2 date1 value1
#1: 2013-03-01 6 2013-04-01 4
#2: 2013-07-01 NA 2013-08-01 6
#3: 2013-12-01 3 2014-01-01 10
Upvotes: 1
Reputation: 12559
You can merge the dataframes (after some manipulation):
df1 <- data.frame(year1=c(2013, 2013, 2014), month1=c(04, 08, 01), value1=c(4,6,10))
df2 <- data.frame(year2=c(2013, 2013, 2014), month2=c(03, 12, 08), value2=c(6,3,8))
df1$month2 <- ifelse(df1$month1==1, 12, df1$month - 1)
df1$year2 <- ifelse(df1$month2==12, df1$year1-1, df1$year1)
merge(df1, df2, all.x=TRUE)
# month2 year2 year1 month1 value1 value2
# 1 3 2013 2013 4 4 6
# 2 7 2013 2013 8 6 NA
# 3 12 2013 2014 1 10 3
Upvotes: 0
Reputation: 56
It's a bit of a workaround, but here is an idea that might help: instead of only subtracting 1, subtract 2, use the modulo operator and then add 1 back.
i = 1:12
((i - 2) %% 12) + 1
[1] 12 1 2 3 4 5 6 7 8 9 10 11
Upvotes: 0