Arrays

Arrays

Zeros, ones, empty, similar

a0 = zeros(3)
a1 = ones(Int, 2, 1)
a2 = Array{Float32}(undef, 5)
a3 = similar(a0)
import numpy
a0 = numpy.zeros(3)
a1 = numpy.ones((2, 1), dtype=int)
a2 = numpy.empty(5, dtype="f4")
a3 = numpy.empty_like(a0)

eltype / .dtype

@assert eltype(a0) == eltype(a3) == Float64
@assert eltype(a1) == Int
@assert eltype(a2) == Float32
assert a0.dtype == a3.dtype == float
assert a1.dtype == int
assert a2.dtype == numpy.dtype("f4")

Comparison

@assert a0 == zero(a0)
@assert all(a0 .== 0)
assert (a0 == numpy.zeros_like(a0)).all()
assert (a0 == 0).all()

Indexing

x0 = reshape(1:6, 2, 3)
2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
 1  3  5
 2  4  6
import numpy
x0 = numpy.arange(1, 7).reshape(3, 2).T
array([[1, 3, 5],
       [2, 4, 6]])

Cartesian indexing

x1 = x0[CartesianIndex.([1, 2], [1, 3])]
2-element Array{Int64,1}:
 1
 6
x1 = x0[[0, 1], [0, 2]]
array([1, 6])

APL indexing

x2 = x0[[1, 2], [1, 3]]
2×2 Array{Int64,2}:
 1  5
 2  6
x2 = x0[numpy.ix_([0, 1], [0, 2])]
x2_equivalent = x0[[[0], [1]], [[0, 2]]]
assert (x2 == x2_equivalent).all()
x2
array([[1, 5],
       [2, 6]])

Boolean indexing

x3 = x0[x0 .% 2 .== 0]
3-element Array{Int64,1}:
 2
 4
 6
x3 = x0[x0 % 2 == 0]
array([2, 4, 6])

permutedims / .transpose

@assert size(permutedims(zeros(3, 5, 7), (2, 1, 3))) == (5, 3, 7)
import numpy
assert numpy.zeros((3, 5, 7)).transpose(1, 0, 2).shape == (5, 3, 7)

Adjoint and transpose

A = [
    1   2im
    -3 -4im
]
@assert A' == adjoint(A) == [
    1     -3
    -2im  4im
]
@assert transpose(A) == [
    1    -3
    2im  -4im
]
@assert adjoint.(A) == [
    1  -2im
    -3  4im
]
import numpy
A = numpy.array([
    [1, 2j],
    [-3, -4j],
])
assert (A.T.conj() == numpy.array([
    [1, -3],
    [-2j, 4j],
])).all()
assert (A.T == numpy.array([
    [1, -3],
    [2j, -4j],
])).all()
assert (A.conj() == numpy.array([
    [1, -2j],
    [-3, 4j],
])).all()
Note

Although there is numpy.matrix.H which is closer to Julia's adjoint, Numpy manual notes that:

It is strongly advised not to use the matrix subclass.

Zero-dimensional array

A = Array{Int,0}(undef)
A[] = 12345
@assert A[] == 12345
@assert A[] isa Int
@assert A[] - 12345 == 0
@assert length(A) == 1
@assert ndims(A) == 0
@assert size(A) == ()
import numpy
A = numpy.array(12345)
assert A.item() == numpy.asscalar(A) == 12345
assert isinstance(A.item(), int)
assert isinstance(numpy.asscalar(A), int)
assert A - 12345 == 0
assert A.size == 1
assert A.ndim == 0
assert A.shape == ()

Broadcasting

Broadcasting in Julia starts from left (leading dimension):

xs = reshape(1:6, (2, 3))
ys = 1:3:6
@assert ifelse.(xs .> ys, xs, ys) == [
    1 3 5
    4 4 6
]

Broadcasting in Python starts from right (trailing dimension):

import numpy
xs = (numpy.arange(6) + 1).reshape(3, 2)
ys = numpy.arange(1, 7, 3)

@numpy.vectorize
def vifelse(b, x, y):
    if b:
        return x
    else:
        return y

assert (vifelse(xs > ys, xs, ys).T == [  # notice `.T`
    [1, 3, 5],
    [4, 4, 6],
]).all()
Note

As mentioned in numpy.vectorize — NumPy Manual, there is no performance gain for using numpy.vectorize in Python (but sometimes it's quite useful!):

The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.