与 R 中的条件合并
Merging with conditions in R
varA=c('2018-01-03', '2018-01-25','2018-01-15','2018-01-06')
varB=c('2018-01-02', '2018-01-05', '2018-01-13', '2018-01-21', '2018-01-26')
varC=c(201801,201802,201804,201809,201815)
df1=as.data.frame(varA)
df2=as.data.frame(cbind(varB,varC))
使用上面的代码获取数据帧:
varA
1 2018-01-03
2 2018-01-25
3 2018-01-15
4 2018-01-06
和
varB varC
1 2018-01-02 201801
2 2018-01-05 201802
3 2018-01-13 201804
4 2018-01-21 201809
5 2018-01-26 201815
据此我想将 df1 和 df2 合并在一起,但是如果 varA 作为日期介于 varB 的两个日期之间,它将从最早的日期开始获取 varC。我认为显示我期望的结果更容易:
varA varB varC
1 2018-01-03 2018-01-02 201801
2 2018-01-25 2018-01-21 201809
3 2018-01-15 2018-01-13 201804
4 2018-01-06 2018-01-05 201802
希望这很清楚。我不确定如何获得所需的输出。
Base R 中的 findInterval
在这里可能会有帮助。例如,
将 VarA 和 VarB 强制转换为 Date 对象并使用 findInterval
创建一个新列,其中包含 df2 中的行(即 VarB 索引),这些行与您为每个 VarA 指定的条件相匹配。
df1$row_match <- findInterval(as.Date(df1$varA), as.Date(df2$varB))
然后在
上创建新的对应列(df2 中的行)到 join/merge
df2$row_match <- seq_len(nrow(df2))
df3 <- merge(df1, df2, by = "row_match")
#> df3
# row_match varA varB varC
#1 1 2018-01-03 2018-01-02 201801
#2 2 2018-01-06 2018-01-05 201802
#3 3 2018-01-15 2018-01-13 201804
#4 4 2018-01-25 2018-01-21 201809
你可以试试
library(tidyverse)
map(df1$varA, function(x) df2[between(df2$varB, x, x),]) %>%
bind_rows() %>%
bind_cols(df1,.)
varA varB varC
1 2018-01-03 2018-01-02 201801
2 2018-01-25 2018-01-21 201809
3 2018-01-15 2018-01-13 201804
4 2018-01-06 2018-01-05 201802
想法是使用 tidyverse 函数 map
& between
找到区间,然后添加 df1
。
您可以使用 data.table
进行左连接:
varA <- c('2018-01-03', '2018-01-25','2018-01-15','2018-01-06')
varB <- c('2018-01-02', '2018-01-05', '2018-01-13', '2018-01-21', '2018-01-26')
varC <- c(201801,201802,201804,201809,201815)
library(lubridate)
dt1 <- data.table(varA = ymd(varA))
dt2 <- data.table(varA = ymd(varB), varB = ymd(varB), varC = varC)
setkey(dt1, varA)
setkey(dt2, varA)
dt2[dt1,, roll = T]
varA=c('2018-01-03', '2018-01-25','2018-01-15','2018-01-06')
varB=c('2018-01-02', '2018-01-05', '2018-01-13', '2018-01-21', '2018-01-26')
varC=c(201801,201802,201804,201809,201815)
df1=as.data.frame(varA)
df2=as.data.frame(cbind(varB,varC))
使用上面的代码获取数据帧:
varA
1 2018-01-03
2 2018-01-25
3 2018-01-15
4 2018-01-06
和
varB varC
1 2018-01-02 201801
2 2018-01-05 201802
3 2018-01-13 201804
4 2018-01-21 201809
5 2018-01-26 201815
据此我想将 df1 和 df2 合并在一起,但是如果 varA 作为日期介于 varB 的两个日期之间,它将从最早的日期开始获取 varC。我认为显示我期望的结果更容易:
varA varB varC
1 2018-01-03 2018-01-02 201801
2 2018-01-25 2018-01-21 201809
3 2018-01-15 2018-01-13 201804
4 2018-01-06 2018-01-05 201802
希望这很清楚。我不确定如何获得所需的输出。
findInterval
在这里可能会有帮助。例如,
将 VarA 和 VarB 强制转换为 Date 对象并使用 findInterval
创建一个新列,其中包含 df2 中的行(即 VarB 索引),这些行与您为每个 VarA 指定的条件相匹配。
df1$row_match <- findInterval(as.Date(df1$varA), as.Date(df2$varB))
然后在
上创建新的对应列(df2 中的行)到 join/mergedf2$row_match <- seq_len(nrow(df2))
df3 <- merge(df1, df2, by = "row_match")
#> df3
# row_match varA varB varC
#1 1 2018-01-03 2018-01-02 201801
#2 2 2018-01-06 2018-01-05 201802
#3 3 2018-01-15 2018-01-13 201804
#4 4 2018-01-25 2018-01-21 201809
你可以试试
library(tidyverse)
map(df1$varA, function(x) df2[between(df2$varB, x, x),]) %>%
bind_rows() %>%
bind_cols(df1,.)
varA varB varC
1 2018-01-03 2018-01-02 201801
2 2018-01-25 2018-01-21 201809
3 2018-01-15 2018-01-13 201804
4 2018-01-06 2018-01-05 201802
想法是使用 tidyverse 函数 map
& between
找到区间,然后添加 df1
。
您可以使用 data.table
进行左连接:
varA <- c('2018-01-03', '2018-01-25','2018-01-15','2018-01-06')
varB <- c('2018-01-02', '2018-01-05', '2018-01-13', '2018-01-21', '2018-01-26')
varC <- c(201801,201802,201804,201809,201815)
library(lubridate)
dt1 <- data.table(varA = ymd(varA))
dt2 <- data.table(varA = ymd(varB), varB = ymd(varB), varC = varC)
setkey(dt1, varA)
setkey(dt2, varA)
dt2[dt1,, roll = T]