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.
What about matrix multiplication with data frames…..
LikeLike
You cannot do matrix multiplication with data frames because they are class ‘data.frame’. If you try the %*% operator, it will give you an error. Matrix multiplication can only be completed with matrices – class ‘matrix’. Hope this helps!!!
LikeLike
How can one make column-wise multiplications so that missing values are included (na.rm = TRUE)?
I have tried (prod, v1, v2, na.rm = TRUE) which only gives me Inf as an answer for every single value.
I’d be grateful for any further suggestions. Thank you.
LikeLike
If you were multiplying two values and one of them was NA, you would get NA as your answer. Ignoring NAs would provide little benefit. However, if you use a function like apply(), which allows you to sum or average across rows or columns, you can use the call na.rm=TRUE to ignore NAs. Hope this helps!
LikeLike
Actually, if you use the apply function then you can do this.
apply(c, 1, prod, na.rm = TRUE),
where “c” is the matrix, 1 performs the operation across rows, “prod” is the function for multiplication, and na.rm ignores NAs.
LikeLike