-
Notifications
You must be signed in to change notification settings - Fork 42
100 narray exercises
This is Ruby/Numo::NArray version of 100 numpy exercises (Repository)
# 100 numpy exercises
This is a collection of exercises that have been collected in the numpy mailing
list, on stack overflow and in the numpy documentation. I've also created some
to reach the 100 limit. The goal of this collection is to offer a quick
reference for both old and new users but also to provide a set of exercices for
those who teach.
If you find an error or think you've a better way to solve some of them, feel
free to open an issue at <https://github.com/rougier/numpy-100>
Python:
import numpy as np
Ruby:
require "numo/narray"
Python:
print(np.__version__)
np.show_config()
Ruby:
p Numo::NArray::VERSION
Python:
Z = np.zeros(10)
print(Z)
Ruby:
z = Numo::DFloat.zeros(10)
p z
Python:
Z = np.zeros((10,10))
print("%d bytes" % (Z.size * Z.itemsize))
Ruby:
z = Numo::DFloat.zeros(10,10)
printf "%d bytes", z.byte_size
Python:
$ python -c "import numpy; numpy.info(numpy.add)"
Ruby:
$ ri 'Numo::DFloat#+'
Python:
Z = np.zeros(10)
Z[4] = 1
print(Z)
Ruby:
z = Numo::DFloat.zeros(10)
z[4] = 1
p z
Python:
Z = np.arange(10,50)
print(Z)
Ruby:
z = Numo::DFloat[10..49]
p z
Python:
Z = np.arange(50)
Z = Z[::-1]
print(Z)
Ruby:
z = Numo::Int32.new(50).seq
z = z.reverse
# or
z = z[(-1..0).step(-1)]
Python:
Z = np.arange(9).reshape(3,3)
print(Z)
Ruby:
z = Numo::Int32.new(3,3).seq
p z
Python:
nz = np.nonzero([1,2,0,0,4,0])
print(nz)
Ruby:
nz = Numo::NArray[1,2,0,0,4,0].ne(0).where
p nz
Python:
Z = np.eye(3)
print(Z)
Ruby:
z = Numo::DFloat.eye(3)
p z
Python:
Z = np.random.random((3,3,3))
print(Z)
Ruby:
z = Numo::DFloat.new(3,3,3).rand
p z
Python:
Z = np.random.random((10,10))
Zmin, Zmax = Z.min(), Z.max()
print(Zmin, Zmax)
Ruby:
z = Numo::DFloat.new(10,10).rand
zmin, zmax = z.minmax
p zmin, zmax
Python:
Z = np.random.random(30)
m = Z.mean()
print(m)
Ruby:
z = Numo::DFloat.new(30).rand
m = z.mean
p m
Python:
Z = np.ones((10,10))
Z[1:-1,1:-1] = 0
print(Z)
Ruby:
z = Numo::DFloat.ones(10,10)
z[1..-2,1..-2] = 0
p z
Python:
Z = np.ones((5,5))
Z = np.pad(Z, pad_width=1, mode='constant', constant_values=0)
print(Z)
Ruby:
# todo: pad
Python:
print(0 * np.nan)
print(np.nan == np.nan)
print(np.inf > np.nan)
print(np.nan - np.nan)
print(0.3 == 3 * 0.1)
Ruby:
0 * Float::NAN
Float::NAN == Float::NAN
Float::INFINITY > Float::NAN
Float::NAN - Float::NAN
0.3 == 3 * 0.1
Python:
Z = np.diag(1+np.arange(4),k=-1)
print(Z)
Ruby:
z = Numo::Int32.zeros(5,5)
z.diagonal(-1)[] = Numo::Int32[1..4]
p z
Python:
Z = np.zeros((8,8),dtype=int)
Z[1::2,::2] = 1
Z[::2,1::2] = 1
print(Z)
Ruby:
z = Numo::Int32.zeros(8,8)
z[(1..-1).step(2),(0..-1).step(2)] = 1
z[(0..-1).step(2),(1..-1).step(2)] = 1
p z
# z = (Numo::Int32.new(1,8).seq + Numo::Int32.new(8,1).seq) % 2
# p z
Python:
print(np.unravel_index(100,(6,7,8)))
Ruby:
# NArray allows unraveled index access
z = Numo::Int32.new(6,7,8).seq
p z[100]
Python:
Z = np.tile( np.array([[0,1],[1,0]]), (4,4))
print(Z)
Ruby:
z = Numo::NArray[[0,1],[1,0]].tile(4,4)
p z
Python:
Z = np.random.random((5,5))
Zmax, Zmin = Z.max(), Z.min()
Z = (Z - Zmin)/(Zmax - Zmin)
print(Z)
Ruby:
z = Numo::DFloat.new(5,5).rand
zmin, zmax = z.minmax
z = (z - zmin)/(zmax - zmin)
p z
Python:
color = np.dtype([("r", np.ubyte, 1),
("g", np.ubyte, 1),
("b", np.ubyte, 1),
("a", np.ubyte, 1)])
Ruby:
# todo: record
color = Numo::Struct.new do
uint8 "r"
uint8 "g"
uint8 "b"
uint8 "a"
end
Python:
Z = np.dot(np.ones((5,3)), np.ones((3,2)))
print(Z)
Ruby:
x = Numo::DFloat.ones(5,3)
y = Numo::DFloat.ones(3,2)
z = x.dot y
p z
Python:
# Author: Evgeni Burovski
Z = np.arange(11)
Z[(3 < Z) & (Z <= 8)] *= -1
print(Z)
Ruby:
z = Numo::Int32.new(11).seq
z[(3 < z) & (z <= 8)] *= -1
p z
Python:
# Author: Jake VanderPlas
print(sum(range(5),-1))
from numpy import *
print(sum(range(5),-1))
Ruby:
p [*0...5,-1].inject(:+)
p Numo::Int32[0...5].sum(-1)
Python:
Z = np.arange(5)
Z**Z
2 << Z >> 2
Z <- Z
1j*Z
Z/1/1
Z<Z>Z
Ruby:
z = Numo::Int32.new(5).seq
z**z
2 << z >> 2
z <- z
1i*z
z/1/1
z<z>z
Python:
print(np.array(0) / np.array(0))
print(np.array(0) // np.array(0))
print(np.array([np.nan]).astype(int).astype(float))
Ruby:
p Numo::Int32[0] / Numo::Int32[0]
p Numo::DFloat[Float::NAN].cast_to(Numo::Int32).cast_to(Numo::DFloat)
Python:
# Author: Charles R Harris
Z = np.random.uniform(-10,+10,10)
print (np.trunc(Z + np.copysign(0.5, Z)))
Ruby:
z = Numo::DFloat.new(10).seq(-10,2.1) #rand(-10,+10)
p (z + Numo::DFloat[0.5].copysign(z)).trunc
Python:
Z1 = np.random.randint(0,10,10)
Z2 = np.random.randint(0,10,10)
print(np.intersect1d(Z1,Z2))
Ruby:
# todo: intersect1d
Python:
# Suicide mode on
defaults = np.seterr(all="ignore")
Z = np.ones(1)/0
# Back to sanity
_ = np.seterr(**defaults)
Ruby:
# ?
Python:
np.sqrt(-1) == np.emath.sqrt(-1)
Ruby:
# NA
Python:
yesterday = np.datetime64('today', 'D') - np.timedelta64(1, 'D')
today = np.datetime64('today', 'D')
tomorrow = np.datetime64('today', 'D') + np.timedelta64(1, 'D')
Ruby:
# use built-in class
require "date"
yesterday = Date.today - 1
today = Date.today
tomorrow = Date.today + 1
Python:
Z = np.arange('2016-07', '2016-08', dtype='datetime64[D]')
print(Z)
Ruby:
# use built-in class
require "date"
z = *Date.new(2016,7)..Date.new(2016,8)
p z
Python:
A = np.ones(3)*1
B = np.ones(3)*2
np.add(A,B,out=B)
np.divide(A,2,out=A)
np.negative(A,out=A)
np.multiply(A,B,out=A)
Ruby:
a = Numo::DFloat.new(3).fill(1)
b = Numo::DFloat.new(3).fill(2)
p (a+b)*(-a/2)
(a+b.inplace)*(-a.inplace/2)
p b
Python:
Z = np.random.uniform(0,10,10)
print (Z - Z%1)
print (np.floor(Z))
print (np.ceil(Z)-1)
print (Z.astype(int))
print (np.trunc(Z))
Ruby:
z = Numo::DFloat.new(10).rand(10)
p z - z%1
p z.floor
p z.ceil - 1
p z.cast_to(Numo::Int32)
p z.trunc
Python:
Z = np.zeros((5,5))
Z += np.arange(5)
print(Z)
Ruby:
z = Numo::DFloat.zeros(5,5)
z += Numo::Int32.new(5).seq
p z
Python:
def generate():
for x in range(10):
yield x
Z = np.fromiter(generate(),dtype=float,count=-1)
print(Z)
Ruby:
# no method: fromiter
generate = Enumerator.new do |y|
10.times{|x| y << x}
end
z = Numo::DFloat[*generate]
p z
Python:
Z = np.linspace(0,1,12,endpoint=True)[1:-1]
print(Z)
Ruby:
z = Numo::DFloat.linspace(0,1,12)[1..-2]
p z
Python:
Z = np.random.random(10)
Z.sort()
print(Z)
Ruby:
z = Numo::DFloat.new(10).rand
z = z.sort
p z
Python:
# Author: Evgeni Burovski
Z = np.arange(10)
np.add.reduce(Z)
Ruby:
z = Numo::Int32.new(10).seq
z.sum
# speed?
Python:
A = np.random.randint(0,2,5)
B = np.random.randint(0,2,5)
equal = np.allclose(A,B)
print(equal)
Ruby:
a = Numo::Int32.new(5).rand(2)
b = Numo::Int32.new(5).rand(2)
equal = a.eq(b).all?
p equal
Python:
Z = np.zeros(10)
Z.flags.writeable = False
Z[0] = 1
Ruby:
z = Numo::DFloat.zeros(10)
z.freeze
z[0] = 1
44. Consider a random 10x2 matrix representing cartesian coordinates, convert them to polar coordinates (★★☆)
Python:
Z = np.random.random((10,2))
X,Y = Z[:,0], Z[:,1]
R = np.sqrt(X**2+Y**2)
T = np.arctan2(Y,X)
print(R)
print(T)
Ruby:
z = Numo::DFloat.new(10,2).rand
x,y = z[true,0], z[true,1]
r = Numo::NMath.sqrt(x**2+y**2)
t = Numo::NMath.atan2(y,x)
p r
p t
Python:
Z = np.random.random(10)
Z[Z.argmax()] = 0
print(Z)
Ruby:
z = Numo::DFloat.new(10).rand
z[z.max_index] = 0
p z
Python:
Z = np.zeros((5,5), [('x',float),('y',float)])
Z['x'], Z['y'] = np.meshgrid(np.linspace(0,1,5),
np.linspace(0,1,5))
print(Z)
Ruby:
# todo: meshgrid
Python:
# Author: Evgeni Burovski
X = np.arange(8)
Y = X + 0.5
C = 1.0 / np.subtract.outer(X, Y)
print(np.linalg.det(C))
Ruby:
# todo: linalg.det
Python:
for dtype in [np.int8, np.int32, np.int64]:
print(np.iinfo(dtype).min)
print(np.iinfo(dtype).max)
for dtype in [np.float32, np.float64]:
print(np.finfo(dtype).min)
print(np.finfo(dtype).max)
print(np.finfo(dtype).eps)
Ruby:
# todo: Int32::MIN/MAX, etc
Python:
np.set_printoptions(threshold=np.nan)
Z = np.zeros((16,16))
print(Z)
Ruby:
Numo::NArray.inspect_cols = nil
Numo::NArray.inspect_rows = nil
z = Numo::DFloat.zeros(25,25)
p z
Python:
Z = np.arange(100)
v = np.random.uniform(0,100)
index = (np.abs(Z-v)).argmin()
print(Z[index])
Ruby:
z = Numo::Int32.new(100).seq
v = rand*100
index = (z-v).abs.min_index
p z[index]
Python:
Z = np.zeros(10, [ ('position', [ ('x', float, 1),
('y', float, 1)]),
('color', [ ('r', float, 1),
('g', float, 1),
('b', float, 1)])])
print(Z)
Ruby:
# todo: record
52. Consider a random vector with shape (100,2) representing coordinates, find point by point distances (★★☆)
Python:
Z = np.random.random((10,2))
X,Y = np.atleast_2d(Z[:,0]), np.atleast_2d(Z[:,1])
D = np.sqrt( (X-X.T)**2 + (Y-Y.T)**2)
print(D)
# Much faster with scipy
import scipy
# Thanks Gavin Heverly-Coulson (#issue 1)
import scipy.spatial
Z = np.random.random((10,2))
D = scipy.spatial.distance.cdist(Z,Z)
print(D)
Ruby:
# todo: cdist
Python:
Z = np.arange(10, dtype=np.int32)
Z = Z.astype(np.float32, copy=False)
print(Z)
Ruby:
# NArray does not support in-place type conversion
Python:
from io import StringIO
# Fake file
s = StringIO("""1, 2, 3, 4, 5\n
6, , , 7, 8\n
, , 9,10,11\n""")
Z = np.genfromtxt(s, delimiter=",", dtype=np.int)
print(Z)
Ruby:
require "stringio"
s = StringIO.new("1, 2, 3, 4, 5
6, , , 7, 8
, , 9,10,11")
z = Numo::NArray[*s.readlines.map{|l| l.split(",").map{|x| x.strip.empty? ? Float::NAN : x.to_f}}]
Python:
Z = np.arange(9).reshape(3,3)
for index, value in np.ndenumerate(Z):
print(index, value)
for index in np.ndindex(Z.shape):
print(index, Z[index])
Ruby:
z = Numo::Int32.new(3,3).seq
z.each_with_index{|x,*i| p [i,x]}
Python:
X, Y = np.meshgrid(np.linspace(-1,1,10), np.linspace(-1,1,10))
D = np.sqrt(X*X+Y*Y)
sigma, mu = 1.0, 0.0
G = np.exp(-( (D-mu)**2 / ( 2.0 * sigma**2 ) ) )
print(G)
Ruby:
x = Numo::DFloat.linspace(-1,1,10)
y = Numo::DFloat.linspace(-1,1,10).expand_dims(1)
d = Numo::NMath.sqrt(x*x+y*y)
sigma, mu = 1.0, 0.0
g = Numo::NMath.exp(-( (d-mu)**2 / ( 2.0 * sigma**2 ) ) )
p g
Python:
# Author: Divakar
n = 10
p = 3
Z = np.zeros((n,n))
np.put(Z, np.random.choice(range(n*n), p, replace=False),1)
print(Z)
Ruby:
# todo: choise
Python:
# Author: Warren Weckesser
X = np.random.rand(5, 10)
# Recent versions of numpy
Y = X - X.mean(axis=1, keepdims=True)
# Older versions of numpy
Y = X - X.mean(axis=1).reshape(-1, 1)
print(Y)
Ruby:
x = Numo::DFloat.new(5, 10).rand
y = x - x.mean(1).expand_dims(1)
Python:
# Author: Steve Tjoa
Z = np.random.randint(0,10,(3,3))
print(Z)
print(Z[Z[:,1].argsort()])
Ruby:
z = Numo::Int32.new(3,3).rand(10)
p z
p z[z[true,1].sort_index,true]
Python:
# Author: Warren Weckesser
Z = np.random.randint(0,3,(3,10))
print((~Z.any(axis=0)).any())
Ruby:
z = Numo::Int32.new(3,10).rand(3)
(~z.ne(0).any?(0)).any?
Python:
Z = np.random.uniform(0,1,10)
z = 0.5
m = Z.flat[np.abs(Z - z).argmin()]
print(m)
Ruby:
z = Numo::DFloat.new(10).rand
x = 0.5
m = z[(z - x).abs.min_index]
p m
62. Considering two arrays with shape (1,3) and (3,1), how to compute their sum using an iterator? (★★☆)
Python:
A = np.arange(3).reshape(3,1)
B = np.arange(3).reshape(1,3)
it = np.nditer([A,B,None])
for x,y,z in it: z[...] = x + y
print(it.operands[2])
Ruby:
# no iterator
Python:
class NamedArray(np.ndarray):
def __new__(cls, array, name="no name"):
obj = np.asarray(array).view(cls)
obj.name = name
return obj
def __array_finalize__(self, obj):
if obj is None: return
self.info = getattr(obj, 'name', "no name")
Z = NamedArray(np.arange(10), "range_10")
print (Z.name)
Ruby:
module NamedArray
attr_accessor :name
end
def NamedArray(array,name)
obj = array.extend(NamedArray)
obj.name = name
return obj
end
z = NamedArray(Numo::NArray[0...10], "range_10")
p z.name
# todo: asarray
64. Consider a given vector, how to add 1 to each element indexed by a second vector (be careful with repeated indices)? (★★★)
Python:
# Author: Brett Olsen
Z = np.ones(10)
I = np.random.randint(0,len(Z),20)
Z += np.bincount(I, minlength=len(Z))
print(Z)
Ruby:
z = Numo::Int32.ones(10)
i = Numo::Int32.new(20).rand(0,z.size)
z += i.bincount(minlength:z.size)
Python:
# Author: Alan G Isaac
X = [1,2,3,4,5,6]
I = [1,3,9,3,4,1]
F = np.bincount(I,X)
print(F)
Ruby:
x = [1,2,3,4,5,6]
i = [1,3,9,3,4,1]
f = Numo::NArray[*i].bincount(x)
p f
Python:
# Author: Nadav Horesh
w,h = 16,16
I = np.random.randint(0,2,(h,w,3)).astype(np.ubyte)
F = I[...,0]*256*256 + I[...,1]*256 +I[...,2]
n = len(np.unique(F))
print(np.unique(I))
Ruby:
# todo: unique
w,h = 16,16
i = Numo::UInt32.new(h,w,3).rand(2)
f = i[false,0]*256*256 + i[false,1]*256 +i[false,2]
p f.flatten.sort.to_a.uniq
Python:
A = np.random.randint(0,10,(3,4,3,4))
sum = A.reshape(A.shape[:-2] + (-1,)).sum(axis=-1)
print(sum)
Ruby:
a = Numo::Int32.new(3,4,3,4).rand(10)
sum = a.sum(-2,-1)
p sum
68. Considering a one-dimensional vector D, how to compute means of subsets of D using a vector S of same size describing subset indices? (★★★)
Python:
# Author: Jaime Fernández del Río
D = np.random.uniform(0,1,100)
S = np.random.randint(0,10,100)
D_sums = np.bincount(S, weights=D)
D_counts = np.bincount(S)
D_means = D_sums / D_counts
print(D_means)
Ruby:
d = Numo::DFloat.new(100).rand(0,1)
s = Numo::Int32.new(100).rand(0,10)
d_sums = s.bincount(d)
d_counts = s.bincount
d_means = d_sums / d_counts
p d_means
Python:
# Author: Mathieu Blondel
A = np.random.uniform(0,1,(5,5))
B = np.random.uniform(0,1,(5,5))
# Slow version
np.diag(np.dot(A, B))
# Fast version
np.sum(A * B.T, axis=1)
# Faster version
np.einsum("ij,ji->i", A, B)
Ruby:
a = Numo::DFloat.new(3,3).seq
b = Numo::DFloat.new(3,3).seq
p a.mulsum(b.transpose,1)
# speed?
70. Consider the vector [1, 2, 3, 4, 5], how to build a new vector with 3 consecutive zeros interleaved between each value? (★★★)
Python:
# Author: Warren Weckesser
Z = np.array([1,2,3,4,5])
nz = 3
Z0 = np.zeros(len(Z) + (len(Z)-1)*(nz))
Z0[::nz+1] = Z
print(Z0)
Ruby:
z = Numo::NArray[1,2,3,4,5]
nz = 3
z0 = Numo::Int32.zeros(z.size + (z.size-1)*(nz))
z0[(0..-1).step(nz+1)] = z
p z0
71. Consider an array of dimension (5,5,3), how to mulitply it by an array with dimensions (5,5)? (★★★)
Python:
A = np.ones((5,5,3))
B = 2*np.ones((5,5))
print(A * B[:,:,None])
Ruby:
a = Numo::Int32.ones(5,5,3)
b = Numo::Int32.new(5,5).fill(2)
p a * b[:*,:*,:-]
Python:
# Author: Eelco Hoogendoorn
A = np.arange(25).reshape(5,5)
A[[0,1]] = A[[1,0]]
print(A)
Ruby:
a = Numo::Int32.new(5,5).seq
a[[0,1],true] = a[[1,0],true].copy
p a
# todo: identity check between read/write array
73. Consider a set of 10 triplets describing 10 triangles (with shared vertices), find the set of unique line segments composing all the triangles (★★★)
Python:
# Author: Nicolas P. Rougier
faces = np.random.randint(0,100,(10,3))
F = np.roll(faces.repeat(2,axis=1),-1,axis=1)
F = F.reshape(len(F)*3,2)
F = np.sort(F,axis=1)
G = F.view( dtype=[('p0',F.dtype),('p1',F.dtype)] )
G = np.unique(G)
print(G)
Ruby:
# todo: roll
74. Given an array C that is a bincount, how to produce an array A such that np.bincount(A) == C? (★★★)
Python:
# Author: Jaime Fernández del Río
C = np.bincount([1,1,2,3,4,4,6])
A = np.repeat(np.arange(len(C)), C)
print(A)
Ruby:
a = Numo::NArray[1,1,2,3,4,4,6]
c = a.bincount
a = a.seq.repeat(c)
p a
Python:
# Author: Jaime Fernández del Río
def moving_average(a, n=3) :
ret = np.cumsum(a, dtype=float)
ret[n:] = ret[n:] - ret[:-n]
return ret[n - 1:] / n
Z = np.arange(20)
print(moving_average(Z, n=3))
Ruby:
def moving_average(a, n=3)
ret = a.cumsum
ret[n..-1] = ret[n..-1] - ret[0..-n-1]
ret[n-1..-1] / n
end
z = Numo::DFloat.new(20).seq
p moving_average(z, 3)
76. Consider a one-dimensional array Z, build a two-dimensional array whose first row is (Z[0],Z[1],Z[2]) and each subsequent row is shifted by 1 (last row should be (Z[-3],Z[-2],Z[-1]) (★★★)
Python:
# Author: Joe Kington / Erik Rigtorp
from numpy.lib import stride_tricks
def rolling(a, window):
shape = (a.size - window + 1, window)
strides = (a.itemsize, a.itemsize)
return stride_tricks.as_strided(a, shape=shape, strides=strides)
Z = rolling(np.arange(10), 3)
print(Z)
Ruby:
# no module: stride_tricks
Python:
# Author: Nathaniel J. Smith
Z = np.random.randint(0,2,100)
np.logical_not(Z, out=Z)
Z = np.random.uniform(-1.0,1.0,100)
np.negative(Z, out=Z)
Ruby:
# todo: logical_not
z = Numo::Int32.new(100).rand(2)
p z
z.inplace ^ 1
p z
z = Numo::DFloat.new(100).rand(-1,1)
p z
-z.inplace
p z
78. Consider 2 sets of points P0,P1 describing lines (2d) and a point p, how to compute distance from p to each line i (P0[i],P1[i])? (★★★)
Python:
def distance(P0, P1, p):
T = P1 - P0
L = (T**2).sum(axis=1)
U = -((P0[:,0]-p[...,0])*T[:,0] + (P0[:,1]-p[...,1])*T[:,1]) / L
U = U.reshape(len(U),1)
D = P0 + U*T - p
return np.sqrt((D**2).sum(axis=1))
P0 = np.random.uniform(-10,10,(10,2))
P1 = np.random.uniform(-10,10,(10,2))
p = np.random.uniform(-10,10,( 1,2))
print(distance(P0, P1, p))
Ruby:
def distance(p0, p1, p)
t = p1 - p0
l = (t**2).sum(1)
u = -((p0[true,0]-p[false,0])*t[true,0] + (p0[true,1]-p[false,1])*t[true,1]) / l
u = u.reshape(u.size,1)
d = p0 + u*t - p
return Numo::NMath.sqrt((d**2).sum(1))
end
p0 = Numo::DFloat.new(10,2).rand(-10,10)
p1 = Numo::DFloat.new(10,2).rand(-10,10)
p = Numo::DFloat.new( 1,2).rand(-10,10)
p distance(p0, p1, p)
79. Consider 2 sets of points P0,P1 describing lines (2d) and a set of points P, how to compute distance from each point j (P[j]) to each line i (P0[i],P1[i])? (★★★)
Python:
# Author: Italmassov Kuanysh
# based on distance function from previous question
P0 = np.random.uniform(-10, 10, (10,2))
P1 = np.random.uniform(-10,10,(10,2))
p = np.random.uniform(-10, 10, (10,2))
print(np.array([distance(P0,P1,p_i) for p_i in p]))
Ruby:
p0 = Numo::DFloat.new(10,2).rand(-10,10)
p1 = Numo::DFloat.new(10,2).rand(-10,10)
p = Numo::DFloat.new(10,2).rand(-10,10)
p Numo::NArray[*(0...p.shape[0]).map{|i| distance(p0, p1, p[i,true])}]
80. Consider an arbitrary array, write a function that extract a subpart with a fixed shape and centered on a given element (pad with a fill
value when necessary) (★★★)
Python:
# Author: Nicolas Rougier
Z = np.random.randint(0,10,(10,10))
shape = (5,5)
fill = 0
position = (1,1)
R = np.ones(shape, dtype=Z.dtype)*fill
P = np.array(list(position)).astype(int)
Rs = np.array(list(R.shape)).astype(int)
Zs = np.array(list(Z.shape)).astype(int)
R_start = np.zeros((len(shape),)).astype(int)
R_stop = np.array(list(shape)).astype(int)
Z_start = (P-Rs//2)
Z_stop = (P+Rs//2)+Rs%2
R_start = (R_start - np.minimum(Z_start,0)).tolist()
Z_start = (np.maximum(Z_start,0)).tolist()
R_stop = np.maximum(R_start, (R_stop - np.maximum(Z_stop-Zs,0))).tolist()
Z_stop = (np.minimum(Z_stop,Zs)).tolist()
r = [slice(start,stop) for start,stop in zip(R_start,R_stop)]
z = [slice(start,stop) for start,stop in zip(Z_start,Z_stop)]
R[r] = Z[z]
print(Z)
print(R)
Ruby:
# todo: minimum, maximum
81. Consider an array Z = [1,2,3,4,5,6,7,8,9,10,11,12,13,14], how to generate an array R = 1,2,3,4], [2,3,4,5], [3,4,5,6], ..., [11,12,13,14? (★★★)
Python:
# Author: Stefan van der Walt
Z = np.arange(1,15,dtype=np.uint32)
R = stride_tricks.as_strided(Z,(11,4),(4,4))
print(R)
Ruby:
# no moudle: stride_tricks
Python:
# Author: Stefan van der Walt
Z = np.random.uniform(0,1,(10,10))
U, S, V = np.linalg.svd(Z) # Singular Value Decomposition
rank = np.sum(S > 1e-10)
print(rank)
Ruby:
# todo: svd
Python:
Z = np.random.randint(0,10,50)
print(np.bincount(Z).argmax())
Ruby:
z = Numo::Int32.new(50).rand(0,10)
z.bincount.max_index
Python:
# Author: Chris Barker
Z = np.random.randint(0,5,(10,10))
n = 3
i = 1 + (Z.shape[0]-3)
j = 1 + (Z.shape[1]-3)
C = stride_tricks.as_strided(Z, shape=(i, j, n, n), strides=Z.strides + Z.strides)
print(C)
Ruby:
# no module: stride_tricks
Python:
# Author: Eric O. Lebigot
# Note: only works for 2d array and value setting using indices
class Symetric(np.ndarray):
def __setitem__(self, index, value):
i,j = index
super(Symetric, self).__setitem__((i,j), value)
super(Symetric, self).__setitem__((j,i), value)
def symetric(Z):
return np.asarray(Z + Z.T - np.diag(Z.diagonal())).view(Symetric)
S = symetric(np.random.randint(0,10,(5,5)))
S[2,3] = 42
print(S)
Ruby:
module Symetric
def []=(i,j,value)
super(i,j,value)
super(j,i,value) if i != j
end
end
def symetric(z)
y = z + z.transpose
y.diagonal.store(z.diagonal)
y.extend(Symetric)
end
s = symetric(Numo::Int32.new(5,5).rand(10))
s[2,3] = 42
p s
86. Consider a set of p matrices wich shape (n,n) and a set of p vectors with shape (n,1). How to compute the sum of of the p matrix products at once? (result has shape (n,1)) (★★★)
Python:
# Author: Stefan van der Walt
p, n = 10, 20
M = np.ones((p,n,n))
V = np.ones((p,n,1))
S = np.tensordot(M, V, axes=[[0, 2], [0, 1]])
print(S)
# It works, because:
# M is (p,n,n)
# V is (p,n,1)
# Thus, summing over the paired axes 0 and 0 (of M and V independently),
# and 2 and 1, to remain with a (n,1) vector.
Ruby:
p, n = 10, 20
m = Numo::DFloat.ones(p,n,n)
v = Numo::DFloat.ones(p,n,1)
s = m.transpose(0,2,1).mulsum(v,0,1)
p s
# todo: tensordot?
Python:
# Author: Robert Kern
Z = np.ones((16,16))
k = 4
S = np.add.reduceat(np.add.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),
np.arange(0, Z.shape[1], k), axis=1)
print(S)
Ruby:
n, k = 16, 4
z = Numo::DFloat.ones(n,n)
s = z.reshape(n/k,k,n/k,k).sum(1,3)
# todo: reduceat?
Python:
# Author: Nicolas Rougier
def iterate(Z):
# Count neighbours
N = (Z[0:-2,0:-2] + Z[0:-2,1:-1] + Z[0:-2,2:] +
Z[1:-1,0:-2] + Z[1:-1,2:] +
Z[2: ,0:-2] + Z[2: ,1:-1] + Z[2: ,2:])
# Apply rules
birth = (N==3) & (Z[1:-1,1:-1]==0)
survive = ((N==2) | (N==3)) & (Z[1:-1,1:-1]==1)
Z[...] = 0
Z[1:-1,1:-1][birth | survive] = 1
return Z
Z = np.random.randint(0,2,(50,50))
for i in range(100): Z = iterate(Z)
print(Z)
Ruby:
def iterate(z)
# Count neighbours
n = z[0..-3,0..-3] + z[0..-3,1..-2] + z[0..-3,2..-1] +
z[1..-2,0..-3] + z[1..-2,2..-1] +
z[2..-1,0..-3] + z[2..-1,1..-2] + z[2..-1,2..-1]
# Apply rules
birth = n.eq(3) & z[1..-2,1..-2].eq(0)
survive = (n.eq(2) | n.eq(3)) & z[1..-2,1..-2].eq(1)
z[] = 0
#z[1..-2,1..-2][birth | survive] = 1
y = z[0..-3,0..-3].copy
y[birth | survive] = 1
z[1..-2,1..-2] = y
end
z = Numo::Int32.new(50,50).rand(2)
100.times{ iterate(z) }
p z
Python:
Z = np.arange(10000)
np.random.shuffle(Z)
n = 5
# Slow
print (Z[np.argsort(Z)[-n:]])
# Fast
print (Z[np.argpartition(-Z,n)[:n]])
Ruby:
z = Numo::DFloat.new(10000).rand
n = 5
p z[z.sort_index[-n..-1]]
# todo: shuffle, argpartition
90. Given an arbitrary number of vectors, build the cartesian product (every combinations of every item) (★★★)
Python:
# Author: Stefan Van der Walt
def cartesian(arrays):
arrays = [np.asarray(a) for a in arrays]
shape = (len(x) for x in arrays)
ix = np.indices(shape, dtype=int)
ix = ix.reshape(len(arrays), -1).T
for n, arr in enumerate(arrays):
ix[:, n] = arrays[n][ix[:, n]]
return ix
print (cartesian(([1, 2, 3], [4, 5], [6, 7])))
Ruby:
def cartesian(*arrays)
arrays = arrays.map{|a| Numo::Int32.cast(a)}
shape = arrays.map{|x| x.size}
asz = arrays.size
ix = Numo::Int32.zeros(*shape, asz)
arrays.each_with_index do |arr,n|
s = [1]*asz
s[n] = arr.size
ix[false,n] = arr.reshape(*s)
end
return ix.reshape(ix.size/asz,asz)
end
p cartesian([1, 2, 3], [4, 5], [6, 7])
Python:
Z = np.array([("Hello", 2.5, 3),
("World", 3.6, 2)])
R = np.core.records.fromarrays(Z.T,
names='col1, col2, col3',
formats = 'S8, f8, i8')
print(R)
Ruby:
# todo: record
Python:
# Author: Ryan G.
x = np.random.rand(5e7)
%timeit np.power(x,3)
%timeit x*x*x
%timeit np.einsum('i,i,i->i',x,x,x)
Ruby:
x = Numo::DFloat.new(5e7).rand
x**3 # probably fast
93. Consider two arrays A and B of shape (8,3) and (2,2). How to find rows of A that contain elements of each row of B regardless of the order of the elements in B? (★★★)
Python:
# Author: Gabe Schwartz
A = np.random.randint(0,5,(8,3))
B = np.random.randint(0,5,(2,2))
C = (A[..., np.newaxis, np.newaxis] == B)
rows = (C.sum(axis=(1,2,3)) >= B.shape[1]).nonzero()[0]
print(rows)
Ruby:
a = Numo::Int32.new(8,3).rand(5)
b = Numo::Int32.new(2,2).rand(5)
c = a[false,:new,:new].eq b
rows = (c.count_true(1,2,3) >= b.shape[1]).where
p rows
Python:
# Author: Robert Kern
Z = np.random.randint(0,5,(10,3))
E = np.logical_and.reduce(Z[:,1:] == Z[:,:-1], axis=1)
U = Z[~E]
print(Z)
print(U)
Ruby:
z = Numo::Int32.new(10,3).rand(5)
e = (z[true,1..-1].eq z[true,0..-2]).all?(1)
u = z[(~e).where,true]
p z
p u
Python:
# Author: Warren Weckesser
I = np.array([0, 1, 2, 3, 15, 16, 32, 64, 128])
B = ((I.reshape(-1,1) & (2**np.arange(8))) != 0).astype(int)
print(B[:,::-1])
# Author: Daniel T. McDonald
I = np.array([0, 1, 2, 3, 15, 16, 32, 64, 128], dtype=np.uint8)
print(np.unpackbits(I[:, np.newaxis], axis=1))
Ruby:
i = Numo::NArray[0, 1, 2, 3, 15, 16, 32, 64, 128]
b = Numo::Int32.cast((i[true,:new] & (2**Numo::Int32.new(8).seq)).ne 0)
p b.reverse(1)
i = Numo::UInt8[0, 1, 2, 3, 15, 16, 32, 64, 128]
p Numo::Bit.from_binary(i.to_binary,[i.size,8]).reverse(1)
Python:
# Author: Jaime Fernández del Río
Z = np.random.randint(0,2,(6,3))
T = np.ascontiguousarray(Z).view(np.dtype((np.void, Z.dtype.itemsize * Z.shape[1])))
_, idx = np.unique(T, return_index=True)
uZ = Z[idx]
print(uZ)
Ruby:
# todo: unique row
97. Considering 2 vectors A & B, write the einsum equivalent of inner, outer, sum, and mul function (★★★)
Python:
# Author: Alex Riley
# Make sure to read: http://ajcr.net/Basic-guide-to-einsum/
A = np.random.uniform(0,1,10)
B = np.random.uniform(0,1,10)
np.einsum('i->', A) # np.sum(A)
np.einsum('i,i->i', A, B) # A * B
np.einsum('i,i', A, B) # np.inner(A, B)
np.einsum('i,j', A, B) # np.outer(A, B)
Ruby:
# no method: einsum
a = Numo::DFloat.new(10).rand(0,1)
b = Numo::DFloat.new(10).rand(0,1)
a.sum # np.sum(A)
a*b # A * B
a.mulsum(b) # np.inner(A, B)
a[false,:new]*b # np.outer(A, B)
98. Considering a path described by two vectors (X,Y), how to sample it using equidistant samples (★★★)?
Python:
# Author: Bas Swinckels
phi = np.arange(0, 10*np.pi, 0.1)
a = 1
x = a*phi*np.cos(phi)
y = a*phi*np.sin(phi)
dr = (np.diff(x)**2 + np.diff(y)**2)**.5 # segment lengths
r = np.zeros_like(x)
r[1:] = np.cumsum(dr) # integrate path
r_int = np.linspace(0, r.max(), 200) # regular spaced path
x_int = np.interp(r_int, r, x) # integrate path
y_int = np.interp(r_int, r, y)
Ruby:
# todo: interp
99. Given an integer n and a 2D array X, select from X the rows which can be interpreted as draws from a multinomial distribution with n degrees, i.e., the rows which only contain integers and which sum to n. (★★★)
Python:
# Author: Evgeni Burovski
X = np.asarray([[1.0, 0.0, 3.0, 8.0],
[2.0, 0.0, 1.0, 1.0],
[1.5, 2.5, 1.0, 0.0]])
n = 4
M = np.logical_and.reduce(np.mod(X, 1) == 0, axis=-1)
M &= (X.sum(axis=-1) == n)
print(X[M])
Ruby:
x = Numo::NArray[[1.0, 0.0, 3.0, 8.0],
[2.0, 0.0, 1.0, 1.0],
[1.5, 2.5, 1.0, 0.0]]
n = 4
m = (x%1).eq(0).all?(-1)
m &= x.sum(-1).eq(n)
p x[m.where,true]
100. Compute bootstrapped 95% confidence intervals for the mean of a 1D array X (i.e., resample the elements of an array with replacement N times, compute the mean of each sample, and then compute percentiles over the means). (★★★)
Python:
# Author: Jessica B. Hamrick
X = np.random.randn(100) # random 1D array
N = 1000 # number of bootstrap samples
idx = np.random.randint(0, X.size, (N, X.size))
means = X[idx].mean(1)
confint = np.percentile(means, [2.5, 97.5])
print(confint)
Ruby:
x = Numo::DFloat.new(100).rand_norm
n = 1000 # number of bootstrap samples
idx = Numo::Int32.new(n, x.size).rand(x.size)
means = x[idx].mean(1)
confint = means[means.sort_index[means.size/100.0*Numo::DFloat[2.5, 97.5]]]
p confint
# todo: percentile