Reputation: 2505
I have a data table that looks like this, resulting from a questionnaire about what drugs (encoded as a Drug ID) people are taking:
ID Drug1 Drug2 Drug3 Drug4
1 45 NA NA NA
2 NA NA NA NA
3 23 45 NA NA
4 23 NA NA NA
5 57 45 23 NA
In other words, the 1st person is taking a drug with ID "45" The second person is not taking any drugs. The third person is taking drug 23 and 45.
I would like to convert this into the following matrix:
ID 23 45 57
1 FALSE TRUE FALSE
2 FALSE FALSE FALSE
3 TRUE TRUE FALSE
4 TRUE FALSE FALSE
5 TRUE TRUE TRUE
How can I do this in R? I could not find a solution online that works for multiple columns like this.
Upvotes: 2
Views: 2250
Reputation: 887118
We could use mtabulate
library(qdapTools)
res <- cbind(df1[1],!!mtabulate(as.data.frame(t(df1[-1]))))
row.names(res) <- NULL
res
# ID 23 45 57
#1 1 FALSE TRUE FALSE
#2 2 FALSE FALSE FALSE
#3 3 TRUE TRUE FALSE
#4 4 TRUE FALSE FALSE
#5 5 TRUE TRUE TRUE
Upvotes: 1
Reputation: 93813
No packages needed:
with( cbind(dat[1], stack(dat[-1]) ), table(ID, values) > 0 )
# values
#ID 23 45 57
# 1 FALSE TRUE FALSE
# 2 FALSE FALSE FALSE
# 3 TRUE TRUE FALSE
# 4 TRUE FALSE FALSE
# 5 TRUE TRUE TRUE
Upvotes: 2
Reputation: 28441
We can use recast
from reshape2
to melt then cast the data frame. The exclamation points !!
are short for as.logical
:
library(reshape2)
r <- recast(df, id.var="ID", ID~value)
cbind(r[1], !!r[,-c(1,ncol(r))])
# ID 23 45 57
# 1 1 FALSE TRUE FALSE
# 2 2 FALSE FALSE FALSE
# 3 3 TRUE TRUE FALSE
# 4 4 TRUE FALSE FALSE
# 5 5 TRUE TRUE TRUE
Upvotes: 2