Reputation: 43
I have this vector
ID var2 ID var2 var1 ID var2 ID var3
"1000" "1" "1001" "1" "1" "1002" "7" "1003" "3"
that can be obtained from
x=c("1000","1","1001","1","1","1002","7","1003","3")
names(x)=c("ID","var2","ID","var2","var1","ID","var2","ID","var3")
and I would convert it into this matrix of dimension 4x4:
ID var1 var2 var3
"1000" NA "1" NA
"1001" "1" "1" NA
"1002" NA "7" NA
"1003" NA NA "3"
Could you help me please?
Upvotes: 4
Views: 93
Reputation: 886998
We could split
the vector 'x' by the a grouping vector based on the occurence of 'ID', match
the unique names ('nm1') with names of the list elements to order
and then rbind
to get the expected output
nm1 <- sort(unique(names(x)))
do.call(rbind,lapply(split(x, cumsum(grepl('ID', names(x)))), function(y)
setNames(y[match(nm1, names(y))], nm1)
))
# ID var1 var2 var3
#1 "1000" NA "1" NA
#2 "1001" "1" "1" NA
#3 "1002" NA "7" NA
#4 "1003" NA NA "3"
Or use row/col
index after creating an empty matrix.
indx <- match(names(x), nm1)
m1 <- matrix(, nrow= max(tabulate(indx)), ncol=length(nm1),
dimnames=list(NULL, nm1))
m1[cbind(cumsum(indx==1), indx)] <- x
Upvotes: 3
Reputation: 330073
Neither pretty or fast but you can do something like this using data.table::rbindlist
library(data.table)
# Create list of lists splitting data by ID and convert to data.table
dt <- rbindlist(tapply(x, cumsum(names(x) == "ID"), as.list), fill=TRUE)
# Ensure column order
setcolorder(dt, c('ID', 'var1', 'var2', 'var3'))
# Convert to matrix
as.matrix(dt)
Upvotes: 2