Можно использовать параметр, использующий data.table
rolling
соединение. Сначала df2
необходимо преобразовать в long-format
с помощью melt
, а затем объединить оба df1
и df2
.
library(data.table)
setDT(df1, key = c("MLID", "Position","Weight") )
df2 <- melt(df2, id.vars = c("MLID","Weight"), variable.name = "Position",
value.name = "Charge")
setDT(df2, key = c("MLID", "Position","Weight"))
df2[df1, roll = "nearest"]
# MLID Weight Position Charge
# 1: 992 0.580 N1 4.95
# 2: 992 0.125 NO 2.80
# 3: BJR 0.690 N1 4.95
Вариант № 2: Подход, основанный на tidyverse
, может быть следующим:
library(tidyverse)
df2 %>% gather(Position, Charge, -MLID, -Weight) %>%
right_join(df1, by=c("MLID", "Position")) %>%
filter(Weight.x <= Weight.y) %>%
group_by(MLID, Position) %>%
arrange(Weight.y-Weight.x) %>%
slice(1) %>%
select(MLID, Weight = Weight.y, Position, Charge)
# # A tibble: 3 x 4
# # Groups: MLID, Position [3]
# MLID Weight Position Charge
# <chr> <dbl> <chr> <dbl>
# 1 992 0.580 N1 4.95
# 2 992 0.125 NO 2.80
# 3 BJR 0.690 N1 4.95
Данные:
Данные OP's
немного изменены, чтобы включить аргумент stringsAsFactors = FALSE
в data.frame
, чтобы избежать ненужных предупреждений.
df1 <- data.frame(MLID=c('992','992','BJR'),
Position=c('NO','N1','N1'),
Weight=c(0.125,0.58,0.69), stringsAsFactors = FALSE)
df2 <- data.frame(MLID=c('992','992','992','992',
'BJR','BJR','BJR','BJR'),
Weight=c(0,0.251,0.501,1.001,
0,0.251,0.501,1.001),
NO=c(2.80,4.05,4.05,4.05,
4.05,4.05,4.05,4.05),
N1=c(3.47,4.73,4.95,5.15,
4.73,7.73,4.95,5.15), stringsAsFactors = FALSE )