Reputation: 987
I have a data frame where I would like to match the Score values of ID to New.Score.
The ID 123
has score 5
in group 1, but in group 2 it has score 1
. And I only want to use the scores that appear within each group.
This is my df:
Group ID Score New.ID New.Score
1 123 5 456
1 456 1 789
1 789 0 123
2 555 1 999
2 123 1 123
2 999 0 555
And my desired output:
Group ID Score New.ID New.Score
1 123 5 456 1
1 456 1 789 0
1 789 0 123 5
2 555 1 999 0
2 123 1 123 1
2 999 0 555 1
I tried with ave
:
mtch <- function(x) {
dt[match(x,dt$ID),"Score"]
}
dt$New.Score <- ave(dt$New.ID, dt$Group, FUN = mtch)
But it gives me NA values.
Code for df creation:
Group <- as.factor(c(1, 1, 1, 2, 2, 2))
ID <- as.factor(c(123,456,789, 555, 123, 999))
Score <- c(5,1,0, 1,1,0)
dt <- data.frame(Group, ID, Score, New.ID)
Upvotes: 2
Views: 456
Reputation: 14360
You can use a similar approach as in my previous answer (Set values of column based on other column), but this time use an interaction
in the matching. Something like this:
dt$New.Score <- dt[match(interaction(dt$Group,dt$New.ID) ,
interaction(dt$Group,dt$ID)), "Score"]
# Group ID Score New.ID New.Score
# 1 1 123 5 456 1
# 2 1 456 1 789 0
# 3 1 789 0 123 5
# 4 2 555 1 999 0
# 5 2 123 1 123 1
# 6 2 999 0 555 1
Data:
Group <- as.factor(c(1, 1, 1, 2, 2, 2))
ID <- as.factor(c(123,456,789, 555, 123, 999))
Score <- c(5,1,0, 1,1,0)
New.ID <- as.factor(c(456, 789, 123, 999, 123, 555))
dt <- data.frame(Group, ID, Score, New.ID)
Upvotes: 1
Reputation: 887118
We can use data.table
. Convert the 'data.frame' to 'data.table' (setDT(dt)
), grouped by 'Group', match
the 'New.ID' with 'ID' to get the numeric index and use that to rearrange the 'Score' and assign (:=
) it to 'New.Score'
library(data.table)
setDT(dt)[, New.Score := Score[match(New.ID, ID)], Group]
dt
# Group ID Score New.ID New.Score
#1: 1 123 5 456 1
#2: 1 456 1 789 0
#3: 1 789 0 123 5
#4: 2 555 1 999 0
#5: 2 123 1 123 1
#6: 2 999 0 555 1
Upvotes: 2