Pandas 1.4.4ではデータフレームの列名による列指定に[]
とloc[]
が使えますが、これらはタプルで列名を指定したときの動作が異なります。[]
はタプルをひとつのキーとして扱い、loc[]
はデータフレームの持つ列名により動作を変えます。前者はデータフレームがハッシュ化できるオブジェクト(辞書のキーになれるオブジェクト?)を列名として扱う動作通りですが、後者は複雑です。
ここでは[]
とloc[]
の違いを紹介しますが、結論としてはデータフレームのインデックス参照[]
ではリストを使う(タプルは使わない)方が良さそうです。リストの方が多少コストが大きいですが、いくつかの列名を指定する程度であれば普通は無視できる程度だと思います。列がタプルを含む場合はもちろんタプルも使います。
# []とloc[]の動作差 import pandas as pd df = pd.DataFrame({"A": [0, 1, 2], "B": [3, 4, 5]}) print(df[["A", "B"]]) # Success. #print(df[("A", "B")]) # KeyError:データフレームは列名("A", "B")を持たない。 print(df.loc[:, ["A", "B"]]) # Success. print(df.loc[:, ("A", "B")]) # Success!?:列Aと列Bが選択される。
# loc[]の列名による動作差 import pandas as pd df1 = pd.DataFrame({ "A": [1], "B": [2], ("A", "B"): [3], ("A", "B", "A"): [4], ("A", "B", "B"): [5], ("B", "A", "B"): [6]}) print(df1) # A B (A, B) (A, B, A) (A, B, B) (B, A, B) #0 1 2 3 4 5 6 print(df1.loc[:,"A"]) #列Aをシリーズとして返す。 #0 1 #Name: A, dtype: int64 print(df1.loc[:,("A",)]) #列Aをデータフレームとして返す。 # A #0 1 print(df1.loc[:,("A","B")]) print(df1.loc[:,("A","B",)]) #列Aと列Bをデータフレームとして返す。 #注意:列("A", "B")ではない。 # A B #0 1 2 df2 = pd.DataFrame({ ("A", "B"): [3], ("A", "B", "A"): [4], ("A", "B", "B"): [5], ("B", "A", "B"): [6]}) print(df2.loc[:,"A"]) print(df2.loc[:,("A",)]) #列("A"(, ...))に該当する列を返す。 #注意:列Aがある場合と動作が異なる。 # B # NaN A B #0 3 4 5 print(df2.loc[:,("A","B")]) print(df2.loc[:,("A","B")]) #列("A", "B"(, ...))に該当する列を返す。 #注意:列("A", "B")だけではない。 # NaN A B #0 3 4 5 print(df2.loc[:,("A","B",pd.NA)]) print(df2.loc[:,("A","B",pd.NA,)]) #列("A", "B")に該当するシリーズを返す。 #0 3 #Name: (A, B, nan), dtype: int64