Reputation: 133
Suppose I have a data frame with several lines that look like:
User Lab Score
A 1 5
A 2 6
A 4 7
B 1 3
B 3 4
C 2 5
Then, for lab 1, I want to divide the score by 5, for lab 2, I want to divide the score by 8, for lab 3, I want to divide the score by 7, and for lab 4 I want to divide the score by 9. How would I go about doing that?
Upvotes: 3
Views: 18714
Reputation: 121568
Here a clean and generalisable solution using merge
.
dat1 <- data.frame(Lab=c(1,2,3,4),
coef = c(1/5,1/8,1/7,1/9))
dt.m <- merge(dat,dat1,all.x=TRUE)
dt.m$coef[is.na(dt.m $coef)] <- 1 ## default value
dtt <- transform(dt.m,newScore=Score*coef)
Lab User Score coef newScore
1 1 A 5 0.2000000 1.0000000
2 1 B 3 0.2000000 0.6000000
3 2 A 6 0.1250000 0.7500000
4 2 C 5 0.1250000 0.6250000
5 3 B 4 0.1428571 0.5714286
6 4 A 7 0.1111111 0.7777778
EDIT If you want to get the same order , structure as the original data :
dtt[order(dtt$User),c('User','Lab','Score','newScore')]
User Lab Score newScore
1 A 1 5 1.0000000
3 A 2 6 0.7500000
6 A 4 7 0.7777778
2 B 1 3 0.6000000
5 B 3 4 0.5714286
4 C 2 5 0.6250000
Upvotes: 2
Reputation: 193507
This might be pretty unorthodox, but could also be easier to read than a lot of ifelse
s. factor
your "Lab" value, specify the divisor as the labels
, and divide as normal. Assuming the data.frame
is called "mydf":
within(mydf, {
temp <- as.numeric(as.character(factor(Lab, levels=c(1, 2, 3, 4),
labels=c(5, 8, 7, 9))))
Score <- Score/temp
rm(temp)
})
# User Lab Score
# 1 A 1 1.0000000
# 2 A 2 0.7500000
# 3 A 4 0.7777778
# 4 B 1 0.6000000
# 5 B 3 0.5714286
# 6 C 2 0.6250000
Upvotes: 0
Reputation: 57686
For data transformation tasks like this, use ifelse
, which is a vectorised form of selecting from different results based on a condition.
df$Score <- with(df, ifelse(Lab == 1, Score/5,
ifelse(Lab == 2, Score/8,
ifelse(Lab == 3, Score/7, Score/9))))
(This assumes you only have 4 Labs.)
Upvotes: 12