Если ваши данные «большого размера», это решение не будет для вас: декартово соединение взорвется за пределы того, что «стандартный» компьютер допустит в отношении памяти.
Если, однако, вашданные достаточно малы (очень относительный термин), тогда вы можете выполнить cartesian-join (также известный как полное или полное внешнее объединение) и отфильтровать результаты.(Это решение является реализацией одного раздела из https://www.mango -solutions.com / blog / in -ween-a-rock-and-a-conditional-join . Существуют и другие разделы, в которых обсуждается SQL иfuzzyjoin
, оба достойных кандидата.)
Три диалекта, в зависимости от ваших предпочтений.
Base R
a <- merge(d2, d1, all.x=T)
a <- transform(a, Final = ifelse(Low <= Final & Final <= High, Final, NA))
a[!duplicated(a),]
# Criteria Order Final Low High
# 1 a 1 NA 0 10
# 2 a 1 13 11 20
# 3 a 1 NA 21 30
# 4 a 1 8 0 10
# 5 a 1 NA 11 20
# 7 a 2 NA 5 22
# 8 a 2 2 0 4
# 9 b 2 12 0 18
У него есть дополнительный ряд, пытающийся работать элегантно ...
dplyr
library(dplyr)
full_join(d1, d2) %>%
mutate(Final = if_else(between(Final, Low, High), Final, NA_integer_)) %>%
group_by(Criteria, Order, Low, High) %>%
summarise(Final = coalesce(Final)[1]) %>%
ungroup()
# Joining, by = c("Criteria", "Order")
# # A tibble: 8 x 5
# Criteria Order Low High Final
# <chr> <int> <int> <int> <int>
# 1 a 1 0 10 NA
# 2 a 1 11 20 13
# 3 a 1 21 30 NA
# 4 a 2 0 4 2
# 5 a 2 5 22 NA
# 6 b 1 0 13 NA
# 7 b 1 14 32 NA
# 8 b 2 0 18 12
data.table
library(data.table)
as.data.table(d2)[d1, on = .(Final > Low, Final < High, Criteria, Order),
.(Criteria, Order, Low, High, x.Final)]
# Criteria Order Low High x.Final
# 1: a 1 0 10 8
# 2: a 1 11 20 13
# 3: a 1 21 30 NA
# 4: b 1 0 13 NA
# 5: b 1 14 32 NA
# 6: a 2 5 22 NA
# 7: a 2 0 4 2
# 8: b 2 0 18 12
(Существует также решение, использующее data.table::foverlaps
, которое может быть быстрее или более экономным для памяти. Прочитайте ссылку, это очень полезно.)
Данные:
d1 <- structure(list(Criteria = c("a", "a", "a", "b", "b", "a", "a",
"b"), Order = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L), Low = c(0L,
11L, 21L, 0L, 14L, 5L, 0L, 0L), High = c(10L, 20L, 30L, 13L,
32L, 22L, 4L, 18L)), class = "data.frame", row.names = c("1",
"2", "3", "4", "5", "6", "7", "8"))
d2 <- structure(list(Criteria = c("a", "b", "a", "a"), Order = c(1L,
2L, 1L, 2L), Final = c(13L, 12L, 8L, 2L)), class = "data.frame", row.names = c("1",
"2", "3", "4"))