Reputation: 1141
I want to create a new column containing an number indexed from another column. The choice of column depends on the indexed number.
I've tried using if loops, but can't work out how to achieve this
testdata <- data.frame(sample=c("A01", "A02", "A03"),
mode=c(187, 189, 190),
control=c("A03",NA,NA),
mancontrol=c(NA, 191, 192))
expectedresults <- data.frame(sample=c("A01", "A02", "A03"),
mode=c(187, 189, 190),
control=c("A01",NA,NA),
mancontrol=c(NA, 191, 192),
ctrlmode=c(190, 191, 192))
I need to create a new column at the end, 'ctrlmode'.
A) If there is a value for that row in the 'mancontrol' column I want this value put into 'ctrlmode'.
B) If 'mancontrol' is NA, I want to look up the control sample in the 'control' column, then look up the control sample's mode in the 'mode' column, and put that mode into the new 'ctrlmode' column.
I'd be hugely grateful for some help! Thanks!
Upvotes: 1
Views: 70
Reputation: 886938
We can use match
with case_when
. The logic is if there are non-NA elements in 'mancontrol, return the 'mancontrol' or else match
the 'control' with the 'sample' to get the index and use that to subset the 'mode'
library(dplyr)
testdata %>%
mutate(ctrlmode = case_when(!is.na(mancontrol) ~ mancontrol,
TRUE ~ mode[match(control, sample)]))
if we have multiple types, then make sure than the output have only a single type as case_when
does the type check
testdata %>%
mutate(ctrlmode = case_when(!is.na(mancontrol) ~ as.numeric(mancontrol),
TRUE ~ mode[match(control, sample)]))
Or we can create an index and use that to assign
i1 <- is.na(testdata$mancontrol)
testdata$mancontrol[i1] <- with(testdata, mode[match(control, sample)][i1])
Upvotes: 2