100 numpy exercises(61 – 70)

numpyの理解を深めるために100問エクササイズに挑戦してみました。

今回は61問目から70問目までです。

61. Find the nearest value from a given value in an array.

Z = np.random.uniform(0,1,10)
print(Z)

z = 0.5
print(np.abs(Z - z).argmin())

m = Z.flat[np.abs(Z - z).argmin()]
print(m)
[0.27576656 0.4030415  0.52931972 0.09513933 0.54607919 0.81908521 0.96007619 0.2462154  0.11258337 0.03125006]

2

0.5293197200423708

62. Considering two arrays with shape (1,3) and (3,1), how to compute their sum using an iterator?

A = np.arange(3).reshape(3,1)
print(A)

B = np.arange(3).reshape(1,3)
print(B)

it = np.nditer([A,B,None])
for x,y,z in it: z[...] = x + y
print(it.operands[2])
[[0]
 [1]
 [2]]

[[0 1 2]]

[[0 1 2]
 [1 2 3]
 [2 3 4]]

63. Create an array class that has a name attribute.

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)
range_10

64. Consider a given vector, how to add 1 to each element indexed by a second vector (be careful with repeated indices)?

Z = np.ones(10)
print(Z)

I = np.random.randint(0,len(Z),20)
print(I)

Z += np.bincount(I, minlength=len(Z))
print(Z)
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]

[0 2 2 7 4 0 9 9 4 1 5 8 1 1 0 2 5 9 9 6]

[4. 4. 4. 1. 3. 3. 2. 2. 2. 5.]

65. How to accumulate elements of a vector (X) to an array (F) based on an index list (I)?

X = [1,2,3,4,5,6]
I = [1,3,9,3,4,1]
F = np.bincount(I,X)
print(F)
[0. 7. 0. 6. 5. 0. 0. 0. 0. 3.]

66. Considering a (w,h,3) image of (dtype=ubyte), compute the number of unique colors.

w, h = 256, 256
I = np.random.randint(0, 4, (h, w, 3)).astype(np.ubyte)
colors = np.unique(I.reshape(-1, 3), axis=0)
n = len(colors)
print(n)
64

67. Considering a four dimensions array, how to get sum over the last two axis at once?

A = np.random.randint(0,10,(3,4,3,4))
# solution by passing a tuple of axes (introduced in numpy 1.7.0)
sum = A.sum(axis=(-2,-1))
print(sum)
# solution by flattening the last two dimensions into one
# (useful for functions that don't accept tuples for axis argument)
sum = A.reshape(A.shape[:-2] + (-1,)).sum(axis=-1)
print(sum)
[[52 65 59 52]
 [37 44 78 65]
 [47 42 46 40]]

[[52 65 59 52]
 [37 44 78 65]
 [47 42 46 40]]

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?

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)
[0.59106947 0.48393144 0.39774691 0.55092921 0.54903803 0.40256009 0.54447985 0.31561391 0.43108683 0.5625863 ]

69. How to get the diagonal of a dot product?

A = np.random.uniform(0,1,(5,5))
B = np.random.uniform(0,1,(5,5))

# Slow version
print(np.diag(np.dot(A, B)))

# Fast version
print(np.sum(A * B.T, axis=1))

# Faster version
print(np.einsum("ij,ji->i", A, B))
[2.43058829 1.88526771 1.01422527 1.45964625 1.12584508]

[2.43058829 1.88526771 1.01422527 1.45964625 1.12584508]

[2.43058829 1.88526771 1.01422527 1.45964625 1.12584508]

70. Consider the vector [1, 2, 3, 4, 5], how to build a new vector with 3 consecutive zeros interleaved between each value?

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)
[1. 0. 0. 0. 2. 0. 0. 0. 3. 0. 0. 0. 4. 0. 0. 0. 5.]

次回は71〜80問目に挑戦してみます。