按最接近的日期连接两个数据帧,无需在R中进行检查

按最接近的日期连接两个数据帧,无需在R中进行检查,r,data.table,tidyverse,R,Data.table,Tidyverse,我有两个不同长度的数据帧。两个数据框都包含日期。我想加入最近的日期列,而不必经过。例如,如果“2019-01-05”是日期,两个选项是“2019-01-06”和“2019-01-02”,则它将与“2019-01-02”合并。我尝试使用data.table包中的roll“inf”,但没有得到预期的结果。下面是我想按日期加入的两个玩具数据框 我还想按股票代码列对join进行分组。在tidyverse中,代码类似于: df1 %>% group_by(ticker) %>% inner_j

我有两个不同长度的数据帧。两个数据框都包含日期。我想加入最近的日期列,而不必经过。例如,如果“2019-01-05”是日期,两个选项是“2019-01-06”和“2019-01-02”,则它将与“2019-01-02”合并。我尝试使用data.table包中的roll“inf”,但没有得到预期的结果。下面是我想按日期加入的两个玩具数据框

我还想按股票代码列对join进行分组。在tidyverse中,代码类似于:

df1 %>% group_by(ticker) %>% inner_join(df2, by = "Date") #but choose the closest date without going over.


df1 = data.frame(ticker = c("AAPL", "AAPL", "MSFT", "MSFT"), date = c("2019-01-06", "2019-02-06", "2019-01-06", "2019-05-02"))

df2 = data.frame(ticker = c("AAPL", "AAPL", "AAPL", "MSFT", "MSFT", "MSFT"), date = c("2019-01-03", "2019-01-07" , "2019-02-06", "2019-01-05", "2019-01-07", "2019-05-02"), randomVar = rnorm(6))

print(df1)
 ticker       date
1   AAPL 2019-01-06
2   AAPL 2019-02-06
3   MSFT 2019-01-06
4   MSFT 2019-05-02


print(df2)
 ticker       date  randomVar
1   AAPL 2019-01-03 -0.5321493
2   AAPL 2019-01-07 -0.7909461
3   AAPL 2019-02-06  0.2121993
4   MSFT 2019-01-05  1.2336315
5   MSFT 2019-01-07 -0.2729354
6   MSFT 2019-05-02 -0.5349596
我想创建df3,它是df1和df2之间的连接。日期键列只能是df1日期列中的那些

在这种情况下,我们的新df3应该与此完全相同

 print(df3)

 ticker       date   randomVar
1   AAPL 2019-01-06  -0.5321493
2   AAPL 2019-02-06   0.2121993
3   MSFT 2019-01-06   1.2336315
4   MSFT 2019-05-02   -0.5349596

这可以在SQL中完成,使用默认的SQLite后端,在ticker上使用left join,在df2日期小于或等于df1日期,然后在df1上分组,并从df2中获取加入到df1的最大日期

library(sqldf)
sqldf("select df1.*, max(df2.date), df2.randomVar from df1 
  left join df2 on df1.ticker = df2.ticker and df1.date >= df2.date
  group by df1.rowid
  order by df1.rowid")[-3]
给予:

  ticker       date  randomVar
1   AAPL 2019-01-06 -0.5321493
2   AAPL 2019-02-06  0.2121993
3   MSFT 2019-01-06  1.2336315
4   MSFT 2019-05-02 -0.5349596
注 可复制形式的输入:

Lines1 <- "ticker       date
1   AAPL 2019-01-06
2   AAPL 2019-02-06
3   MSFT 2019-01-06
4   MSFT 2019-05-02"


Lines2 <- "ticker       date  randomVar
1   AAPL 2019-01-03 -0.5321493
2   AAPL 2019-01-07 -0.7909461
3   AAPL 2019-02-06  0.2121993
4   MSFT 2019-01-05  1.2336315
5   MSFT 2019-01-07 -0.2729354
6   MSFT 2019-05-02 -0.5349596"

df1 <- read.table(text = Lines1, as.is = TRUE)
df2 <- read.table(text = Lines2, as.is = TRUE)

Lines1这可以在SQL中完成,使用默认的SQLite后端,在ticker上使用左连接,在df2日期小于或等于df1日期,然后在df1上分组,并从df2中获取连接到df1的最大日期

library(sqldf)
sqldf("select df1.*, max(df2.date), df2.randomVar from df1 
  left join df2 on df1.ticker = df2.ticker and df1.date >= df2.date
  group by df1.rowid
  order by df1.rowid")[-3]
给予:

  ticker       date  randomVar
1   AAPL 2019-01-06 -0.5321493
2   AAPL 2019-02-06  0.2121993
3   MSFT 2019-01-06  1.2336315
4   MSFT 2019-05-02 -0.5349596
注 可复制形式的输入:

Lines1 <- "ticker       date
1   AAPL 2019-01-06
2   AAPL 2019-02-06
3   MSFT 2019-01-06
4   MSFT 2019-05-02"


Lines2 <- "ticker       date  randomVar
1   AAPL 2019-01-03 -0.5321493
2   AAPL 2019-01-07 -0.7909461
3   AAPL 2019-02-06  0.2121993
4   MSFT 2019-01-05  1.2336315
5   MSFT 2019-01-07 -0.2729354
6   MSFT 2019-05-02 -0.5349596"

df1 <- read.table(text = Lines1, as.is = TRUE)
df2 <- read.table(text = Lines2, as.is = TRUE)

Lines1已经有一个可接受的答案,但是由于存在
data.table
标签,这里有一个
data.table
解决方案:

#convert sample data to data.table
setDT(df1)
setDT(df2)
#convert dates to 'real' dates
df1[, date := as.IDate(date) ]
df2[, date := as.IDate(date) ]
#update df1 by reference with a rolling join
df1[, randomVar := df2[ df1, x.randomVar, on = .(ticker, date), roll = Inf ] ]

#    ticker       date  randomVar
# 1:   AAPL 2019-01-06 -0.5321493
# 2:   AAPL 2019-02-06  0.2121993
# 3:   MSFT 2019-01-06  1.2336315
# 4:   MSFT 2019-05-02 -0.5349596

已经有一个可接受的答案,但由于存在
data.table
标记,因此这里有一个
data.table
解决方案:

#convert sample data to data.table
setDT(df1)
setDT(df2)
#convert dates to 'real' dates
df1[, date := as.IDate(date) ]
df2[, date := as.IDate(date) ]
#update df1 by reference with a rolling join
df1[, randomVar := df2[ df1, x.randomVar, on = .(ticker, date), roll = Inf ] ]

#    ticker       date  randomVar
# 1:   AAPL 2019-01-06 -0.5321493
# 2:   AAPL 2019-02-06  0.2121993
# 3:   MSFT 2019-01-06  1.2336315
# 4:   MSFT 2019-05-02 -0.5349596

请参阅
数据表中的“滚动联接”。教程。
fuzzyjoin
我认为也有助于此-链接请参阅
data.table
包中的“滚动连接”。教程。
fuzzyjoin
我认为也能帮上忙-link Hey@G.Grothendiek,这很有效,速度也很快!为什么这是我第一次看到sqldf包?通常,数据转换在dplyr或data.table中完成。我应该仔细看看这个软件包吗?我相信它被广泛使用。如果你用谷歌搜索R sqldf,它的点击率为54000。嘿@G.Grothendiek,这很有效,而且非常快!为什么这是我第一次看到sqldf包?通常,数据转换在dplyr或data.table中完成。我应该仔细看看这个软件包吗?我相信它被广泛使用。如果你用谷歌搜索rsqldf,它会有54000次点击。