Mike
Mike

Reputation: 1141

Using if logic with match

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

Answers (1)

akrun
akrun

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

Related Questions