100 numpy exercisesを解いてみた
100 numpy exercisesとは
numpyというpythonの有名なライブラリがあるのですが、その練習問題100題がgithubに公開されている。それが100 numpy exercisesです。サイトを下記に示す。
githubのリンク:https://github.com/rougier/numpy-100/
この中には
問題のみのファイル(100_Numpy_exercises.md)、
ヒント付きのファイル(100_Numpy_exercises_with_hints.md)、
解答付きのファイル(100_Numpy_exercises_with_soliutions.md)、
ヒント・解答付きのファイル(100_Numpy_exercises_with_hints_with_soliutions.md)があり、
それらをダウンロードしてからオフラインで学習するのも良いのではないか。
難易度は(★☆☆,★★☆,★★★)の3段階に分かれている。
##解いてみる。
まずは1~10
1. Import the numpy package under the name "np" (★☆☆)
numpyのパッケージをnpの名前でImportしなさいという問題
import numpy as np
で実行するとnumpyをnpとしてImportすることができる。
2. Print the numpy version and the configuration (★☆☆)
numpyのバージョンと構成をPrintしなさいという問題
print(np.__version__)
np.show_config()
これで、numpyのバージョンとconfigfileの場所が示すことができる。
3. Create a null vector of size 10 (★☆☆)
サイズ10の0ベクトルを作る問題
vector = np.zeros(10)
.zero
で零ベクトルを作ることができる(2次元以上も括弧を中に作ることで作成可能)。実行すると、大きさ10の零ベクトルがvectorに作られる。
4. How to find the memory size of any array (★☆☆)
いくつかの配列のメモリの大きさを見つける方法を示す問題。
vector = np.zeros((10, 10))
print(vector, vector.itemsize, vector.size)
print("{} bites".format(vector.size * vector.itemsize))
.itemsize
は1つの配列要素の長さをバイト単位で指定する属性
.size
は配列の大きさを指定する属性
であるのでそれぞれを掛けた積を配列のメモリの大きさとして出力した。
5. How to get the documentation of the numpy add function from the command line? (★☆☆)
コマンドラインからnumpy.add関数の文章を取得する方法を示す問題。
.info()
で各関数のヘルプ情報を取得するので
>command line
python
>>> import numpy as np
>>> np.info(np.add)
とコマンドラインに打ち込むと
add(x1, x2, /, out=None, *, where=True, casting='same_kind', order='K', dtype=None, subok=True[, signature, extobj])
Add arguments element-wise.
#(以下省略)
と出力される。
6. Create a null vector of size 10 but the fifth value which is 1 (★☆☆)
5番目の値が1だけのサイズが10の零行列を作る
vector = np.zeros(10)
vector[4] = 1
と先に10が大きさの零行列を作ってから5番目の値を1に変えることで作成することができる。
7. Create a vector with values ranging from 10 to 49 (★☆☆)
ranging:並べている
10から49までを並べた値のベクトルを作る
vector = np.arange(10,50)
.arange([n,]m)
で[n以上]m未満の順列を作成する。
forと同じで左側以上右側未満の数列なので+1する必要があることに注意する。
8. Reverse a vector (first element becomes last) (★☆☆)
ベクトルを反転させる問題。(最初の要素が最後の要素になる。)
vector = vector[::-1]
vector = np.fliplr([vector])[0] # 1次元
vector = np.filplr(vector) # 2次元から
.filp
、.filplr
を用いて反転することもできるが1次元の場合逆スライスを用いると簡単に反転ができる。(どのように反転するかによるが)
9. Create a 3x3 matrix with values ranging from 0 to 8 (★☆☆)
0から8までの順列の値を持った3×3の行列(matrix)を作る問題
vector = np.arange(9).reshape(3, 3)
np.arange(9)
で0から8までの順列を作成し、
reshape(3,3)
で3×3の行列に並べ替えることで求めるとこができる。
10. Find indices of non-zero elements from [1,2,0,0,4,0] (★☆☆)
[1,2,0,0,4,0]のベクトルから0ではない要素の
zero = np.nonzero([1, 2, 0, 0, 4, 0])
np.nonzero
を用いると何番目が0でないかを求めることができる。
11. Create a 3x3 identity matrix (★☆☆)
3×3の単位行列(identity matrix)を作成する問題。
np.eye(3) #np.identity(3)でも可
np.eye(n[,m])
はn行[m列,Noneの時はn列]の単位行列を作成することができる(正方行列以外でも作成可能)。
np.identity(n)
はn行n列の単位行列を作成することができる(正方行列以外は作成不可)。
12. Create a 3x3x3 array with random values (★☆☆)
3×3×3の乱数の行列を作成する。
vector = np.random.rand(3, 3, 3)
np.random.rand()
は0~1の間の小数の一様分布に則った乱数を作成し、np.random.randn
は正規分布に則った乱数の行列を作成する。
また、3×3×3の0以上10未満の乱数の行列を作成するときは
vector=np.random.randint(0,10,3**3).reshape(3,3,3)
と.reshape()
を用いる。
13. Create a 10x10 array with random values and find the minimum and maximum values (★☆☆)
10×10の乱数の行列を作成し、最小と最大の値の行列を作成する問題。
vector = np.random.rand(10, 10)
Max = vector.max()
Min = vector.min()
.max()
、.min()
を用いることで、行列の最大値と最小値を求めることが出来る。
14. Create a random vector of size 30 and find the mean value (★☆☆)
サイズが30の乱数の行列を作成し、平均値を求める問題
vector = np.random.rand(10, 10)
Mean = vector.mean()
.mean()
で行列の平均値を求めることが出来る。
.std()
で行列の標準偏差を求めることが出来る。
15. Create a 2d array with 1 on the border and 0 inside (★☆☆)
境界線が1、内側が0の2次元行列を作成する。
vector = np.ones((10, 10))
vector[1:-1] = 0
で割り出すことが出来る。また、非効率ではあるが、
.ones()
ではなく、.zeros()
用いて
vector = np.zeros((10, 10))
vector[0,:] = vector[:, -1] = vector[:, 0] = vector[-1,:] = 1
と求めることが出来る。
16. How to add a border (filled with 0's) around an existing array? (★☆☆)
既存の配列の周りに境界線(0で塗りつぶされた)を追加するには??
z = np.ones((5, 5))
z = np.pad(z, pad_width=1, mode='constant', constant_values=0)
既存の配列zに.pad()
を適応させることで、配列zに幅1値0を加えることができる。
17. What is the result of the following expression? (★☆☆)
次の式の結果は??
0 * np.nan >> nan
np.nan == np.nan >> False
np.inf > np.nan >> False
np.nan - np.nan >> nan
np.nan in set([np.nan]) >> True
0.3 == 3 * 0.1 >> False
np.nan
の取り扱いについて
np.nan
は配列の取得の際に起きてしまう不測の値である。また.np.inf
にnp.inf
を引いてしまう(-np.inf
を足す)と得られる。
np.nan
に何らかの四則演算をしても必ずnon
になってしまいます。
不測の値なのでnp.non
と比べても(比較演算をしても)値はFalse
を返します。
non
であるかを判定する際には'np.isnon()'を用いるかset()
を用いて集合に変換し、np.non
であるかを調べることで求めることができます。
最後の行は2進小数で表すときに表せない小数になった際誤差が発生する。例えば3*0.1=0.30000000000000004
となるのでFalse
になる。
18. Create a 5x5 matrix with values 1,2,3,4 just below the diagonal (★☆☆)
対角線の真下(just below)に1,2,3,4以下の値を持った行列を作成する問題。
z = np.diag(np.arange(5) + 1, k=-1)
np.diag()
を用いることで対角行列を作成することができる。2次行列を入れると対角成分を出力させるが、1次の行列を入力するとそれを対角成分とする行列を出力する。また、kの値だけ対角行列をずらすことができる。
19. Create a 8x8 matrix and fill it with a checkerboard pattern (★☆☆)
8×8の行列を作成し、すべてにチェックボードパターンを敷き詰める問題。
z = np.zeros((8, 8))
z[1::2,::2] = 1 #2番目から1つ飛ばしで1を代入を2つ飛ばし
z[::2, 1::2] = 1 #始点から1つ飛ばしで1を代入を2列目から2つ飛ばし
説明が下手ですがスライスをうまく用いるとチェックボードバターンを敷き詰めることができる。
20. Consider a (6,7,8) shape array, what is the index (x,y,z) of the 100th element?
(6,7,8)の形状の配列を考えてみる(consider)。100個目の(x,y,z)要素はなにか?
print(np.unravel_index(100,(6,7,8)))
np.unravel_index()
を活用して
21. Create a checkerboard 8x8 matrix using the tile function (★☆☆)
8×8のチェックボード配列をtile関数を用いて作成する。
Z = np.tile(np.array([[0, 1], [1, 0]]), (4, 4))
これで、([0,1],
[1,0])をタイルみたいに
配列(4,4)に並べるので、
[[0 1 0 1 0 1 0 1]
[1 0 1 0 1 0 1 0]
[0 1 0 1 0 1 0 1]
[1 0 1 0 1 0 1 0]
[0 1 0 1 0 1 0 1]
[1 0 1 0 1 0 1 0]
[0 1 0 1 0 1 0 1]
[1 0 1 0 1 0 1 0]]
とチェックボード配列を作成することができる。
22. Normalize a 5x5 random matrix (★☆☆)
5×5の乱数配列を正則化する問題
正規化とは機械学習の際に過学習を防ぐ際に行われる重みを小さい値に保つ方法であり、
z = np.random.random((5, 5))
x = np.random.random((5, 5))
#正則化
z = (z - np.min(z)) / (np.max(z) - np.min(z))
#標準化
x = (x - np.mean(x)) / np.std(x)
23. Create a custom dtype that describes a color as four unsigned bytes (RGBA) (★☆☆)
色を4つの符号なしバイトで表記するカスタムdtypeを作成する問題。
color = np.dtype([('r', np.ubyte, 1),
('g', np.ubyte, 1),
('b', np.ubyte, 1),
('a', np.ubyte, 1)])
24. Multiply a 5x3 matrix by a 3x2 matrix (real matrix product) (★☆☆)
5×3の行列に3×2の行列を乗算する(実数行列の積)
left = np.random.random((5, 3))
right = np.random.random((3, 2))
ans = np.dot(left, right)
ans = left.dot(right) #同義
np.dot
で配列の内積を出力する
25. Given a 1D array, negate all elements which are between 3 and 8, in place. (★☆☆)
1次元の配列が与えられたときその場で3から8までの空いたのすべての要素を否定します。
Z = np.array(range(10))
Z[(3 < Z) & (Z < 8)] *= -1 # 3と8の間を-1する
とするとZ配列は
[ 0 1 2 3 -4 -5 -6 -7 8 9]
26. What is the output of the following script? (★☆☆)
出力される次のスクリプトは何か。
print(sum(range(5), -1)) #sum([配列](,始点))最後に始点の値を足す
from numpy import *
print(sum(range(5), -1)) #np.sum([配列](,軸))
組み込み関数とnumpyで仕様が異なるので値も異なる
27. Consider an integer vector Z, which of these expressions are legal? (★☆☆)
整数の行列Zを考える。これらの表現のうち、どれが適してるか?
Z = np.array([1,2,3])
# 各要素の累乗の形
Z**Z #[ 1 4 27]
# シフト演算 2bit左に移動してから2bit右に移動したときの値
2 << Z >> 2 #[1 2 4]
# 全体を否定し各要素と比べる
Z < - Z #[False False False]
# 各要素を虚数方向の大きさに。
1j*Z #[0.+1.j 0.+2.j 0.+3.j]
#
Z/1/1 #[1. 2. 3.]
Z < Z > Z #Traceback (most recent call last):
28. What are the result of the following expressions?
次の計算の答えは何?
np.array(0) / np.array(0) #RuntimeWarning: invalid value encountered in true_divide
np.array(0) // np.array(0) #RuntimeWarning: invalid value encountered in true_divide
np.array([np.nan]).astype(int).astype(float) #[-2.14748365e+09]
0での除算はできないので上二つは0除算エラーを吐く
3番目はnp.nanの型を強制的にint型にするとint型の最小値-2147483648になり、float型にすると桁が10桁以上なのでa+enで10の累乗の形で表される。
29. How to round away from zero a float array ? (★☆☆)
どのようにfloatの配列を0から離れるように小数点を切るか。
絶対値にして小数点以下を切り上げして、符号を付け足すことで求めることができる。
Z = np.random.uniform(-10, 10, 10)
# np.copysign(a, b) aにbの符号を付け足す。
print(np.copysign(np.ceil(abs(Z)),Z))
そのままnp.ceilを行うと負の数が0から近づくので絶対値にしてから切り上げを行い、符号をつけると条件を満たす。
30. How to find common values between two arrays? (★☆☆)
二つの配列の間の共通な値を見つける方法
one = np.random.randint(0, 10, 10)
two = np.random.randint(0, 10, 10)
print(np.intersect1d(one, two))
intrsect:交差する
np.intrsect1d
で配列の共通要素を抜き出す。
31. How to ignore all numpy warnings (not recommended)? (★☆☆)
すべてのnumpyの警告を無視する方法(推奨されていない)
recommend:推奨する
ignore:無視する
a = np.array(0)
#warning.simplefilterを用いて警告を無視する方法
warnings.simplefilter('ignore',category=RuntimeWarning)
print(1 / a)
#np.seterrを用いる方法(これだと0除算エラーのみ)
np.seterr(divide='ignore')
print(1 / a)
# np.errstate()を用いて0除算エラーを無視する方法
with np.errstate(divide='ignore'):
divide = 1 / a
print(divide)
一番上のコードはコード全体にRuntimeWarning
を無視する方法
二番上のコードはコード全体にRuntimeWarning
の中のゼロ除算エラーを(divide='ignore')引数で指定し、無視するように設定することが可能
三番目のコードはwith文とnp.errstate
を用いることでwith文下の命令文でしか適応させない設定することができます。
32. Is the following expressions true? (★☆☆)
次の式は真ですか?
np.sqrt(-1) == np.emath.sqrt(-1)
>>False
\sqrt{-1}=1i\\
であることは複素数を学んでいる人は理解出来るが、np.sqrt()
を使うと出力が実数しかなく虚数で返すことが出来ないため、Runtimeerror
を吐き、nonを出力する。
また、複素数を返すのがnp.emath.sqrt()
を用いると複素数で表すことが出来るので、0+j1を出力する。
non
と0+j1
は同じではないのでよってFalse
を返す
33. How to get the dates of yesterday, today and tomorrow? (★☆☆)
昨日、今日、明日のデータの入手方法とは
Today = np.datetime64('today', 'D')
Yesterday = Today - np.timedelta64(1, 'D')
Tomorrow = Today + np.timedelta64(1, 'D')
print(Yesterday, Today, Tomorrow)
np.datetime('today',"D")
を用いることで今日の日付を[第二変数によって年、月、日]取り出すことが出来る。また"today"を任意な整数に置き換えると1970-01-01に第二変数の値を足した値を出力する。
34. How to get all the dates corresponding to the month of July 2016? (★★☆)
2016年6月に対応した全ての日を得る方法
dates = np.arange("2016-06", '2016-07', dtype='datetime64[D]')
print(dates)
データ型を指定することで、2016年6月から2016年7月まで(含まれない)の日付を出力することが出来る。
35. How to compute ((A+B)*(-A/2)) in place (without copy)? (★★☆)
その場で(copy無しで)((A+B)*(-A/2))を割り出す方法を求める。
A = np.ones(3) * 1
B = np.ones(3) * 2 #適当な配列
print((A + B) * (-A / 2)) #愚直に実行
np.add(A, B, out=B) #+ AとBを足しBに出力
np.divide(A, 2, out=A) #/ Aと2の商をA出力
np.negative(A, out=A) #- Aを負に出力
np.multiply(A, B,out=A) #* AとBの積をAに出力
print(A)
36. Extract the integer part of a random array using 5 different methods (★★☆)
5つの違った方法をを用いて乱数の整数部分を抜き出す方法
Z = np.random.uniform(0, 10, 10) #適当な乱数
print(Z)
print(Z - Z % 1) #1桁目以外の小数を引く
print(np.ceil(Z) - 1) #切り上げ-1する
print(Z.astype(int)) #dtype(int) 配列の要素をint型に変換する
print(np.floor(Z)) #切り捨て(小数部分を取り除く)
print(np.trunc(Z)) #切り捨て(小さな部分の整数に丸める)
以上の方法で求めることが出来る。
37. Create a 5x5 matrix with row values ranging from 0 to 4 (★★☆)
5×5の0から5までの範囲の行の値を持った5×5の行列を作成する問題
Z = np.zeros((5, 5)) #零行列を作成する
Z += np.arange(5)
#+=[0,1,2,3,4]が
#ブロードキャストするので列が一致していれば良い。(条件あり)
print(Z)
np.arange(n)
でn以下の順列を作成する。
38. Consider a generator function that generates 10 integers and use it to build an array (★☆☆)
10個の整数を生成する関数を考える
def genereate():
for x in range(10):
yield x #yield:一旦関数内の動作を一時停止してxを出力
Z = np.fromiter(generate(),dtype=float,count=-1)
ここで特記することはyield
とfromiter
である.
yieldは基本的に関数の中で用いられ,一旦関数内の動作を一時停止して値を返す.
関数内の動作を停止して値を返すreturnと異なって,値を返した後,処理が再開されるのでメモリの消費が抑えられる.
np.fromiterはiterableからobjectから新しい一次元配列を作成する.関数でdtypeは配列の要素の型,countはiterableから読み取る要素の値をそれぞれとしてある,
39. Create a vector of size 10 with values ranging from 0 to 1, both excluded (★★☆)
0,1を除く0から1までの値を持つサイズ10のベクトルを作成する
Z = np.linspace(0,1,11,endpoint=False)[1:]
print(Z)
#[0.09090909 0.18181818 0.27272727 0.36363636 0.45454545 0.54545455 0.63636364 0.72727273 0.81818182 0.90909091]
全体が等差数列であるベクトルを作成する方法としてarange
とlinspace
がある.
arangeは引数の考え方がrange()
と同様に初期値[初期値は0]と最終値と間隔(公差)[初期値は1]を適切に選択することで
初期値から始まり最終値で終わるベクトルを作成するとことが出来る.
また,linspaceは間隔(公差)ではなく要素数を設定する,
この問題では0と1を含まない大きさ10のベクトルを作成するのでnp.linspaceのendpointをFalseにすることで最終値を含まないベクトルを作成することが出来る.
また,初期値を削除するため,1つ多い大きさのベクトルを作成し.[1:]で0番目の要素である0を排除することで0,1を含まない大きさ10のベクトルを作成することが出来る.
40. Create a random vector of size 10 and sort it (★★☆)
ソートされたサイズが10の乱数ベクトルを作成する.
Z = np.random.random(10)
Z.sort()
print(Z)
np.random.random(size)
で0より大きく1より小さいベクトルをsize分だけ作成することが出来る.また,list.sort()
[listは型]はlist内容を降順にソートするpythonの組み込み関数である.
#最後に
今回は1から40までのnumpyについての基本的な操作を理解するための問題を解いた.
今後,41から100までを解いていきたいです.
皆さんも良かったら基礎が復習できるので暇な時間にでも解いて見ると良いのではないでしょうか?