:download:`download notebook <../ipynb_files/pythonの基本.ipynb>` Pythonの基本 ============ (Colab only) このノートブックの内容は自由に編集,事項していただいて構いません 本ノートブックは統計学を学上で最低限の知識を著者の偏見でまとめたものです. もしpythonに公式ドキュメントを参照したい場合は日本語翻訳がありますので - https://docs.python.org/ja/3/ を参照することができます.公式のpythonチュートリアルもありますが,内容はかなり膨大です. - https://docs.python.org/ja/3/tutorial/index.html § 1 数の基本演算 ---------------- pythonにおける数の四則演算は加法演算子:\ ``+``\ ,減法演算子:\ ``-``\ ,乗法演算子:\ ``*``\ ,\ *除法演算子*\ (÷):\ ``/``\ で与えれます.まずは電卓としてpythonを使ってみよう .. raw:: html
In:
.. code-block:: ipython 1 + 2 .. raw:: html
.. parsed-literal:: 3 .. raw:: html
In:
.. code-block:: ipython 2 - 3 .. raw:: html
.. parsed-literal:: -1 .. raw:: html
In:
.. code-block:: ipython 4 * 5 .. raw:: html
.. parsed-literal:: 20 .. raw:: html
In:
.. code-block:: ipython 1 / 3 .. raw:: html
.. parsed-literal:: 0.3333333333333333 pythonで虚数単位\ :math:`i=\sqrt{-1}`\ は\ ``1j``\ :math:`(\neq j)`\ で表され,複素数\ :math:`1 + 2\mathrm{i}`\ は次のように表記します. .. raw:: html
In:
.. code-block:: ipython 1 + 2j .. raw:: html
.. parsed-literal:: (1+2j) 複数の計算を一つのコードセルにまとめ記載することも可能です. .. raw:: html
In:
.. code-block:: ipython 4 + 4 5 + 5 .. raw:: html
.. parsed-literal:: 10 **注意** 複数のコードを1つのコードセルに記載した場合,コードセルの実行で出力されるものは最後の行の結果のみであるということに注意してください.最終行以外も出力したい場合は明示的に以下のようにする必要があります. .. raw:: html
In:
.. code-block:: ipython print(4 + 4) print(5 + 5) .. raw:: html
.. parsed-literal:: 8 10 これらの四則演算を組み合わせて複雑な式を評価することも可能です.括弧がない式において,乗法と除法は加法と減法より先に計算されます. .. raw:: html
In:
.. code-block:: ipython 5 + 5 * 5 .. raw:: html
.. parsed-literal:: 30 明示的に括弧をつけると演算の順番を変更することができます .. raw:: html
In:
.. code-block:: ipython (5 + 5) * 5 .. raw:: html
.. parsed-literal:: 50 数学では不要な括弧は省略されますが,プログラミングにおいて括弧は重要で省略してはならない場合が多いです.例えば\ :math:`\frac{3 + 3}{1 + 2} = 2`\ をプログラミンで評価したい場合は次のように表記します .. raw:: html
In:
.. code-block:: ipython (3 + 3) / (1 + 2) .. raw:: html
.. parsed-literal:: 2.0 もし,括弧を省略すると .. raw:: html
In:
.. code-block:: ipython 3 + 3 / 1 + 2 .. raw:: html
.. parsed-literal:: 8.0 は\ :math:`3 + \frac{3}{1} + 2 = 8`\ と解釈され .. raw:: html
In:
.. code-block:: ipython 3 + 3 /(1 + 2) .. raw:: html
.. parsed-literal:: 4.0 は\ :math:`3 + \frac{3}{1+2} = 4`\ と解釈されてしまう. ちなみに除算(÷):\ ``/``\ を含む式を実行すると結果は小数点表記(浮動小数点)で表示されていることに気がつくであろうか. 整数(Integer)同士について加法,減法,乗法の演算結果は整数であるが,除法は一般に整数ではなく有理数になる.コンピューターでは一般に有理数(と無理数)を含めた数を浮動小数(Float)で扱い,整数はIntegerとして明確に区別する.整数はint型(type),浮動小数はfloat型として扱う.コード中で\ ``1``\ とした場合はint型の1を意味し,\ ``1.0``\ とした場合はFloatの型の\ ``1.0``\ を意味します.型の調べ方は ``type`` 関数を利用することで可能です. .. raw:: html
In:
.. code-block:: ipython type(1), type(1.0) .. raw:: html
.. parsed-literal:: (int, float) 整数除算(例えば\ :math:`\frac{5}{2} = 2` 余り\ :math:`1`\ )の計算を行いたい場合は 整数除算演算子:\ ``//``\ ,余りは剰余演算子:\ ``%``\ で求めることができます .. raw:: html
In:
.. code-block:: ipython 5 // 2, 5 % 2 .. raw:: html
.. parsed-literal:: (2, 1) 冪乗の計算は指数演算子\ ``**``\ を用います.例えば\ :math:`2^4=16`\ は .. raw:: html
In:
.. code-block:: ipython 2 ** 4 .. raw:: html
.. parsed-literal:: 16 指数が複数の式で構成される場合も必ず括弧を付けてください.例えば,\ :math:`2^{2 + 1}`\ の計算の場合 .. raw:: html
In:
.. code-block:: ipython 2 ** (2 + 1) .. raw:: html
.. parsed-literal:: 8 ですが,括弧を付けないと .. raw:: html
In:
.. code-block:: ipython 2 ** 2 + 1 .. raw:: html
.. parsed-literal:: 5 これは\ :math:`2^2 + 1`\ を意味します.\ :math:`10^{~3}`\ は\ ``10**3``\ ともかけますが\ ``1e3``\ と書くこともできます.この表記は\ :math:`1\times\mathrm{e}3`\ を意味し,eは底が10の指数(exponent)の頭文字で指数が3であることを意味しています.\ ``3e2``\ と書いた時は\ :math:`3\times 10^{2} = 300`\ を意味します.\ ``4e-3``\ と書いた時は\ :math:`1\times 10^{-3} = 1/1000 = 0.001`\ を表します. .. raw:: html
In:
.. code-block:: ipython print(1e3) print(3e2) print(1e-3) .. raw:: html
.. parsed-literal:: 1000.0 300.0 0.001 § 2 変数と代入 -------------- 一つ前のセクションではpythonを電卓として利用したが,コードを書く上で変数を使えた方が便利である.変数\ :math:`x`\ に1を代入する操作は代入演算子:\ ``=``\ で実現し .. raw:: html
In:
.. code-block:: ipython x = 1 x .. raw:: html
.. parsed-literal:: 1 上のコードで1行目は 変数\ ``x`` に 1を代入する.1行目の出力は何もないため,2行目を追記してで\ ``x``\ に代入された値を表示させている.2行目のコードを明示的に\ ``print(x)``\ としても良い. **注意** プログラミングにおける“\ :math:`=`\ ”は右辺の評価を左辺に代入する操作を意味し,数学の等号“\ :math:`=`\ ”(等しい)とは異なる. 例えば\ :math:`x`\ を数として,数学では式\ :math:`x=x+1`\ は\ :math:`0=1`\ となり矛盾するため式\ :math:`x=x+1`\ は偽の命題である. 一方プログラミングにおいて\ :math:`x=x+1`\ は右辺の変数\ :math:`x`\ の値に1を加え,その結果を左辺の変数\ :math:`x`\ に再代入(上書き)する操作を意味する. .. raw:: html
In:
.. code-block:: ipython x = x + 1 x .. raw:: html
.. parsed-literal:: 2 他方\ :math:`x + 1 = 2`\ のような表記は左辺が“\ :math:`x+1`\ ”を一括りとした変数として扱えないのでプログラミングではSyntaxError(構文エラー)となる. .. raw:: html
In:
.. code-block:: ipython (x + 1) = 2 .. raw:: html
:: File "/tmp/ipython-input-21-2315787992.py", line 1 (x + 1) = 2 ^ SyntaxError: cannot assign to expression here. Maybe you meant '==' instead of '='? 変数は1文字以外でもよく,下記は”\ :math:`abc`\ ” (:math:`\neq a\times b\times c`)という3文字の変数名に3を代入する操作である. .. raw:: html
In:
.. code-block:: ipython abc = 3 .. raw:: html
一般に変数に何らかの意味がある場合は,その意味がわかるような意味がある場合は,意味がわかるような変数名をつけるべきだが,変数名にスペースを含めることはできない.そのため複数の単語を繋ぐ場合は\ ``_``\ などでつなげたり,単語の1文字目を大文字にしたり,思い切って\ ``temporal -> tmp; argument -> arg``\ のように省略したりする工夫が必要である.なお\ ``-``\ は引き算を意味するため利用できない. 変数の略記(Abbriviation)は\ `Abbreviations in code `__\ などが参考になるであろうが,絶対的な基準がある訳ではないので固執する必要性はない. .. raw:: html
In:
.. code-block:: ipython this_is_a_extreamly_marvelous_important_number = 1 ThisIsAExtreamlyMarvelousImportantNumber = 1 .. raw:: html
意味を持たない(使い捨てるような)変数で値が実数ならば\ :math:`x`\ ,\ :math:`y`\ ,\ :math:`z`\ などを用い,値が整数ならば\ :math:`i`\ ,\ :math:`j`\ ,\ :math:`k`\ ,\ :math:`l`\ などを利用する場合が多い.記号\ ``j``\ は単独で使うと変数を意味するが\ ``2j``\ のように数字が\ ``j``\ の前についていると複素数を意味することに注意が必要である. .. raw:: html
In:
.. code-block:: ipython j = 3 j .. raw:: html
.. parsed-literal:: 3 .. raw:: html
In:
.. code-block:: ipython 2j, type(2j) .. raw:: html
.. parsed-literal:: (2j, complex) § 3 比較演算子 -------------- プログラミングにおいて\ ``=``\ は右辺の評価を左辺の変数に代入する代入演算子であった. では,左辺と右辺が等しいかどうか比較したい場合は,比較演算子:\ ``==``\ を用る.比較演算子は比較した結果が「真」であればTrueを返し,「偽」であればFalseを返す. .. raw:: html
In:
.. code-block:: ipython 3 + 2 == 5 .. raw:: html
.. parsed-literal:: True .. raw:: html
In:
.. code-block:: ipython 3 + 2 == 4 .. raw:: html
.. parsed-literal:: False 代表的な比較演算子は - ``==``\ :等しい - ``!=``\ :等しくない - ``<`` :右辺の方が大きい - ``>`` :左辺の方が大きい - ``<=`` :右辺の方が大きいか等しい(:math:`\leqq`) - ``>=`` :左辺の方が大きいかか等しい(:math:`\geqq`) .. raw:: html
In:
.. code-block:: ipython a = 3 b = 4 a <= b .. raw:: html
.. parsed-literal:: True .. raw:: html
In:
.. code-block:: ipython b > a .. raw:: html
.. parsed-literal:: True 上の例題わかるように,式の比較はTrue/Falseのいずれかを返す論理命題になっています.論理命題A,Bいずれも真であればTrue,A,Bのいずれかが偽であればFalseを返す論理式は ``A & B`` (AかつB) で与えられ AまたはBが真であればTrue,A,Bいずれも偽であればFalseを返す論理式は ``A | B`` (AまたはB) で与えることができます.\ ``&`` や ``|`` をで式を比較する場合は必ず括弧()で論理式をくくる必要があります. .. raw:: html
In:
.. code-block:: ipython (3 < 5) & (5 < 7) .. raw:: html
.. parsed-literal:: True .. raw:: html
In:
.. code-block:: ipython (3 < 5) & (8 < 7) .. raw:: html
.. parsed-literal:: False .. raw:: html
In:
.. code-block:: ipython (3 < 5) | (8 < 7) .. raw:: html
.. parsed-literal:: True .. raw:: html
In:
.. code-block:: ipython (6 < 5) | (8 < 7) .. raw:: html
.. parsed-literal:: False § 4 関数 -------- § 4.1 定義済み関数 ~~~~~~~~~~~~~~~~~~ $:raw-latex:`\sin `x, :raw-latex:`\cos`, e^x (= :raw-latex:`\exp `x), :raw-latex:`\log `x $など基本的な数学関数は\ `numpy `__\ と呼ばれるパッケージで関数が定義されています.pythonでパッケージを利用するには ``import as ``\ のようにしてパッケージをインポートする必要があります.ニックネームはつけなくても構いませんが,\ ``numpy``\ は\ ``np``\ と省略するのが一般的です. .. raw:: html
In:
.. code-block:: ipython import numpy as np .. raw:: html
``numpy``\ で定義された関数を呼び出すには\ ``np.sin(0)``\ のようにします. .. raw:: html
In:
.. code-block:: ipython print( np.sin(0) ) print( np.cos(0) ) .. raw:: html
.. parsed-literal:: 0.0 1.0 平方根(square root)は\ ``np.sqrt``\ もしくは\ ``**(1/2)``\ で評価することができます .. raw:: html
In:
.. code-block:: ipython print( np.sqrt(2) ) print( 2 ** (1/2) ) .. raw:: html
.. parsed-literal:: 1.4142135623730951 1.4142135623730951 ネピア数(オイラー数)\ :math:`e`\ は底が\ :math:`e`\ の指数関数\ :math:`e^x = \exp x`\ で\ :math:`x=1`\ を代入した値なので以下のようにすれば良い. .. raw:: html
In:
.. code-block:: ipython e = np.exp(1) print(e) .. raw:: html
.. parsed-literal:: 2.718281828459045 ``numpy``\ の\ ``log``\ 関数は底が\ :math:`e`\ の自然対数,\ ``log10``\ は底が\ :math:`10`\ の常用対数を意味します. .. raw:: html
In:
.. code-block:: ipython print( np.log(e) ) print( np.log10(10**3) ) .. raw:: html
.. parsed-literal:: 1.0 3.0 print()も関数で,これは括弧の中に代入した値(関数の引数)を文字列として出力する関数です.print関数の引数は複数代入することができ .. raw:: html
In:
.. code-block:: ipython print( "sin(0) = ", np.sin(0) ) .. raw:: html
.. parsed-literal:: sin(0) = 0.0 のように記載することもできます.上記の例でprint関数の1番目の引数(第1引数)“sin(0) =” は\ ``"``\ で括られた内容が単なる文字列であることを意味しています.2番目の引数は\ :math:`\sin(0)`\ の値を\ ``numpy``\ パッケージの\ ``sin``\ 関数で評価した結果を代入しています. 文字列も変数に代入することが可能で以下のように示すこともできます. .. raw:: html
In:
.. code-block:: ipython fujisan1 = "あたまを雲の上に出し" fujisan2 = "四方の山を見下ろして" print(fujisan1, fujisan2, "...") .. raw:: html
.. parsed-literal:: あたまを雲の上に出し 四方の山を見下ろして ... また複数の変数の値をprintで出力する場合,コンマ\ ``,``\ が増えて読みづらくなってしまう場合があります.そのような場合は次のようにすると視認性が高まります. .. raw:: html
In:
.. code-block:: ipython a = 1 b = 2 c = 3 print( f"a = {a}, b = {b} のとき,a + b = {c} で与えられる" ) #最初の"の前にfをつけると{}で括った変数の値をそのまま出力できる .. raw:: html
.. parsed-literal:: a = 1, b = 2 のとき,a + b = 3 で与えられる numpyでの三角関数の引数はラジアンを用いて評価されます.そのため\ :math:`\theta=\pi/2`\ での\ :math:`\sin \theta`, :raw-latex:`\cos `:raw-latex:`\theta`$の値は .. raw:: html
In:
.. code-block:: ipython print("π≈", np.pi) # ≈は近似値を意味する. print( np.sin(np.pi/2) ) print( np.cos(np.pi/2) ) .. raw:: html
.. parsed-literal:: π≈ 3.141592653589793 1.0 6.123233995736766e-17 ここで\ ``np.pi``\ は\ ``numpy``\ で定義された\ :math:`\pi`\ の値です.\ :math:`\pi`\ は無理数なので小数点で表示する場合は無限に長い桁が必要です.しかし,コンピューター上で数は有限桁しか扱うことができず一般には少数部第16位の桁(\ :math:`10^{-16}`\ )以降は打ち切られています(無理数を有理数で近似している).\ ``np.cos(np.pi/2)``\ を評価すると\ ``6.123233995736766e-17``\ と表示されていますが,この値は\ :math:`6.123233995736766\times 10^{~-17}`\ を意味します.\ :math:`\cos(\frac{\pi}{2})`\ は厳密には\ :math:`0`\ ですがコンピューター上では\ :math:`10^{-16}`\ 以下の実数は原則扱えない為,\ ``6.123233995736766e-17``\ と表示されてしまいます.この係数\ ``6.123233995736766``\ の値に意味はなく(ランダムに近い値で)重要なのは\ ``e-17`` = :math:`10^{-17}`\ です.これは\ :math:`10^{-16}`\ より小さいので,コンピューター的にはほとんど0に近い値ということを示しています. したがって\ ``np.cos(np.pi/2)``\ と\ ``0``\ はコンピューター上で厳密に一致はしません. .. raw:: html
In:
.. code-block:: ipython np.cos(np.pi/2) == 0 .. raw:: html
.. parsed-literal:: np.False_ しかしコンピューター上の計算誤差を考慮して0に近い(close)か\ ``numpy``\ のisclose関数で調べることができ .. raw:: html
In:
.. code-block:: ipython np.isclose(np.cos(np.pi/2), 0) .. raw:: html
.. parsed-literal:: np.True_ となりTrueが返ってきているので,\ ``np.cos(np.pi/2)``\ の値はコンピューター上では0に見做せることを意味しています.別の例を与えます.\ :math:`\sqrt{2}`\ は2乗すると2になる無理数ですが,計算機では16桁程度の有限桁しか扱えない為\ :math:`(\sqrt{2})^2`\ の計算を行うと誤差が生じます. .. raw:: html
In:
.. code-block:: ipython two = np.sqrt(2) * np.sqrt(2) print(two) .. raw:: html
.. parsed-literal:: 2.0000000000000004 この値を真の値からとの誤差を\ :math:`|\mathrm{two} -2|`\ で評価すると,計算機で発生している誤差の大きさを見積もることができます.数の絶対値(absolute value)は\ ``np.abs``\ で定義されています. .. raw:: html
In:
.. code-block:: ipython np.abs(two - 2) .. raw:: html
.. parsed-literal:: np.float64(4.440892098500626e-16) なお,\ ``4.440892098500626``\ の1桁目以降の値は\ :math:`10^{-16}`\ より小さいため信頼できない(ほとんどランダム)な値が入っています. § 4.2ユーザー定義関数 ~~~~~~~~~~~~~~~~~~~~~ 基本的な関数は\ ``numpy``\ を使うことで利用することができますが,自分で定義した(ユーザー定義関数)を使うことが多々ある.関数の定義は :: def 関数名(引数): <手続き> return 返り値 です.\ ``def``\ の次の行以降を\ ````\ キーでインデントを下げて(def行の\ ``:``\ をつけ忘れなければ自動的にインドデントが下がるので明示的に\ ``
In:
.. code-block:: ipython def f(x): return 3 * x .. raw:: html
.. raw:: html
In:
.. code-block:: ipython print( f(1) ) print( f(2) ) .. raw:: html
.. parsed-literal:: 3 6 ``return``\ 行のコードが(ユーザー定義)関数\ :math:`f`\ の返り値である.返り値とは\ :math:`y=f(x)`\ と表記した際の\ :math:`y`\ (出力)に相当する量です.関数\ :math:`f`\ の入力\ :math:`x`\ は\ :math:`f`\ の引数と呼ばれます.関数の引数を含め\ ``def``\ コードの中で使用された変数は\ ``def``\ の中でのみ有効な局所変数です. .. raw:: html
In:
.. code-block:: ipython x = 100 print( f(x=1) ) # 明示的にx=1をfに代入しているがこの代入は関数の中でのみ有効 print( x ) .. raw:: html
.. parsed-literal:: 3 100 .. raw:: html
In:
.. code-block:: ipython def f(x): z = 1 return x + z .. raw:: html
.. raw:: html
In:
.. code-block:: ipython print( f(3) ) z .. raw:: html
.. parsed-literal:: 4 :: --------------------------------------------------------------------------- NameError Traceback (most recent call last) /tmp/ipython-input-51-2391348818.py in () 1 print( f(3) ) ----> 2 z NameError: name 'z' is not defined **注意** 同じ関数名で関数を定義すると,古い関数の定義は削除され新しい関数の定義で上書きされます. 関数の引数は省略することも可能ですが,関数を呼び出す際には,関数名の後に必ず括弧()をつける必要があります.括弧()を付けないと関数自身のオブジェクトを意味します. .. raw:: html
In:
.. code-block:: ipython def euler(): return np.exp(1) print(euler()) print(euler) .. raw:: html
.. parsed-literal:: 2.718281828459045 関数の引数は複数設定することが可能です.例えば与えらえた2つの数を足した 結果を変える関数,myAddは次のように定義できます. .. raw:: html
In:
.. code-block:: ipython def myAdd(a, b): return a + b .. raw:: html
.. raw:: html
In:
.. code-block:: ipython print( myAdd(1, 2) ) print( myAdd(2.0, 3.0) ) print( myAdd(np.sqrt(2), 1) ) .. raw:: html
.. parsed-literal:: 3 5.0 2.414213562373095 関数の定義において入力(引数)および,出力(返り値)は数は何個でも構わない.例えば,整数除算と剰余(余り)の2つの要素を返り値に指定したければ,\ ``","``\ で区切って返り値を複数指定すれば良い. .. raw:: html
In:
.. code-block:: ipython def myDivMod(a, b): return a // b, a % b .. raw:: html
.. raw:: html
In:
.. code-block:: ipython myDivMod(5, 3) .. raw:: html
.. parsed-literal:: (1, 2) § 5 リスト(list),配列(array),データフレーム(dataframe) -------------------------------------------------------------- § 5.1 リスト(list)と1次元配列(array) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ リスト(list)や配列(array)を使って複数のもの(数以外も可能)を一つにまとめることができます.複数のものが\ **数以外**\ のものが含まれる場合は,リストを用いて次のようにまとめることができます. .. raw:: html
In:
.. code-block:: ipython lst = [1, 1, 5, "this", "is", "a", "list", np.sin] print(lst) .. raw:: html
.. parsed-literal:: [1, 1, 5, 'this', 'is', 'a', 'list', ] リストを構成する要素はほとんどなんでも良く非常に柔軟である一方, 複数のものが\ **数**\ のみで構成される場合は\ ``numpy``\ の\ ``array``\ (配列)を用いた方が効率的で,数に特化した機能(総和,平均などの計算など)を利用することができます. (正確には\ ``array``\ は\ ``list``\ のように数以外の要素を扱うことも可能) .. raw:: html
In:
.. code-block:: ipython import numpy as np arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) print(arr) print( arr.sum() ) # 総和の計算 print( arr.mean() ) # 平均の計算 print( arr.var() ) # 分散の計算 print( arr.std() ) # 標準偏差の計算 print( arr.min() ) # 最小値 print( arr.max() ) # 最大値 .. raw:: html
.. parsed-literal:: [ 1 2 3 4 5 6 7 8 9 10] 55 5.5 8.25 2.8722813232690143 1 10 ここで\ ``arr.sum()``\ は\ ``numpy``\ の\ ``array``\ で定義されている\ ``sum``\ 関数を引数なしで呼び出しているように見えますが.正確には\ ``sum``\ 関数にはの引数には\ ``arr``\ が代入されており,以下の操作と\ ``arr.sum()``\ は完全に等しい操作になっています. .. raw:: html
In:
.. code-block:: ipython print( np.sum(arr) ) # 総和の計算 print( np.mean(arr) ) # 平均の計算 print( np.var(arr) ) # 分散の計算 print( np.std(arr) ) # 標準偏差の計算 print( np.min(arr) ) # 最小値 print( np.max(arr) ) # 最大値 .. raw:: html
.. parsed-literal:: 55 5.5 8.25 2.8722813232690143 1 10 listやarrayの要素の数は\ ``len``\ (length)関数を用いて調べることができます. .. raw:: html
In:
.. code-block:: ipython print( len(lst) ) print( len(arr) ) .. raw:: html
.. parsed-literal:: 8 10 listやarrayの\ :math:`i`\ 番目の要素を取り出す場合は\ ``lst[i-1]``, ``ary[i-1]``\ で取り出すことができます. 長さ\ :math:`n`\ のlistおよびarrayの最初の要素番号(index)は\ :math:`0`\ 番目から始まり\ :math:`n-1`\ で終わります. .. raw:: html
In:
.. code-block:: ipython print( arr[0] ) print( arr[len(arr) - 1] ) .. raw:: html
.. parsed-literal:: 1 10 listやarrayの要素を後ろから\ :math:`i`\ 番目のように指定する場合は負のindexで指定することもできます\ :math:`i=-1`\ の場合は一番最後の要素,\ :math:`i=-2`\ の場合は後ろから2番目の要素を意味します. .. raw:: html
In:
.. code-block:: ipython print( lst[-1] ) print( arr[-2] ) .. raw:: html
.. parsed-literal:: 9 連続した数の列(数列)を作る関数は良く利用されます. .. raw:: html
In:
.. code-block:: ipython np.arange(10) .. raw:: html
.. parsed-literal:: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) .. raw:: html
In:
.. code-block:: ipython np.arange(0, 10, 2) # 初項2,公差2で (10-1)を超えない数列 .. raw:: html
.. parsed-literal:: array([0, 2, 4, 6, 8]) 全く同じ操作をpythonの標準関数\ ``range``\ でも実現可能ですが,\ ``range``\ はiteratorと呼ばれるオブジェクトを返し,実際に数列の要素が必要になるまで評価しないため(遅延評価),rangeで生成したlistの要素全てをprintで示すことはできません. .. raw:: html
In:
.. code-block:: ipython print( range(10) ) print( range(0, 10, 2) ) rng = range(10) rng[-1] .. raw:: html
.. parsed-literal:: range(0, 10) range(0, 10, 2) .. parsed-literal:: 9 :math:`s`\ から\ :math:`e`\ まで\ :math:`n`\ 等分した数列は\ ``numpy``\ の\ ``linspace`` (linearly spaced value) を用いて\ ``np.linspace(s, e, n)``\ 得ることができます. .. raw:: html
In:
.. code-block:: ipython np.linspace(0, 1, 10) # 0から1まで10等分した数列 .. raw:: html
.. parsed-literal:: array([0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444, 0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ]) 終点を含めずに\ :math:`n`\ 等分した数列を生成するには\ ``endpoint=False``\ のオプションをつければよく, .. raw:: html
In:
.. code-block:: ipython np.linspace(0, 1, 10, endpoint=False) # 0から1まで,終点1を含めずに10等分した数列 .. raw:: html
.. parsed-literal:: array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]) なお上の数列と同じ数列は\ ``np.arange``\ でも生成可能で .. raw:: html
In:
.. code-block:: ipython np.arange(0, 1, 0.1) # 0から0.1刻みで1を超えない数列 .. raw:: html
.. parsed-literal:: array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]) § 5.2 多次元配列 (n dimensional array) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 複数配列を一つにまとめた方が効率的であることも多い.2つの配列を1つの配列にまとめたものを2次元配列,\ :math:`n`\ 個の配列を一つの配列にまとめたものを多次元配列という. ``numpy``\ の\ ``array``\ は多次元配列(\ ``ndarray``\ )を扱うように設計されています. .. raw:: html
In:
.. code-block:: ipython x = np.arange(0, 10, 1) y = x ** 2 arr = np.array([x, y]) arr .. raw:: html
.. parsed-literal:: array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81]]) 多次元配列の行と列の大きさ(配列の型)はshapeと呼ばれる変数(属性)に代入されています.shapeは\ ``array``\ の関数ではなく\ ``array``\ の属性値(attribution, 変数)なので括弧は不要です. .. raw:: html
In:
.. code-block:: ipython arr.shape .. raw:: html
.. parsed-literal:: (2, 10) これは\ ``arr``\ が2行10列の多次元配列(2次元配列であって各配列は10個の要素を持つ)です.\ :math:`i`\ 番目の配列を取り出すには\ ``arr[i, :]``\ のようにします. .. raw:: html
In:
.. code-block:: ipython print( arr[0,:] ) # 0番目(最初)の配列 print( arr[1,:] ) # 1番目(最初)の配列 .. raw:: html
.. parsed-literal:: [0 1 2 3 4 5 6 7 8 9] [ 0 1 4 9 16 25 36 49 64 81] 上は2次元配列の例ですが,\ ``numpy``\ の\ ``array``\ は多数の配列を要素にとることができます. .. raw:: html
In:
.. code-block:: ipython x = np.arange(0, 10, 1) ndarr = np.array([x, x**2, x**3, x**4]) print(ndarr) print(ndarr.shape) .. raw:: html
.. parsed-literal:: [[ 0 1 2 3 4 5 6 7 8 9] [ 0 1 4 9 16 25 36 49 64 81] [ 0 1 8 27 64 125 216 343 512 729] [ 0 1 16 81 256 625 1296 2401 4096 6561]] (4, 10) ただし長さの異なる配列を要素にすることはできません. .. raw:: html
In:
.. code-block:: ipython x1 = np.linspace(0, 1, 10) x2 = np.linspace(0, 1, 9) np.array([x1, x2]) .. raw:: html
:: --------------------------------------------------------------------------- ValueError Traceback (most recent call last) /tmp/ipython-input-73-3792097717.py in () 1 x1 = np.linspace(0, 1, 10) 2 x2 = np.linspace(0, 1, 9) ----> 3 np.array([x1, x2]) ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part. § 5.3 pandas DataFrame ~~~~~~~~~~~~~~~~~~~~~~ ``numpy``\ の\ ``array``\ は主に\ **数**\ を扱う場合は非常に強力ですが,統計学では\ **数以外**\ のデータを扱うことが非常に多いです.\ ``python``\ 標準のlistを用いて,\ **数以外**\ のデータを扱うことも可能ですが,統計学で必要とする機能が定義されていません.そのため,統計学で用いるようなデータは\ ```pandas`` `__\ パッケージで定義された\ ```DataFrame`` `__\ を使うと効率的です.\ ``pandas``\ は内部的に\ ``numpy``\ を継承しているため,\ ``numpy``\ を使う代わり\ ``pandas``\ だけで完結することも可能です.加えてcsvやexcelのデータを\ ``pandas``\ から呼び出すこともできます. ``pandas``\ パッケージからヒストグラムや箱ひげ図を作図できますが,日本語が文字化けしてしまうので,その対策として下記を実行して\ ``japanize-matplotlib``\ をインストールします(ランタイムが再起動した場合は再度インストールが必要です.). さっそく\ ``pandas``\ の\ ``DataFrame``\ を使ってみましょう.\ ``pandas``\ パッケージは\ ``import pandas as pd``\ としてインポートすることが一般的です. .. raw:: html
In:
.. code-block:: ipython !pip install japanize-matplotlib #japanize-matplotlibをinstall import japanize_matplotlib # 作画の日本語文字化けを防ぐために利用 import pandas as pd sex = ['M', 'F', 'F', 'M', 'F', 'M', 'M', 'M'] # 性別(M = male, F = female) weight = [60.3, 50.4, 55.3, 70.2, None, 52.2, 57.5, 55.5] # 体重 Noneは欠損値を意味する height = [166.2, 160.3, 165.3, 174.2, 171.2, 157.6, 165.5, 163.4] # 身長 df = pd.DataFrame({'性別': sex, '体重': weight, '身長': height}) df .. raw:: html
.. parsed-literal:: Collecting japanize-matplotlib Downloading japanize-matplotlib-1.1.3.tar.gz (4.1 MB)  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.1/4.1 MB 34.6 MB/s eta 0:00:00 [?25h Preparing metadata (setup.py) ... [?25l[?25hdone Requirement already satisfied: matplotlib in /usr/local/lib/python3.11/dist-packages (from japanize-matplotlib) (3.10.0) Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (1.3.2) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (0.12.1) Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (4.58.4) Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (1.4.8) Requirement already satisfied: numpy>=1.23 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (2.0.2) Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (24.2) Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (11.2.1) Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (3.2.3) Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.11/dist-packages (from matplotlib->japanize-matplotlib) (2.9.0.post0) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.11/dist-packages (from python-dateutil>=2.7->matplotlib->japanize-matplotlib) (1.17.0) Building wheels for collected packages: japanize-matplotlib Building wheel for japanize-matplotlib (setup.py) ... [?25l[?25hdone Created wheel for japanize-matplotlib: filename=japanize_matplotlib-1.1.3-py3-none-any.whl size=4120257 sha256=eba16dcfbabeec23d8151d5a3a07e975a59bf27e992332e312e4f5acdd6a9aca Stored in directory: /root/.cache/pip/wheels/da/a1/71/b8faeb93276fed10edffcca20746f1ef6f8d9e071eee8425fc Successfully built japanize-matplotlib Installing collected packages: japanize-matplotlib Successfully installed japanize-matplotlib-1.1.3 .. raw:: html
性別 体重 身長
0 M 60.3 166.2
1 F 50.4 160.3
2 F 55.3 165.3
3 M 70.2 174.2
4 F NaN 171.2
5 M 52.2 157.6
6 M 57.5 165.5
7 M 55.5 163.4
最後に表示されているものが\ ``df``\ ,すなわち\ ``pandas``\ のDataFrameに格納した\ ``sex``\ ,\ ``weight``\ ,\ ``height``\ のデータセットです.上の定義で体重データにデータの欠損を表す,\ ``NaN``\ が含まれていますいます.以下の各種統計量の計算において\ ``NaN``\ は基本的に無視されます. .. raw:: html
In:
.. code-block:: ipython # 欠損値 NaN (Not a Number)は基本的に無視して計算される print( df['体重'].count() ) #体重データの個数(欠損値が1つ含まれる) print( df['身長'].count() ) #身長データの個数 print( df['体重'].mean() ) print( df['体重'].var() ) print( df['体重'].std() ) print( df['体重'].min() ) print( df['体重'].max() ) .. raw:: html
.. parsed-literal:: 7 8 57.34285714285714 42.716190476190484 6.535762425011368 50.4 70.2 上で計算されている統計量は個別に計算する必要ななく,\ ``describe()``\ 関数を使えばDataFrameの要約することができます.ただし,平均値や分散の計算ができないデータ(上の例では性別)は表示されません. .. raw:: html
In:
.. code-block:: ipython df.describe() .. raw:: html
.. raw:: html
体重 身長
count 7.000000 8.000000
mean 57.342857 165.462500
std 6.535762 5.379309
min 50.400000 157.600000
25% 53.750000 162.625000
50% 55.500000 165.400000
75% 58.900000 167.450000
max 70.200000 174.200000
DataFrameに含まれるデータのヒストグラムを描画します.\ ``pandas``\ での描画は\ ```matplotlib`` `__\ と呼ばれる描画パッケージを継承しています.なお,デフォルトでは\ ``matplotlib``\ は日本語を表示できないので,\ ``japanize_matplotlib``\ を\ ``import``\ できていないと日本語が□(tofu)になります. .. raw:: html
In:
.. code-block:: ipython df.hist() .. raw:: html
.. parsed-literal:: array([[, ]], dtype=object) .. image:: python%E3%81%AE%E5%9F%BA%E6%9C%AC_files/python%E3%81%AE%E5%9F%BA%E6%9C%AC_148_1.png 多数のデータからなるDataFrameの場合,DataFrame全体を表示させる前にどのようなデータ(列の名前)があるか知りたい場合があります.列名(column name)を表示させるには\ ``df.columns``\ に格納されています.\ ``columns``\ は\ ``DataFrame``\ の属性値(変数)であって関数ではないので括弧()は不要です. .. raw:: html
In:
.. code-block:: ipython df.columns .. raw:: html
.. parsed-literal:: Index(['性別', '体重', '身長'], dtype='object') ``DataFrame``\ から特定の列のデータを取り出す場合は,列の名前(column name)を指定します. .. raw:: html
In:
.. code-block:: ipython df['体重'] .. raw:: html
.. raw:: html
体重
0 60.3
1 50.4
2 55.3
3 70.2
4 NaN
5 52.2
6 57.5
7 55.5

ここから性別が”F”のデータのみを抽出してみましょう. 以下のコードを入力すると’性別’のデータが’F’に一致した場合にTrue, そうでない場合にFalseが返ってきます. .. raw:: html
In:
.. code-block:: ipython df['性別'] == 'M' .. raw:: html
.. raw:: html
性別
0 True
1 False
2 False
3 True
4 False
5 True
6 True
7 True

True/Falseのデータをデータフレーム\ ``df``\ のインデックスに指定するとTrueの結果のみ抽出されます. .. raw:: html
In:
.. code-block:: ipython df[ df['性別'] == 'M' ] .. raw:: html
.. raw:: html
性別 体重 身長
0 M 60.3 166.2
3 M 70.2 174.2
5 M 52.2 157.6
6 M 57.5 165.5
7 M 55.5 163.4
これにdescribe()関数をを加えれば’性別’が’M’(Male)のデーターに制限した際の,データの要約がえれれます. .. raw:: html
In:
.. code-block:: ipython df[ df['性別'] == 'M' ].describe() .. raw:: html
.. raw:: html
体重 身長
count 5.000000 5.000000
mean 59.140000 165.380000
std 6.851496 5.977625
min 52.200000 157.600000
25% 55.500000 163.400000
50% 57.500000 165.500000
75% 60.300000 166.200000
max 70.200000 174.200000
**注意** DataFrameを作成する際に\ ``df = pd.DataFrame({'性別': sex, '体重': weight, '身長': height})``\ のようにDataFrame()の関数に代入しているものは辞書呼ばれる名前付き集合です.pythonでは集合(set)は\ ``{}``\ で定義されます. .. raw:: html
In:
.. code-block:: ipython A = {5, 1, 3, 1} A .. raw:: html
.. parsed-literal:: {1, 3, 5} 集合の要素はlistやarrayと異なり一意的で,重複する要素は削除されます.また要素の順番に無関係です, .. raw:: html
In:
.. code-block:: ipython {1, 2, 3} == {3, 2, 1, 1, 1} .. raw:: html
.. parsed-literal:: True 集合は要素の順番に無関係なのでlistやarrayのように\ :math:`i`\ 番目の要素といった指定ができません .. raw:: html
In:
.. code-block:: ipython A[1] .. raw:: html
:: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) /tmp/ipython-input-85-2665442193.py in () ----> 1 A[1] TypeError: 'set' object is not subscriptable 集合\ ``{}``\ の要素に任意の’記号(key)’を割り当てたものが辞書(dictinary)です. 例えば’x’という記号に5,’y’という記号に1,’z’という記号に3,’w’という記号に1を割り当てた名前付き集合(辞書)は以下のようにして表現されます. .. raw:: html
In:
.. code-block:: ipython A = { 'x':5, 'y':1, 'z':3, 'w':1 } A .. raw:: html
.. parsed-literal:: {'x': 5, 'y': 1, 'z': 3, 'w': 1} 集合同様に辞書の要素の順序は無関係です,集合と同様に要素を数字で指定することはできません. .. raw:: html
In:
.. code-block:: ipython { 'x':5, 'y':1 , 'z':3 ,'w':1 } == { 'w':1, 'z':3 , 'y':1, 'x':5 } .. raw:: html
.. parsed-literal:: True .. raw:: html
In:
.. code-block:: ipython A[1] .. raw:: html
:: --------------------------------------------------------------------------- KeyError Traceback (most recent call last) /tmp/ipython-input-88-2665442193.py in () ----> 1 A[1] KeyError: 1 しかし,割り当てた記号を指定して辞書の要素を取り出すことができます. .. raw:: html
In:
.. code-block:: ipython A['x'] .. raw:: html
.. parsed-literal:: 5 § 6 for文 (繰り返し) --------------------- 同じ操作を繰り返す場合には\ ``for``\ 文を用います. .. raw:: html
In:
.. code-block:: ipython print("for文を始めます") for i in [1, 3, 5]: print(i) print("for文が終わりました") .. raw:: html
.. parsed-literal:: for文を始めます 1 3 5 for文が終わりました ``for``\ 文の基本は :: for i in : 処理内容 です.iteratorはlistやarrayに代表されるオブジェクトで,len(・)を評価して0以上の値になるもであればiteratorとしての資格があります. ``for i in :``\ の場合,はリストの要素を0番目から順に取り出し\ :math:`i`\ に代入し,インデントが下げられた行の処理を逐次的に行なっています.例えば次で定義されるsumはrange(10) = [0, 1, 2, 3, …,9]の総和をfor文を使って計算しています. インデントの高さをfor文の1行目と同じ場所に戻す(Shift+Tab)ことでfor文中の処理の終わりを知らせます. .. raw:: html
In:
.. code-block:: ipython sum = 0 for i in range(10): print(i) sum = sum + i print(f"sum = {sum}") .. raw:: html
.. parsed-literal:: 0 1 2 3 4 5 6 7 8 9 sum = 45 多次元配列もiteratorで,多次元配列をfor文で回すと .. raw:: html
In:
.. code-block:: ipython x = np.arange(10) data = np.array([x, x**2, x**3]) for d in data: print(d) .. raw:: html
.. parsed-literal:: [0 1 2 3 4 5 6 7 8 9] [ 0 1 4 9 16 25 36 49 64 81] [ 0 1 8 27 64 125 216 343 512 729] となります.何番目の要素を宿する場合は\ ``enumerate``\ 関数を使って以下のようにします. .. raw:: html
In:
.. code-block:: ipython for i, d in enumerate(data): print( f"{i}番目のデータ = {d}" ) .. raw:: html
.. parsed-literal:: 0番目のデータ = [0 1 2 3 4 5 6 7 8 9] 1番目のデータ = [ 0 1 4 9 16 25 36 49 64 81] 2番目のデータ = [ 0 1 8 27 64 125 216 343 512 729] 以下のようにfor文の中にfor文を重ねることもてきます. .. raw:: html
In:
.. code-block:: ipython for i in [1, 2]: for j in [3, 4]: print(f"(i, j) = ({i}, {j})") .. raw:: html
.. parsed-literal:: (i, j) = (1, 3) (i, j) = (1, 4) (i, j) = (2, 3) (i, j) = (2, 4) § 7 if文(条件分岐) -------------------- 真(True)もしくは偽(False)の論理式を用いて処理を条件分岐させることができ,\ ``if``\ 文と呼ばれます. if文の基本は次のようになります. :: if <論理式>: 論理式が真(True)の場合の処理 else: 論理式が偽(False)の場合の処理 例えば\ :math:`n`\ が偶数の場合,\ :math:`y=n/2`\ を評価し, :math:`n`\ が奇数の場合\ :math:`y=n/2 + 1`\ を出力するコードは次のように与えられます. .. raw:: html
In:
.. code-block:: ipython n = 10 #n = 11 # <-#を削除するとn=11が代入される if n % 2 == 0: # (nを2で割ったあまりが0 <=> nは偶数) y = n//2 print(f"{n}/2 = {y}") else: # nを2で割ったあまりが0でない <=> nは奇数) y = n//2 print(f"{n}/2 = {y} + 1/2") .. raw:: html
.. parsed-literal:: 10/2 = 5 上の例では論理式がTrueもしくはFalse二律背反となる状況であったが,複数の条件をif文で設定する子も可能です. :: if <論理式1>: 論理式1が真(True)の場合の処理 elif <論理式2>: 論理式1が**偽(False)**かつ論理式2が**真**の場合の処理 elif <論理式3> 論理式1が**偽**かつ論理式2が**偽**かつ論理式3が**真**の場合の処理 else: それ以外<=>論理式1,論理式2,論理式3のいずれも**偽** elif は else ifの省略形. .. raw:: html
In:
.. code-block:: ipython n = 7 #n = 6 if n % 2 == 0: print(f"{n}は2の倍数です") elif n % 3 == 0: print(f"{n}は3の倍数です") elif n % 5 == 0: print(f"{n}は5の倍数です") else: print(f"{n}は2, 3, 5の倍数でもありません") .. raw:: html
.. parsed-literal:: 7は2, 3, 5の倍数でもありません 上の条件分岐で\ :math:`n=6`\ とすると\ :math:`6`\ は2と3の倍数であるが最初の\ ``if n % 2 == 0:``\ の条件にマッチすると,それ以下の条件分岐を無視するため,\ ``6は2の倍数です``\ のみ表示されることに注意せよ. for文とif文を組み合わせると『3の倍数と3が付く数字の時だけアホになる』世界のナベアツ(の元ネタは\ `Fizz Buzz `__\ )っぽいものができる. .. raw:: html
In:
.. code-block:: ipython for n in range(1, 41): if n % 3 == 0: # 3の倍数のとき print("%d ━━━━(゚∀゚)━━━━!!" % n) elif ('3' in f'{n}'): # nを文字列に変換して文字列に'3'がが含まれている print("%d ━━━(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)━━━━!!" % n) else: print(f"{n}...") .. raw:: html
.. parsed-literal:: 1... 2... 3 ━━━━(゚∀゚)━━━━!! 4... 5... 6 ━━━━(゚∀゚)━━━━!! 7... 8... 9 ━━━━(゚∀゚)━━━━!! 10... 11... 12 ━━━━(゚∀゚)━━━━!! 13 ━━━(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)━━━━!! 14... 15 ━━━━(゚∀゚)━━━━!! 16... 17... 18 ━━━━(゚∀゚)━━━━!! 19... 20... 21 ━━━━(゚∀゚)━━━━!! 22... 23 ━━━(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)━━━━!! 24 ━━━━(゚∀゚)━━━━!! 25... 26... 27 ━━━━(゚∀゚)━━━━!! 28... 29... 30 ━━━━(゚∀゚)━━━━!! 31 ━━━(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)━━━━!! 32 ━━━(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)━━━━!! 33 ━━━━(゚∀゚)━━━━!! 34 ━━━(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)━━━━!! 35 ━━━(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)━━━━!! 36 ━━━━(゚∀゚)━━━━!! 37 ━━━(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)━━━━!! 38 ━━━(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)━━━━!! 39 ━━━━(゚∀゚)━━━━!! 40...