こんにちは!
前回はnumpy力を鍛えるために41~50問をやっていきました。
前回の記事はこちら
それでは前回に引き続き100 numpy exercisesを使ってnumpyの学習をしていきたいと思います!
今回は51~60問をやっていきます。
###51. Create a structured array representing a position (x,y) and a color (r,g,b) (★★☆)
#####51. 位置(x,y)と色(r,g,b)を表す構造化された配列を作成する
Z = np.zeros(10, [ ('position', [ ('x', float, 1),
('y', float, 1)]),
('color', [ ('r', float, 1),
('g', float, 1),
('b', float, 1)])])
print(Z)
上記のコードはfloat型の数値を持つ配列を要素に持つ構造化配列を作成します。構造化配列を作っておけば、簡単なコードで色々なデータを取り出すことができます。
実行結果は以下の通りです。
[((0., 0.), (0., 0., 0.)) ((0., 0.), (0., 0., 0.))
((0., 0.), (0., 0., 0.)) ((0., 0.), (0., 0., 0.))
((0., 0.), (0., 0., 0.)) ((0., 0.), (0., 0., 0.))
((0., 0.), (0., 0., 0.)) ((0., 0.), (0., 0., 0.))
((0., 0.), (0., 0., 0.)) ((0., 0.), (0., 0., 0.))]
###52. Consider a random vector with shape (100,2) representing coordinates, find point by point distances (★★☆)
#####52. 座標を表す形状(100,2)のランダムなベクトルを考え、点と点の距離を求める
Z = np.random.random((10,2))
X,Y = np.atleast_2d(Z[:,0], Z[:,1])
D = np.sqrt( (X-X.T)**2 + (Y-Y.T)**2)
print(D)
np.random.random
で(10, 2)
の二次元配列を生成します。np.atleast_2d
で入力された配列をX
,Y
の2つの二次元配列として生成します。2点間の距離の公式を使って(X,Y)
,(X.T, Y.T)
間の距離を求めます。そうすると2点間の距離が100個求まります。
実行結果は以下の通りです。
[[0. 0.6060765 0.40413331 0.49307252 0.10412311 0.36386293
0.52039787 0.33679798 0.41173638 0.63203753]
[0.6060765 0. 0.34389387 0.63998092 0.6437951 0.69211375
0.98402659 0.3863142 0.34481216 0.2826146 ]
[0.40413331 0.34389387 0. 0.30181901 0.48790107 0.35431183
0.6527074 0.42000667 0.00828523 0.23475134]
[0.49307252 0.63998092 0.30181901 0. 0.59708376 0.17966471
0.43859746 0.66966905 0.29895121 0.44140839]
[0.10412311 0.6437951 0.48790107 0.59708376 0. 0.4655664
0.59479412 0.31852055 0.49588384 0.70715854]
[0.36386293 0.69211375 0.35431183 0.17966471 0.4655664 0.
0.30030062 0.61592342 0.3557692 0.55594391]
[0.52039787 0.98402659 0.6527074 0.43859746 0.59479412 0.30030062
0. 0.84115716 0.65469067 0.85487456]
[0.33679798 0.3863142 0.42000667 0.66966905 0.31852055 0.61592342
0.84115716 0. 0.42755679 0.55940182]
[0.41173638 0.34481216 0.00828523 0.29895121 0.49588384 0.3557692
0.65469067 0.42755679 0. 0.22856936]
[0.63203753 0.2826146 0.23475134 0.44140839 0.70715854 0.55594391
0.85487456 0.55940182 0.22856936 0. ]]
ちなみにscipy
を使うとより早い計算ができるらしいので、実際に使う際にはそちらを使った方がいいかもしれないです。
###53. How to convert a float (32 bits) array into an integer (32 bits) in place? (★★☆)
#####53. float(32ビット)の配列をinteger(32ビット)に逐次変換するには?
Z = (np.random.rand(10)*100).astype(np.float32)
Y = Z.view(np.int32)
Y[:] = Z
print(Y)
ここではview
というものを使います。view
は元の配列と同じメモリを参照している配列要素を複製します。似ているものとしてcopy
があるのですが、copy
は元の配列と違うメモリを使用しているので、データ型を変えてもメモリに存在する元の配列に影響はありません。
Z.view
でint型に変えられた値は小数点以下の数値も全て整数に変換されてしまうため、Y
の要素にZ
を代入することによってZの整数部分だけの配列とすることができます。
実行結果は以下の通りです。
[97 73 73 3 11 36 90 61 95 64]
###54. How to read the following file? (★★☆)
#####54. 次のファイルを読むには?
from io import StringIO
s = StringIO('''1, 2, 3, 4, 5
6, , , 7, 8
, , 9,10,11
''')
Z = np.genfromtxt(s, delimiter=",", dtype=np.int)
print(Z)
文字列をファイルとして扱うには、StringIO
が使えます。まずioモジュールをインポートし、StringIOインスタンスを作成します。これで文字列ファイルを作成できました。ファイルを読み込むには、np.genfromtxt
を使います。np.genfromtxt
は欠損値を含んでいたり複数の異なるデータ型を含んでいたりする、より複雑な構造のCSVファイルの読み込みが可能です。区切り文字に,
を設定しています。
実行結果は以下の通りです。
[[ 1 2 3 4 5]
[ 6 -1 -1 7 8]
[-1 -1 9 10 11]]
数値が入力された所には、-1が入ってますね。よくわかりませんが笑笑
###55. What is the equivalent of enumerate for numpy arrays? (★★☆)
#####55. numpyの配列でenumerateに相当するものは何ですか?
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])
np.ndenumerate
,np.index
でenumerate
と同様の動きができるようです。2つの違いはnp.ndenumerate
は配列、np.ndindex
は配列の形状を引数に使うようです。
実行結果は以下の通りです。
(0, 0) 0
(0, 1) 1
(0, 2) 2
(1, 0) 3
(1, 1) 4
(1, 2) 5
(2, 0) 6
(2, 1) 7
(2, 2) 8
(0, 0) 0
(0, 1) 1
(0, 2) 2
(1, 0) 3
(1, 1) 4
(1, 2) 5
(2, 0) 6
(2, 1) 7
(2, 2) 8
###56. Generate a generic 2D Gaussian-like array (★★☆)
#####56. 一般的な2Dガウス状の配列を生成する
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)
np.meshgrid
はx,y,...の各座標の要素列から格子座標を作成するために使います。2Dガウス状の配列を生成するにはガウス分布を持つ一次元ベクトルの多重配列をガウスの式に当てはめればいいので上記のようになります。
実行結果は以下の通りです。
[[0.36787944 0.44822088 0.51979489 0.57375342 0.60279818 0.60279818
0.57375342 0.51979489 0.44822088 0.36787944]
[0.44822088 0.54610814 0.63331324 0.69905581 0.73444367 0.73444367
0.69905581 0.63331324 0.54610814 0.44822088]
[0.51979489 0.63331324 0.73444367 0.81068432 0.85172308 0.85172308
0.81068432 0.73444367 0.63331324 0.51979489]
[0.57375342 0.69905581 0.81068432 0.89483932 0.9401382 0.9401382
0.89483932 0.81068432 0.69905581 0.57375342]
[0.60279818 0.73444367 0.85172308 0.9401382 0.98773022 0.98773022
0.9401382 0.85172308 0.73444367 0.60279818]
[0.60279818 0.73444367 0.85172308 0.9401382 0.98773022 0.98773022
0.9401382 0.85172308 0.73444367 0.60279818]
[0.57375342 0.69905581 0.81068432 0.89483932 0.9401382 0.9401382
0.89483932 0.81068432 0.69905581 0.57375342]
[0.51979489 0.63331324 0.73444367 0.81068432 0.85172308 0.85172308
0.81068432 0.73444367 0.63331324 0.51979489]
[0.44822088 0.54610814 0.63331324 0.69905581 0.73444367 0.73444367
0.69905581 0.63331324 0.54610814 0.44822088]
[0.36787944 0.44822088 0.51979489 0.57375342 0.60279818 0.60279818
0.57375342 0.51979489 0.44822088 0.36787944]]
###57. How to randomly place p elements in a 2D array? (★★☆)
#####57. 2D配列にp個の要素をランダムに配置するには?
n = 10
p = 3
Z = np.zeros((n,n))
np.put(Z, np.random.choice(range(n*n), p, replace=False),1)
print(Z)
まず特定の範囲からランダムな数字を選ぶためにnp.random.choice
を使います。第一引数に値の範囲、第二引数に何個選ぶか、第3引数のreplace
はデフォルトではTrue
ですが、同じ値を選ばないためにFalse
にしておきます。値を置き換える関数として、np.put
を使います。第一引数に置き換えたい配列、第二引数にランダムに選ばれた数字の配列、第三引数に置き換える数字が入ります。
実行結果は以下の通りです。
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
###58. Subtract the mean of each row of a matrix (★★☆)
#####58. 行列の各行の平均値を引きます
X = np.random.rand(5, 10)
Y = X - X.mean(axis=1, keepdims=True)
print(Y)
各行の平均値はnp.mean
のaxis
を1にすることで求められます。keepdims
をTrue
にすればreshape
をする必要がなくなりそのまま計算に移れます。
実行結果は以下の通りです。
[[ 0.37333021 0.14818213 -0.17776424 -0.02976235 -0.30472966 0.21828251
-0.0952619 0.19063885 -0.42395379 0.10103823]
[ 0.10851469 -0.48779044 -0.23011103 -0.24256646 0.11941821 0.37498574
-0.47534218 0.30533606 0.37791314 0.14964229]
[-0.13118259 -0.32867068 0.18038018 0.02444958 -0.04725876 -0.26589785
0.37444314 0.33571181 -0.31668501 0.17471018]
[ 0.12539266 0.03421996 -0.16533064 0.25065169 0.11262873 -0.250109
0.05621285 0.14263656 -0.13638187 -0.16992094]
[ 0.39663391 -0.23377007 0.12086686 -0.08139474 -0.1618067 -0.39339115
-0.15129964 -0.25654682 0.22949898 0.53120939]]
###59. How to sort an array by the nth column? (★★☆)
#####59. 配列をn番目の列でソートするには?
Z = np.random.randint(0,10,(3,3))
print(Z)
print(Z[Z[:,1].argsort()])
任意の列でソートするにはargsort
を使うのが良いです。上記のコードは2番目の列を基準に昇順にソートされています。
実行結果は以下の通りです。
Z = np.random.randint(0,10,(3,3))
print(Z)
print(Z[Z[:,1].argsort()])
###60. How to tell if a given 2D array has null columns? (★★☆)
#####60. 与えられた2D配列にNULL列があるかどうかを見分けるには?
Z = np.random.randint(0,3,(3,10))
print((~Z.any(axis=0)).any())
any
はNULL列があるかどうか見分けるのに使えます。
実行結果は以下の通りです。
False
今回は以上になります。
次回は61~70問をやっていきます。