Reputation: 113
How do I merge datasets where the key is on the column of one dataset and row of another in R?
Example data:
group = c("a", "b", "c", "c")
id1 = c(1, 0, 0, 0)
id2 = c(0, 1, 0, 1)
id3 = c(0, 0, 1, 0)
df1 = data.frame(group,id1, id2, id3)
df1
id = c("id1", "id2", "id3")
iv1 = c(2, 3, 3)
iv2 = c(3, 2, 3)
df2 = data.frame(id, iv1, iv2)
df2
I like to merge these two datasets by ids. I can do it via ifelse:
df1$iv1 = ifelse(df1$id1 == 1, 2, 3)
df1$iv2 = ifelse(df1$id2 == 1, 2, 3)
with the result:
group id1 id2 id3 iv1 iv2
1 a 1 0 0 2 3
2 b 0 1 0 3 2
3 c 0 0 1 3 3
4 c 0 1 0 3 2
The ifelse way would be tedious if say, I have 1000 variables to merge. Is there a more efficient way to merge datasets like these?
Upvotes: 1
Views: 94
Reputation: 3377
Both Pierre and Istrel's answers are good. For this and more complex manipulations, you could also use Hadley Wickham's popular tidyr
package:
install.packages('tidyr', repos='http://cran.rstudio.org')
library(tidyr)
g1 <- gather(df1, idx, id_val, -group) # colnames are in 'idx'; 12 rows total
g1 <- g1[g1$id_val==1, ] # drop rows with id_val == 0
g2 <- merge(g1, df2, by.x='idx', by.y='id')
g3 <- spread(g2, idx, id_val) # pivot the 'idx' column back out
g3
# group iv1 iv2 id1 id2 id3
# 1 a 2 3 1 NA NA
# 2 b 3 2 NA 1 NA
# 3 c 3 2 NA 1 NA
# 4 c 3 3 NA NA 1
g3[is.na(g3)] <- 0
g3
# group iv1 iv2 id1 id2 id3
# 1 a 2 3 1 0 0
# 2 b 3 2 0 1 0
# 3 c 3 2 0 1 0
# 4 c 3 3 0 0 1
Upvotes: 0
Reputation: 2588
Pierre Lafortune have already given a good answer. Still I will post my solution:
ids <- colnames(df1[, 2:4])
ids <- apply(df1[, 2:4], 1, function(x) return(ids[as.logical(x)]))
df1$id <- ids
new_df <- merge(df1, df2, by="id", all.x = TRUE, sort=FALSE)
> new_df
id group id1 id2 id3 iv1 iv2
1 id1 a 1 0 0 2 3
2 id2 b 0 1 0 3 2
3 id2 c 0 1 0 3 2
4 id3 c 0 0 1 3 3
Upvotes: 0
Reputation: 28461
We can use the fact that the column order of the first matches the row order of the second.
df1[c("iv1", "iv2")] <- df2[max.col(df1[-1]),-1]
# group id1 id2 id3 iv1 iv2
# 1 a 1 0 0 2 3
# 2 b 0 1 0 3 2
# 3 c 0 0 1 3 3
# 4 c 0 1 0 3 2
Upvotes: 4