Sum over arrays - What am I doing wrong?

Im trying to port a python numpy implementation of something into Julia and one step is

import numpy as np
np.random.rand(12,10) + np.random.rand(10)

Output shape - (12, 10)
but in Julia

rand(12,10) + rand(10)

throws DimensionMismatch(“dimensions must match: a has dims (Base.OneTo(12), Base.OneTo(10)), b has dims (Base.OneTo(10),), mismatch at 1”)

I tried broadcasting

rand(12,10) .+ rand(10)

DimensionMismatch(“arrays could not be broadcast to a common size; got a dimension with lengths 12 and 10”)

Im so confused. Is there something different here?

I’m not sure what ‘+’ does in python but if you want to add rand(10) to each rows of rand(12, 10) you should store them as a temporary array then add:

tmp = rand(10)
tmp2  = rand(12, 10)
vcat([permutedims(tmp2[i, :] + tmp) for i in 1:12]...)

Youd need the permutedims to keep row array when indexing in it and the vcat to concatenate all the rows.

Broadcasting in Julia can expand dimensions that have only one value, like in Python, but it has to be the “right” dimension.

Here you are adding a 10-value array to a matrix with 10 columns and 12 rows. That will work if the array is a row so it can be expanded to 12 rows:

rand(12,10) .+ rand(10)'

Ohh okay that makes sense

Okay now I get it. I thought it would be a direct translation.
Thanks a lot!

The reason for this difference is that while python creates row vectors when calling np.random.rand, julia creates a column vector. Which explains your dimension mismatch.

I think it’s easier to remember that in Python, you have to start aligning dimensions from the right, and in Julia from the left. That’s because Python is row-major and therefore the right-most dimension is the one contiguous in memory, while in Julia it’s the left-most.

In this example, broadcasting only works if two numbers on top of each other are the same, or at least one of them is 1. The [1] are implicit singleton dimensions that will always match, if one of the arguments is shorter than another.

# python: align from the right
arr1:  12  10
arr2:  [1] 10

# julia: align from the left, 12 and 10 are incompatible
arr1:  12  10
arr2:  10  [1]

# julia: with rand(10)', we have added a singleton dimension
# to arr2, so now it works
arr1:  12  10
arr2:   1  10

That works in higher dimensions, too, where it’s not just about rows and columns anymore.

I actually think it would be cool if the error messages for broadcasting gave such a visualization, but maybe it would be too crazy with many components.