Multiplying vector combinations
You are probably looking for outer()
or it's alias binary operator %o%
:
> c(2,3,4) %o% c(1,2)
[,1] [,2]
[1,] 2 4
[2,] 3 6
[3,] 4 8
> outer(c(2,3,4), c(1,2))
[,1] [,2]
[1,] 2 4
[2,] 3 6
[3,] 4 8
In your case, outer()
offers the flexibility to specify a function that is applied to the combinations; %o%
only applies the *
multiplication function. For your example and data
mph <- function(d, rpm) {
cir <- pi * d
cir * rpm / 63360 * 60
}
> outer(c(20,26,29), c(150,350), FUN = mph)
[,1] [,2]
[1,] 8.924979 20.82495
[2,] 11.602473 27.07244
[3,] 12.941220 30.19618
Product between all combinations of a vector's elements
We can use combn
with anonymous function call
combn(vec, 2, FUN = function(x) x[1] * x[2])
#[1] 2 3 4 6 8 12
data
vec <- 1:4
Multiply permutations of two vectors in R
Use outer(A,B,'*')
which will return a matrix
x<-c(1:4)
y<-c(10:14)
outer(x,y,'*')
returns
[,1] [,2] [,3] [,4] [,5]
[1,] 10 11 12 13 14
[2,] 20 22 24 26 28
[3,] 30 33 36 39 42
[4,] 40 44 48 52 56
and if you want the result in a list you then can do
z<-outer(x,y,'*')
z.list<-as.list(t(z))
head(z.list)
returns
[[1]]
[1] 10
[[2]]
[1] 11
[[3]]
[1] 12
[[4]]
[1] 13
[[5]]
[1] 14
[[6]]
[1] 20
which is x1*y1, x1*y2, x1* y3, x1*y4, x2*y1 ,... (if you want x1*y1, x2*y1, ... replace t(z)
by z
)
How to calculate the product from combinations of several vectors in R?
The expand.grid
solution is OK, but in mathematics there is an elegant Kronecker product.
R has a function kronecker
, but it takes two vectors at a time, so we need Reduce
for a recursive application:
oo <- Reduce(kronecker, list(a, b, c, d))
Alternatively, use outer
(the workhorse of kronecker
):
rr <- Reduce(outer, list(a, b, c, d))
This is more user-friendly, as rr[i, j, u, v]
gives you a[i] * b[j] * c[u] * d[v]
.
Remark 1
Note that elements in oo
and rr
differ in order. Because for two vectors a
and b
:
kronecker(a, b) ## a[1] * b, a[2] * b ...
outer(a, b) ## a * b[1], a * b[2] ...
Thus the following use of kronecker
produces a result identical to rr
.
zz <- Reduce(kronecker, list(d, c, b, a))
dim(zz) <- c(length(a), length(b), length(c), length(d))
Remark 2
The method can be adapted to do a[i] + b[j] + c[u] + d[v]
, by replacing the default operation "*"
in outer
and kronecker
to "+"
. For example:
Reduce(function (x, y) outer(x, y, "+"), list(a, b, c, d))
Remark 3
johannes's answer can be improved. That row-wise application of apply
is a performance killer. We can do the following to get a result consistent with rr
.
xx <- Reduce("*", expand.grid(a, b, c, d))
dim(xx) <- c(length(a), length(b), length(c), length(d))
Multiply two objects in R
The outer product is computed by outer
:
out <- outer(P1, P2)
dimnames(out) <- setNames(dimnames(out), c("P1", "P2"))
P2
P1 Low Medium High
Low 0.0625 0.125 0.0625
Medium 0.1250 0.250 0.1250
High 0.0625 0.125 0.0625
Then you can put it in long form using the reshape2 package:
reshape2::melt(out, value.name = "P(P1*P2)")
P1 P2 P(P1*P2)
1 Low Low 0.0625
2 Medium Low 0.1250
3 High Low 0.0625
4 Low Medium 0.1250
5 Medium Medium 0.2500
6 High Medium 0.1250
7 Low High 0.0625
8 Medium High 0.1250
9 High High 0.0625
Multiplying vectors from the same list and printing the highest 2 outputs
you can use itertools.combinations to multiply each vector in the list of arrays by each other vector in the list:
import itertools
result = [mltply(v1, v2) for v1, v2 in itertools.combinations(vectors_list, 2)]
to print the 3 highest results you can use the built-in function sorted
, or you can sort inline the list using list.sort
then slice the top 3 elements:
print(sorted(result)[-3:])
or:
result.sort()
print(result[-3:])
Multiplying all combinations of array elements in numpy
First, the easy (and arguably "correct") way to do what you want to do: use numpy.outer()
, not numpy.dot()
.
>>> import numpy
>>> t = [3,4]
>>> b = [1,2,3,4]
>>> numpy.outer(t, b)
array([[ 3, 6, 9, 12],
[ 4, 8, 12, 16]])
This function computes the component-wise product of two 1D arrays - in other words, it multiplies each element of one array by each element of the other array - and returns a 2D array with the results.
Given the way Numpy displays its results, you can think of this as writing the first vector across the top of a rectangle and the second one down the left side, and filling in a multiplication table.
| 1 2 3 4
-+----------------
3| 3 6 9 12
4| 4 8 12 16
The function implements a common mathematical operation on vectors, called the outer product, tensor product, or Kronecker product. Note that the outer product is not commutative; in other words, you get a different result depending on which order you give the arguments. Compare the above result to this:
>>> numpy.outer(b, t)
array([[ 3, 4],
[ 6, 8],
[ 9, 12],
[12, 16]])
Again, you can picture this as writing the first argument across the top, second argument down the side, and multiplying:
| 3 4
-+---------
1| 3 4
2| 6 8
3| 9 12
4| 12 16
Numpy's dot()
function, on the other hand, implements the dot product when applied to 1D arrays, or matrix multiplication when applied to 2D arrays, or a generalized version of matrix multiplication when applied to higher-dimensional arrays, but I'll ignore that case because it's a little tricky to understand.
For two 1D arrays,
dot()
multiplies the two first elements together, the two second elements together, etc. and adds them all up, resulting in a number.>>> numpy.dot([1,2,3], [4,5,6])
32because
1*4+2*5+3*6 == 32
. So basically, it iterates over the indices of each array, multiplies corresponding elements, and adds them up. Clearly, the two arrays must have the same length.You can visualize this in a similar way to
outer()
, but instead of writing the 1D arrays along the edge, write them perpendicular to the edge. You should also switch the order, for reasons that will become clear later (but it's really an implementation choice): write the first one on the left and the second one on the top. An example will demonstrate:| 4
| 5
| 6
---------+----
1 2 3| 32To calculate the 32, I multiplied elements at the corresponding position in the column above that cell and the row next to it.
1*4
,2*5
, and3*6
, and then add them all up.For two 2D arrays,
dot()
iterates over one axis of each array, multiplies corresponding elements, and adds them up. The axis being iterated over is the last one of the first array, and the first one (actually, next-to-last) of the second array. Clearly, these two axes must have the same length.It's easy to understand this operation in terms of the diagram, so I'll jump right to that: suppose you want to compute the matrix product of
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]])and
array([[10, 11],
[12, 13],
[14, 15]])in that order. Again, just write the first argument on the side of a rectangle, and the second one over the top, and then you can multiply-and-add to fill in each cell as I did with the 1D example.
| 10 11
| 12 13
| 14 15
----------+--------
1 2 3| 76 82
4 5 6| 184 199
7 8 9| 292 316because, for example,
4*10+5*12+6*14 == 184
.
Now, you might notice that you can use the dot()
function to do the same thing as the outer()
function - but your arrays have be 2D and have a dimension of length 1. That's why you had to jump through some hoops (like the [:, None]
indexing) in your original code sample to make it work. And it has to be the right dimension too: it has to be the last dimension of the first array, and the next-to-last dimension of the second array. So in your specific example, where you want to compute the outer product of [3,4]
and [1,2,3,4]
, in that order, you need to convert the first list into an array of shape (2,1)
, and the second list into an array of shape (1,4)
. If you do that, when you pass them to dot()
, it effectively constructs this diagram and fills in the cells:
|[[ 1, 2, 3, 4]]
-----+------------------
[[3],| 3 6 9 12
[4]]| 4 8 12 16
I added some brackets to help you relate these requirements to Numpy syntax.
What you were trying to do, in the code sample in your question (numpy.dot(t, b)
), would have corresponded to this diagram:
| [[1],
| [2],
| [3],
| [4]]
--------+------------------
[[3, 4]]| ?
See, when you try to apply the multiply-and-add procedure to this, it doesn't work, because you've got two elements in one array and four in the other array, and you can't pair them up to do the multiplications. That's the root of the error Numpy shows you.
When you reverse the order, numpy.dot(b, t)
, you get this diagram:
|[[ 3, 4]]
-----+----------
[[1],| 3 4
[2],| 6 8
[3],| 9 12
[4]]| 12 16
That does give you a sensible result, but be careful about whether it's really the one you want. This is an array of shape (4,2)
, whereas if you fix up the other procedure in the most straightforward way, you would get a result of shape (1,1)
, or really, just a number. In any given situation, only one of these options (at most) will work. And it seems like the logistic
function in the screenshot you posted in a comment is expecting a single number to come out of that dot()
function; it's not going to work with a larger matrix. (Well, it might, but it won't do what you think.)
Related Topics
Why Are Probabilities and Response in Ksvm in R Not Consistent
Getting the Minimum of the Rows in a Data Frame
Levenshtein Type Algorithm with Numeric Vectors
Non-Standard Evaluation and Quasiquotation in Dplyr() Not Working as (Naively) Expected
Labelling Points with Ggplot2 and Directlabels
Copy-On-Modify Semantic on a Vector Does Not Append in a Loop. Why
How to Automate Nested Sections in Rmds Which Include Text, Maps and Tables
Ordering Factors in Each Facet of Ggplot by Y-Axis Value
Replace Na with Mode Based on Id Attribute
How to Annotate Ggplot2 Qplot Outside of Legend and Plotarea? (Similar to Mtext())
How to Obtain All Combinations of the Columns of a Data Frame Taken by 2
Create a New Column with Non-Null Columns' Names
Increasing Whitespace Between Legend Items in Ggplot2
How to Render Custom Map Tiles Created with Gdal2Tiles in Leaflet for R
Modify Spacing Between Key Glyphs in Vertical Legend Whilst Keeping Key Glyph Border