Pythonでプログラムを組んでいると、2次元配列へのアクセスで混乱することがあるので、改めてまとめておきます。
2次元配列の種類
ここでは、以下の方法で2次元配列を扱います。
- リスト
- numpy
- DataFrame
リストの場合
リストの場合は、正確には2次元配列ではない(多重リスト)のですが、そのように扱うこともできます。
list = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
# [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
1つの値を取得する場合は、直接指定します。
value = list[1][2]
# value = 5
スライスでの取得は、期待するようにできません。
# [[4,5], [7,8]]を期待するが...
new_list = list[1:][1:]
# new_list = [6, 7, 8]となる
これは、まず
new_list1 = list[1:]
で[[3, 4, 5], [6, 7, 8]]となり、次の
new_list2 = new_list1[1:]
で[6, 7, 8]となるためです。
ということで、純粋な2次元配列ではないので要注意です。
numpyの場合
numpyは、一番わかりやすい(現実と一致している)です。
import numpy as np
array = np.array(([0, 1, 2], [3, 4, 5], [6, 7, 8]))
# array([[0, 1, 2],
# [3, 4, 5],
# [6, 7, 8]])
まずは1つの値を取得します。
value = array[1, 2]
# value = 5
array[n][m]という書き方ではないのがやや気になりますが、それほど大きな問題ではありません。
スライスで、配列の一部を取得します。
array1 = array[1:, 1:]
# array([[4, 5],
# [7, 8]])
なにも問題ありません。
DataFrameの場合
DataFrameは、ちょっと指定の仕方が違っていますので、要注意です。
(扱えないわけではない)
import pandas as pd
df = pd.DataFrame([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
value = df[1][2]
# value = 7
# 縦と横が逆になる
value = df[2][1]
# value = 5
先に列番号を指定し、そのあとに行番号を指定するのがしっくりしない感じです。
ということで、ちゃんと行→列でも指定する方法があります。
value = df.iloc[1, 2]
# value = 5
基本的には、こちらのやり方で行います。
(numpy同様、array[n][m]での指定ではありませんが)
スライスでの取得も、この「iloc」を使用します。
df2 = df.iloc[1:, 1:]
なお、「iloc」ではなく「loc」というのもありますが、こちらはラベル名で区間を指定するので、ここでは省略します。
また、一つ気を付けないといけないのは、
df2 = df[1:][1:]
まとめ
とりあえず2次元配列を扱う場合はnumpyを使っておけば安心です。
状況によってはDataFrameを使用することもあるかと思いますが、その際には「ilocを使うんだぞ」と忘れないようにしたいと思います。
また、2次元配列でリストを使うことは、極力避けたほうが良いかと思います。