If I understand correctly, the OP has requested to try a match of a
with x1
first, then - if failed - to try to match a
with x2
. So any match of a
with x1
should take precedence over a match of a
with x2
.
Unfortunately, the sample data set provided by the OP does not include a use case to prove this. Therefore, I have modified the sample dataset accordingly (see Data section).
The approach suggested here is to reshape df2
from wide to long format (likewise to MrFlick's answer) but to use a data.table
join with parameter mult = "first"
.
The columns of df2
to be considered as key columns and the precedence can be controlled by the measure.vars
parameter to melt()
. After reshaping, melt()
arranges the rows in the column order given in measure.vars
:
library(data.table)
# define cols of df2 to use as key in order of
key_cols <- c("x1", "x2")
# reshape df2 from wide to long format
long <- melt(setDT(df2), measure.vars = key_cols, value.name = "a")
# join long with df1, pick first matches
result <- long[setDT(df1), on = "a", mult = "first"]
# clean up
setcolorder(result, names(df1))
result[, variable := NULL]
result
a b c x3
1: 5 T F w
2: 1 T T t
3: 7 T F g
4: 3 F F t
5: 0 F F <NA>
Please, note that the original row order of df1
has been preserved.
Also, note that the code works for an arbitrary number of key columns. The precedence of key columns can be easily changed. E.g., if the order is reversed, i.e., key_cols <- c("x2", "x1")
matches of a
with x2
will be picked first.
Data
Enhanced sample datasets:
df1
has an additional row with no match in df2
.
df1 <- data.frame(a=c(5,1,7,3,0),
b=c("T","T","T","F","F"),
c=c("F","T","F","F","F"))
df1
a b c
1: 5 T F
2: 1 T T
3: 7 T F
4: 3 F F
5: 0 F F
df2
has an additional row to prove that a match in x1
takes precedence over a match in x2
. The value 5
appears twice: In row 2 of column x1
and in row 5 of column x2
.
df2 <- data.frame(x1=c(4,5,3,9,6),
x2=c(7,8,1,2,5),
x3=c("g","w","t","o","n"))
df2
x1 x2 x3
1: 4 7 g
2: 5 8 w
3: 3 1 t
4: 9 2 o
5: 6 5 n