Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R how to merge different columns of data frame in one

Tags:

r

reshape

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 
like image 980
Prabhu Avatar asked Nov 28 '22 20:11

Prabhu


2 Answers

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)
like image 98
Barranka Avatar answered Dec 15 '22 11:12

Barranka


@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
like image 29
David Arenburg Avatar answered Dec 15 '22 13:12

David Arenburg