I have a data frame in R which looks like this
data
x1 x2 x3a x3b x3c x3d x4
A 43 0 0 0 1 P
B 23 0 1 0 0 Q
C 11 0 0 0 0 R
D 66 0 0 1 0 S
Now I want to merge columns x3a, x3b, x3c, x3d
to single column. The expected single column will contain column number having value 1 among x3a,x3b,x3c,x3d
. The value should be numbered (x3a=1,x3b=2,x3c=3,x3d=4)
. Expect result will be like following
x3
[1] 4 2 0 3
I tried reshape()
function but could not get what I actually wanted
q<-data[,3:6]
r<-reshape(q,varying=c("x3a","x3b","x3c","x3d"),v.names="x3",direction="long",times=c("x3a","x3b","x3c","x3d"))
final<-r[r$x3!=0,][,3]
But this did not give expected result. It missed out the value 0
between 2
and 3
:
final
[1]4 2 3
This worked:
data <- data.frame(
x1 = c('A','B','C','D'),
x2 = c(43,23,11,66),
x3a = c(0,0,0,0),
x3b = c(0,1,0,0),
x3c = c(0,0,0,1),
x3d = c(1,0,0,0),
x4 = c('P','Q','R','S')
)
data$x3 <- as.matrix(data[,c('x3a','x3b','x3c','x3d')]) %*% c(1,2,3,4)
The result:
x1 x2 x3a x3b x3c x3d x4 x3
1 A 43 0 0 0 1 P 4
2 B 23 0 1 0 0 Q 2
3 C 11 0 0 0 0 R 0
4 D 66 0 0 1 0 S 3
Chase made a comment that is relevant: What if x3a ... x3d
are different than zero or one? You can use ifelse()
to consider that scenario:
data$x3 <- as.matrix(ifelse(data[,c('x3a','x3b','x3c','x3d')] > 0, 1, 0)) %*% c(1,2,3,4)
@Barrankas answer is very clever and also vectorized, here's a less clever/vectorized option
as.numeric(apply(data[, 3:6], 1, function(x) which(x == 1)))
## [1] 4 2 NA 3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With