# Dummying a dataset in R in a vectorized manner

I'm working with a 'weighted' adjacency matrix to a graph. It represents connections or relationships between entities. Since it's weighted it has different values, 0 being no relationship and goes up adding connection between the entities. I've been thinking about how to make a new dataset, similar to this one but only with 0s and 1s. So this:

  A B C D E                        A B C D E
A 0 2 5 1 9                      A 0 1 1 1 1
B 3 0 1 0 0    goes into this:   B 1 0 1 0 0
C 0 0 0 3 4                      C 0 0 0 1 1
D 0 4 5 0 2                      D 0 1 1 0 1
E 0 1 2 3 0                      E 0 1 1 1 0


I've been wondering how to do it, and only came up with a for-loop-solution that seems far from optimal and non-vectorized. I would appreciate any insight from an R enlightened one in order to come up with a more elegant answer.

Cheers

Here is a possible solution that avoids loops.

> tab1 <- rbind(c(0, 2, 5, 1, 9),
+               c(3, 0, 1, 0, 0),
+               c(0, 0, 0, 3, 4),
+               c(0, 4, 5, 0, 2),
+               c(0, 1, 2, 3, 0))
> tab2 <- matrix(as.numeric(tab1!=0),
+                nrow=nrow(tab1), ncol=ncol(tab1))
>
> tab1
[,1] [,2] [,3] [,4] [,5]
[1,]    0    2    5    1    9
[2,]    3    0    1    0    0
[3,]    0    0    0    3    4
[4,]    0    4    5    0    2
[5,]    0    1    2    3    0
> tab2
[,1] [,2] [,3] [,4] [,5]
[1,]    0    1    1    1    1
[2,]    1    0    1    0    0
[3,]    0    0    0    1    1
[4,]    0    1    1    0    1
[5,]    0    1    1    1    0

• Just tab2<-(tab1!=0)*1 is enough. Dimensions will survive comparison.
– user88
Commented Oct 9, 2011 at 12:34
• @mbq: Good point! Commented Oct 9, 2011 at 13:11

@mbq and @robermorales point out that this can be done with functions that maintain the matrix nature of the data automatically, and @ocram shows how to cast the data back to a matrix of the appropriate dimension were the function to not preserve the dimensions. I wanted to show another approach which works even if the transformation would not preserve dimensions.

Starting with the data provided

tab1 <- rbind(c(0, 2, 5, 1, 9),
c(3, 0, 1, 0, 0),
c(0, 0, 0, 3, 4),
c(0, 4, 5, 0, 2),
c(0, 1, 2, 3, 0))


You can use apply over both margins to work on each element at a time, and apply will guarantee the matrix nature is maintained.

tab2 <- apply(tab1, c(1,2), function(x) {ifelse(x==0, 0, 1)})


Here I used a different way of expressing the transformation (equivalent, but different. Probably less efficient, but I think more clear). For this simple case, ifelse will preserve the dimensions.

tab2b <- ifelse(tab1==0, 0, 1)


These give the same results

> identical(tab2, tab2b)
[1] TRUE


This works even if the transformation does not preserve dimensions.

> as.character(tab1)
[1] "0" "3" "0" "0" "0" "2" "0" "0" "4" "1" "5" "1" "0" "5" "2" "1" "0" "3" "0"
[20] "3" "9" "0" "4" "2" "0"
> apply(tab1, c(1,2), as.character)
[,1] [,2] [,3] [,4] [,5]
[1,] "0"  "2"  "5"  "1"  "9"
[2,] "3"  "0"  "1"  "0"  "0"
[3,] "0"  "0"  "0"  "3"  "4"
[4,] "0"  "4"  "5"  "0"  "2"
[5,] "0"  "1"  "2"  "3"  "0"


Try doing only

> tab2 <- (tab1!=0)+0


It will work.

> tab1 <- rbind(c(0, 2, 5, 1, 9),
+               c(3, 0, 1, 0, 0),
+               c(0, 0, 0, 3, 4),
+               c(0, 4, 5, 0, 2),
+               c(0, 1, 2, 3, 0))
> tab2 <- (tab1!=0)+0
>
> tab1
[,1] [,2] [,3] [,4] [,5]
[1,]    0    2    5    1    9
[2,]    3    0    1    0    0
[3,]    0    0    0    3    4
[4,]    0    4    5    0    2
[5,]    0    1    2    3    0
> tab2
[,1] [,2] [,3] [,4] [,5]
[1,]    0    1    1    1    1
[2,]    1    0    1    0    0
[3,]    0    0    0    1    1
[4,]    0    1    1    0    1
[5,]    0    1    1    1    0

• How is that different from mbq comment? Multiplying by one or adding zero is just shorthand for using as.integer. One could argue as.integer is slightly more efficient, but for such application it is pointless to argue. Commented Oct 10, 2011 at 13:51
• I did not see the comment, I am sorry. Commented Oct 11, 2011 at 11:39