Binding vectors, matrices and data frames using rbind and cbind is a common R task. However, when dimensions or classes differ between the objects passed to these functions, errors or unexpected results are common as well. Sounds familiar? Time to practice!

4.3.1 Try to create matrices from the vectors below, by binding them column-wise. First, without using R, write down whether binding the vectors to a matrix is actually possible; then the resulting matrix and its mode (e.g., character, numeric etc.). Finally check your answer using R.

  1. a <- 1:5 ; b <- 1:5
#Both vectors have 5 elements. By column-wise binding, we are going to have a matrix with 2 columns and 5 rows.
a <- 1:5
b <- 1:5

cbind(a,b)
##      a b
## [1,] 1 1
## [2,] 2 2
## [3,] 3 3
## [4,] 4 4
## [5,] 5 5
  1. a <- 1:5 ; b <- c(‘1’, ‘2’, ‘3’, ‘4’, ‘5’)
#Both vectors have 5 elements. By column-wise binding, we are going to have a matrix with 2 columns and 5 rows. Since one of the vectors (b) has character elements, all matrix will be a character matrix now.

a <- 1:5
b <- c("1", "2", "3", "4", "5")

x <- cbind(a,b)
  1. a <- 1:5 ; b <- 1:4; c <- 1:3
#Vectors have different lengths so cbin will give an error.

#a <- 1:5
#b <- 1:4
#c <- 1:3 
#cbin(a,b,c)

4.3.2 Repeat exercise 1, binding vectors row-wise instead of column-wise while avoiding any row names.

  1. a <- 1:5 ; b <- 1:5
#Both vectors have 5 elements. By row-wise binding, we are going to have a matrix with 5 columns and 2 rows.
a <- 1:5
b <- 1:5

rbind(a,b)
##   [,1] [,2] [,3] [,4] [,5]
## a    1    2    3    4    5
## b    1    2    3    4    5
  1. a <- 1:5 ; b <- c(‘1’, ‘2’, ‘3’, ‘4’, ‘5’)
#Both vectors have 5 elements. By row-wise binding, we are going to have a matrix with 5 columns and 2 rows. Since one of the vectors (b) has character elements, all matrix will be a character matrix now.

a <- 1:5
b <- c("1", "2", "3", "4", "5")

rbind(a,b)
##   [,1] [,2] [,3] [,4] [,5]
## a "1"  "2"  "3"  "4"  "5" 
## b "1"  "2"  "3"  "4"  "5"
  1. a <- 1:5 ; b <- 1:4; c <- 1:3
#Vectors have different lengths so rbin will give an error.

#a <- 1:5
#b <- 1:4
#c <- 1:3 
#rbin(a,b,c)

4.3.3 Bind the following matrices column-wise. First, without using R, write down whether binding the matrices is actually possible; then the resulting matrix and its mode (e.g., character, numeric etc.). Finally check your answer using R.

  1. a <- matrix(1:12, ncol=4); b <- matrix(21:35, ncol=5)
a <- matrix(1:12, ncol=4) # 12 elements, 3x4 matrix.
b <- matrix(21:35, ncol=5) # 15 elements, 3x5 matrix.

# The resulting matrix will be a 3x9 matrix

cbind(a,b)
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
## [1,]    1    4    7   10   21   24   27   30   33
## [2,]    2    5    8   11   22   25   28   31   34
## [3,]    3    6    9   12   23   26   29   32   35
  1. a <- matrix(1:12, ncol=4); b <- matrix(21:35, ncol=3)
a <- matrix(1:12, ncol=4) # 12 elements, 3x4 matrix.
b <- matrix(21:35, ncol=3) # 15 elements, 5x3 matrix.

# Number of rows does not match. It will give error.
# cbind(a,b)
  1. a <- matrix(1:39, ncol=3); b <- matrix(LETTERS, ncol=2)
a <- matrix(1:39, ncol=3) # 39 elements, 13x3 matrix.
b <- matrix(LETTERS, ncol=2) # 26 elements, 13x2 matrix.

# It will be a 13x5 matrix with character elements because one of the vectors is a character vector.

cbind(a,b)
##       [,1] [,2] [,3] [,4] [,5]
##  [1,] "1"  "14" "27" "A"  "N" 
##  [2,] "2"  "15" "28" "B"  "O" 
##  [3,] "3"  "16" "29" "C"  "P" 
##  [4,] "4"  "17" "30" "D"  "Q" 
##  [5,] "5"  "18" "31" "E"  "R" 
##  [6,] "6"  "19" "32" "F"  "S" 
##  [7,] "7"  "20" "33" "G"  "T" 
##  [8,] "8"  "21" "34" "H"  "U" 
##  [9,] "9"  "22" "35" "I"  "V" 
## [10,] "10" "23" "36" "J"  "W" 
## [11,] "11" "24" "37" "K"  "X" 
## [12,] "12" "25" "38" "L"  "Y" 
## [13,] "13" "26" "39" "M"  "Z"

4.3.4 Bind the matrix a <- matrix(1:1089, ncol=33) to itself, column-wise, 20 times (i.e., resulting in a new matrix with 21*33 columns). Hint: Avoid using cbind() to obtain an efficient solution. Various solutions are possible.

a <- matrix(1:1089, ncol=33)

a.new <- matrix(a, nrow = 33, ncol = 21*33 ) #As it is mentioned in the question, we will have a new matrix with 21*33 columns and since we're column-wise bindind, with the same number of row.

4.3.5 Try to create new data frames from the data frames below, by binding them column-wise. First, without using R, write down whether binding the data frames is actually possible; then the resulting data frame and the class of each column (e.g., integer, character, factor etc.). Finally check your answer using R.

  1. a <- data.frame(v1=1:5, v2=LETTERS[1:5]) ; b <- data.frame(var1=6:10, var2=LETTERS[6:10])
a <- data.frame(v1=1:5, v2=LETTERS[1:5])  # A 5x2 data frame. 
b <- data.frame(var1=6:10, var2=LETTERS[6:10]) # A 5x2 data frame.

cbind(a,b)
##   v1 v2 var1 var2
## 1  1  A    6    F
## 2  2  B    7    G
## 3  3  C    8    H
## 4  4  D    9    I
## 5  5  E   10    J
  1. a <- data.frame(v1=1:6, v2=LETTERS[1:6]) ; b <- data.frame(var1=6:10, var2=LETTERS[6:10])
a <- data.frame(v1=1:6, v2=LETTERS[1:6]) # A 6x2 data frame. 

b <- data.frame(var1=6:10, var2=LETTERS[6:10]) # A 5x2 data frame. So, the number of rows are not matching. So, we cannot bind them.

#cbind(a,b)

4.3.6 Try to create new data frames from the data frames below, by binding them row-wise. First, without using R, write down whether binding the data frames is actually possible; then the resulting data frame and the class of each column (e.g., integer, character, factor etc.). Finally check your answer using R, and explain any unexpected output.

  1. a <- data.frame(v1=1:5, v2=LETTERS[1:5]) ; b <- data.frame(v1=6:10, v2=LETTERS[6:10])
a <- data.frame(v1=1:5, v2=LETTERS[1:5]) 

b <- data.frame(v1=6:10, v2=LETTERS[6:10]) 

#In this case, number of columns must be equal.

ab <- rbind(a,b)

ab
##    v1 v2
## 1   1  A
## 2   2  B
## 3   3  C
## 4   4  D
## 5   5  E
## 6   6  F
## 7   7  G
## 8   8  H
## 9   9  I
## 10 10  J
str(ab)
## 'data.frame':    10 obs. of  2 variables:
##  $ v1: int  1 2 3 4 5 6 7 8 9 10
##  $ v2: Factor w/ 10 levels "A","B","C","D",..: 1 2 3 4 5 6 7 8 9 10
  1. a <- data.frame(v1=1:6, v2=LETTERS[1:6]) ; b <- data.frame(v2=6:10, v1=LETTERS[6:10])
a <- data.frame(v1=1:6, v2=LETTERS[1:6]) 
b <- data.frame(v2=6:10, v1=LETTERS[6:10])

#In this case, number of columns must be equal. Note that a$v2 column has factors while b$v2 has integers.

ab <- rbind(a,b)
## Warning in `[<-.factor`(`*tmp*`, ri, value = 6:10): invalid factor level,
## NA generated
ab
##    v1   v2
## 1   1    A
## 2   2    B
## 3   3    C
## 4   4    D
## 5   5    E
## 6   6    F
## 7   F <NA>
## 8   G <NA>
## 9   H <NA>
## 10  I <NA>
## 11  J <NA>
str(ab)
## 'data.frame':    11 obs. of  2 variables:
##  $ v1: chr  "1" "2" "3" "4" ...
##  $ v2: Factor w/ 6 levels "A","B","C","D",..: 1 2 3 4 5 6 NA NA NA NA ...

4.3.7 a. Use cbind() to add vector v3 <- 1:5 as a new variable to the data frame created in exercise 6b.
b. Reorder the columns of this data frame, as follows: v1, v3, v2.

b <- data.frame(v2=6:10, v1=LETTERS[6:10])

v3 <- 1:5

x <- cbind(b,v3)

x[c("v1", "v3", "v2")]
##   v1 v3 v2
## 1  F  1  6
## 2  G  2  7
## 3  H  3  8
## 4  I  4  9
## 5  J  5 10

4.3.8 Consider again the matrices of exercise 3b. Use both cbind() and rbind() to bind both matrices column-wise, adding NA for empty cells.

a <- matrix(1:12, ncol=4) 
b <- matrix(21:35, ncol=3)
a <- rbind(a, matrix(NA, ncol=4, nrow=2)) #Adding NA's to the end of matrix a.
ab <- cbind(a, b)
#For this specific need, package gdata has a function called cbindx
library(gdata)
## gdata: read.xls support for 'XLS' (Excel 97-2004) files ENABLED.
## 
## gdata: read.xls support for 'XLSX' (Excel 2007+) files ENABLED.
## 
## Attaching package: 'gdata'
## The following object is masked from 'package:stats':
## 
##     nobs
## The following object is masked from 'package:utils':
## 
##     object.size
## The following object is masked from 'package:base':
## 
##     startsWith
a <- matrix(1:12, ncol=4) 
b <- matrix(21:35, ncol=3)

cbindX(data.frame(a), data.frame(b))
##   X1 X2 X3 X4 X1 X2 X3
## 1  1  4  7 10 21 26 31
## 2  2  5  8 11 22 27 32
## 3  3  6  9 12 23 28 33
## 4 NA NA NA NA 24 29 34
## 5 NA NA NA NA 25 30 35

4.3.9 Consider again the data frames of exercise 5b. Use both cbind() and rbind() to bind both matrices column-wise, adding NA for empty cells.

a <- data.frame(v1=1:6, v2=LETTERS[1:6])

b <- data.frame(var1=6:10, var2=LETTERS[6:10])

b <- rbind(b, c(NA, NA))

new.matrix <- cbind(a, b)

new.matrix
##   v1 v2 var1 var2
## 1  1  A    6    F
## 2  2  B    7    G
## 3  3  C    8    H
## 4  4  D    9    I
## 5  5  E   10    J
## 6  6  F   NA <NA>