Multiplication (and R data types)

This is a basic post about multiplication operations in R. We’re considering element-wise multiplication versus matrix multiplication. First let’s make some data:

# Make some data
a = c(1,2,3)
b = c(2,4,6)
c = cbind(a,b)
x = c(2,2,2)

If we look at the output (c and x), we can see that c is a 3×2 matrix and x is a 1×3 matrix (which I will also call a vector).

# View our data
c
##      a b
## [1,] 1 2
## [2,] 2 4
## [3,] 3 6
x
## [1] 2 2 2

In R the asterisk (*) is used for element-wise multiplication. This is where the elements in the same row are multiplied by one another.

#These will give the same result
c*x
x*c

We can see that the output of c*x and x*c are the same, and the vector x doubles matrix c.

#View our element-wise multiplication output
##      a  b
## [1,] 2  4
## [2,] 4  8
## [3,] 6 12

##      a  b
## [1,] 2  4
## [2,] 4  8
## [3,] 6 12

In R percent signs combined with asterisks are used for matrix multiplication (%*%).

# This works (matrix multiplication)
x%*%c
##       a  b
## [1,] 12 24

If you dig back and remember your matrix multiplication, you’ll find that a 1×3 matrix times a 3×2 matrix gives a 1×2 matrix. It will have the same number of rows as the first matrix (x has 1 row) and the same number of columns as the second matrix (c has 2 columns). Now let’s try this with x and c reversed.

# This doesn't work. Incorrect dimensions.
c%*%x
## Error in c %*% x : non-conformable arguments

R gives us an error because you can’t multiply a 3×2 and 1×3 matrix. For the matrix multiplication to work, the number of columns in the first matrix (c = 3 columns) has to be equal to the number of rows in the second matrix (x= 1 row).

The previous operations were done using the default R arrays, which are matrices. We can confirm this using the command class and typeof below:

# Get the data type
class(c)
typeof(c)
class(x)
typeof(x)

Here’s the output of those functions.

# The output
## [1] "matrix"
## [1] "double"
## [1] "numeric"
## [1] "double"

This shows us that our matrix c, has the R data type of a matrix, with formatting of ‘double’, which means that is is numbers (as opposed to something like ‘character’). This also shows us our 1×3 matrix or vector has the R data type ‘numeric’ and also has the formatting of ‘double’.

Now, let’s say your data is in a data frame rather than a matrix. Let’s see what happens when we perform multiplication on data frames. Remember data frames in R can hold different types of data (numbers, letters, etc.), while matrices can only have one type of data.
***For more info about this see my post here titled CBIND2***
Let’s convert our matrices to data frames using the function data.frame.

c1 = data.frame(c)
x1 = data.frame(x)

Now let’s look at our data. Note that there is an extra column of numbers from 1 to 3 for both c1 and x1. This is just a feature of the data frame output in R, where it is counting the rows 1 through 3.

c1
##   a b
## 1 1 2
## 2 2 4
## 3 3 6

x1
##   x
## 1 2
## 2 2
## 3 2

And just to be thorough, let’s check the R data type, to make sure they are not matrices.

# Check the data type
class(c1)
typeof(c1)
class(x1)
typeof(x1)

Here’s the output of those the data type. Notice that the class is now ‘data.frame’ instead of ‘matrix’ or ‘numeric’.

# The output
## [1] "data.frame"
## [1] "list"
## [1] "data.frame"
## [1] "list"

Now let’s try our simple element-wise multiplication again. You may have guessed it already, but these functions will no longer work.

# These both do not work
c1*x1
x1*c1

Here’s the output of the multiplication (i.e., the errors R provides).

## Error in Ops.data.frame(c1, x1) : 
##   ‘*’ only defined for equally-sized data frames

## Error in Ops.data.frame(c1, x1) : 
##   ‘*’ only defined for equally-sized data frames

According to the error R is providing, we can only multiply data frames of the same size. So, let’s try this out by making some new data.

# Make some data
h=c(2,2)
k=c(4,4)
j=cbind(h,k)
l=j*2

df1 = data.frame(j)
df2 = data.frame(l)

Now let’s look at the data to see what we have

# View the new data frames
df1
##   h k
## 1 2 4
## 2 2 4

df2
##   h k
## 1 4 8
## 2 4 8

Finally, let’s multiply df1*df2 and see what happens.

# Data frame multiplication
df1*df2
##   h  k
## 1 8 32
## 2 8 32

R has done element-wise multiplication on the data frames. This makes sense since we use only the (*) command. If we try this again with the order of the data frames reversed, we will get the same answer.

# Reverse the order for multiplication
df2*df1
##   h  k
## 1 8 32
## 2 8 32

That’s all for now. Hopefully this shed more light onto the way R performs multiplication, especially based on the data type.

Advertisements