web-dev-qa-db-ja.com

Iloc、ix、およびlocはどう違いますか?

これら3つのスライス方法がどのように異なるのか、誰かが説明できますか?
ドキュメント 、および これら答え を見ましたが、3つの違いについては説明できません。私にとっては、スライスのレベルが低いため、大部分は互換性があります。

たとえば、DataFrameの最初の5行を取得したいとします。これら3つすべてが機能するのはどうしてですか。

df.loc[:5]
df.ix[:5]
df.iloc[:5]

用途の違いが明確な3つのケースを誰かが提示できますか?

482
AZhao

注:pandasバージョン0.20.0以降では、ixname__は 非推奨 であり、代わりにlocname__およびilocname__の使用が推奨されます。 ixname__を説明するこの回答の一部は、以前のバージョンのパンダのユーザーの参照としてそのまま残しました。 ixname __の代替を示す例を以下に追加しました。


まず、3つの方法の要約を次に示します。

  • locname__は、インデックスから特定のlabelsを持つ行(または列)を取得します。
  • ilocname__は、インデックス内の特定のpositionsで行(または列)を取得します(したがって、整数のみを受け取ります)。
  • ixname__は通常、locname__のように振る舞いますが、ラベルがインデックスに存在しない場合はilocname__のように振る舞います。

ixname__を使用するのが少し面倒になる可能性があるいくつかの微妙な点に注意することが重要です。

  • インデックスが整数型の場合、ixname__はラベルベースのインデックス付けのみを使用し、位置ベースのインデックス付けにフォールバックしません。ラベルがインデックスにない場合、エラーが発生します。

  • インデックスにonly整数が含まれていない場合、整数を指定すると、ixname__はラベルベースのインデックスではなく、位置ベースのインデックスをすぐに使用します。ただし、ixname__に別の型(文字列など)が指定されている場合は、ラベルベースのインデックス付けを使用できます。


3つの方法の違いを説明するために、次のシリーズを検討してください。

>>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5])
>>> s
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN
4    NaN
5    NaN

整数値3を使用したスライスについて見ていきます。

この場合、s.iloc[:3]は最初の3行を返します(3を位置として扱うため)、s.loc[:3]は最初の8行を返します(3をラベルとして扱うため):

>>> s.iloc[:3] # slice the first three rows
49   NaN
48   NaN
47   NaN

>>> s.loc[:3] # slice up to and including label 3
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

>>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

s.ix[:3]は、s.loc[:3]と同じSeriesを返すことに注意してください。これは、位置を処理するのではなく、最初にラベルを探すためです(sname__のインデックスは整数型です)。

インデックスにない整数ラベル(たとえば6)を使用するとどうなりますか?

ここで、s.iloc[:6]は、シリーズの最初の6行を期待どおりに返します。ただし、s.loc[:6]はインデックスにないため、6はKeyErrorを発生させます。

>>> s.iloc[:6]
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN

>>> s.loc[:6]
KeyError: 6

>>> s.ix[:6]
KeyError: 6

上記の微妙な点により、s.ix[:6]は、locname__のように動作しようとしますが、インデックスで6が見つからないため、KeyErrorが発生します。インデックスは整数型ixname__であるため、ilocname__のように動作することはありません。

ただし、インデックスが混合型である場合、整数ixname__を指定すると、KeyErrorが発生する代わりに、すぐにilocname__のように動作します。

>>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5])
>>> s2.index.is_mixed() # index is mix of different types
True
>>> s2.ix[:6] # now behaves like iloc given integer
a   NaN
b   NaN
c   NaN
d   NaN
e   NaN
1   NaN

ixname__は引き続き整数以外を受け入れ、locname__のように動作することに注意してください。

>>> s2.ix[:'c'] # behaves like loc given non-integer
a   NaN
b   NaN
c   NaN

一般的なアドバイスとして、ラベルを使用してのみインデックスを作成する場合、または整数位置を使用してのみインデックスを作成する場合は、locname__またはilocname__を使用して、予期しない結果を避けます。ixname__は使用しないでください。


位置ベースとラベルベースのインデックス作成の組み合わせ

DataFrameが指定されている場合、行と列のラベルと位置のインデックス方法を混在させることができます。

たとえば、次のDataFrameを考えます。 'c'およびまでの行をスライスする最適な方法は、最初の4列を取得することですか?

>>> df = pd.DataFrame(np.nan, 
                      index=list('abcde'),
                      columns=['x','y','z', 8, 9])
>>> df
    x   y   z   8   9
a NaN NaN NaN NaN NaN
b NaN NaN NaN NaN NaN
c NaN NaN NaN NaN NaN
d NaN NaN NaN NaN NaN
e NaN NaN NaN NaN NaN

pandas(0.20.0以前)の以前のバージョンでは、ixname__を使用すると、これを非常にきれいに行うことができます。ラベルで行を、位置で列をスライスできます(列については、ixname__がデフォルトでposition- 4は列名ではないため、ベースのスライス):

>>> df.ix[:'c', :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

パンダの以降のバージョンでは、ilocname__と別のメソッドのヘルプを使用してこの結果を達成できます。

>>> df.iloc[:df.index.get_loc('c') + 1, :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

get_loc() は、「このインデックス内のラベルの位置を取得する」という意味のインデックスメソッドです。 ilocname__を使用したスライスはエンドポイントを除外するため、行 'c'が必要な場合はこの値に1を追加する必要があることに注意してください。

パンダのドキュメントにはさらに例があります here

820
Alex Riley

ilocは整数位置に基づいて機能します。そのため、行ラベルが何であっても、次のようにしていつでも最初の行を取得できます。

df.iloc[0]

または最後の5行

df.iloc[-5:]

列にも使用できます。これは3列目を取得します。

df.iloc[:, 2]    # the : in the first position indicates all rows

それらを組み合わせて行と列の交差を得ることができます。

df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns)

一方、.locは名前付きインデックスを使用します。行と列のラベルとして文字列を使用してデータフレームを設定しましょう。

df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])

それで最初の行を取得することができます

df.loc['a']     # equivalent to df.iloc[0]

そして'date'列の次の2行は

df.loc['b':, 'date']   # equivalent to df.iloc[1:, 1]

等々。さて、おそらくDataFrameのデフォルトの行と列のインデックスは0からの整数であり、この場合iloclocは同じように働くことを指摘する価値があります。これが、3つの例が同じ理由です。 文字列や日時などの数値以外のインデックスがある場合、 df.loc[:5] はエラーを発生させます。

また、データフレームの__getitem__を使用するだけで列の検索を実行できます。

df['time']    # equivalent to df.loc[:, 'time']

ここで、位置と名前付きインデックスを混在させる、つまり、行の名前と列の位置を使用したインデックスを作成するとします(わかりやすくするために、行インデックスの文字列と整数の文字列でデータフレームを作成するのではなく列インデックス)これが.ixの出番です。

df.ix[:2, 'time']    # the first two rows of the 'time' column

また、locメソッドにブールベクトルを渡すこともできることを言及する価値があると思います。例えば:

 b = [True, False, True]
 df.loc[b] 

dfの1行目と3行目を返します。これは選択のためのdf[b]と同等ですが、ブールベクトルによる代入にも使用できます。

df.loc[b, 'name'] = 'Mary', 'John'
105
JoeCondron

私の意見では、受け入れられた答えは紛失した値だけを持つDataFrameを使っているので、混乱を招きます。また、.iloc 位置ベースの という用語は好きではありません。代わりに、 整数の位置 を使ってください。.ilocの意味がわかりやすいからです。キーワードはINTEGERです - .ilocはINTEGERSを必要とします。

詳細については、私の非常に詳細な ブログシリーズ サブセットの選択を参照してください。


.ixは廃止予定であいまいなため、絶対に使用しないでください。

.ixは非推奨なので、.loc.ilocの違いにのみ焦点を当てます。

違いについて説明する前に、DataFrameには各列と各インデックスの識別に役立つラベルがあることを理解することが重要です。サンプルのDataFrameを見てみましょう。

df = pd.DataFrame({'age':[30, 2, 12, 4, 32, 33, 69],
                   'color':['blue', 'green', 'red', 'white', 'gray', 'black', 'red'],
                   'food':['Steak', 'Lamb', 'Mango', 'Apple', 'Cheese', 'Melon', 'Beans'],
                   'height':[165, 70, 120, 80, 180, 172, 150],
                   'score':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2],
                   'state':['NY', 'TX', 'FL', 'AL', 'AK', 'TX', 'TX']
                   },
                  index=['Jane', 'Nick', 'Aaron', 'Penelope', 'Dean', 'Christina', 'Cornelia'])

enter image description here

bold 内のすべての単語はラベルです。には、ラベルagecolorfoodheightscore、およびstateが使用されます。他のラベルJaneNickAaronPenelopeDeanChristinaCorneliaは、 index に使用されます。


DataFrame内の特定の行を選択する主な方法は、.locおよび.ilocインデクサを使用することです。これらの各インデクサーを使用して列を同時に選択することもできますが、今のところは単に行に集中する方が簡単です。また、各インデクサーは、選択するために名前のすぐ後に続く一連の大括弧を使用します。

.locはラベルのみでデータを選択します

最初に、インデックスまたは列ラベルによってデータを選択するだけの.locインデクサーについて説明します。サンプルのDataFrameでは、インデックスの値として意味のある名前を指定しています。多くのDataFrameは意味のある名前を持たず、代わりにデフォルトの0からn-1までの整数になります。nはDataFrameの長さです。

.locに使用できる3つの異なる入力があります

  • 文字列
  • 文字列のリスト
  • 開始値と終了値として文字列を使用したスライス表記

文字列を持つ.locを使用して単一行を選択する

単一行のデータを選択するには、.locの後の角かっこ内にインデックスラベルを配置します。

df.loc['Penelope']

これはデータ行をSeriesとして返します。

age           4
color     white
food      Apple
height       80
score       3.3
state        AL
Name: Penelope, dtype: object

文字列のリストを持つ.locで複数行を選択する

df.loc[['Cornelia', 'Jane', 'Dean']]

これは、リストに指定された順序で行を含むDataFrameを返します。

enter image description here

スライス表記で.locを使用して複数の行を選択する

スライス表記は、start、stop、stepの値によって定義されます。ラベルでスライスすると、パンダは戻り値にストップ値を含めます。以下のスライスは、アロンからディーンまでを含みます。そのステップサイズは明示的に定義されていませんが、デフォルトは1です。

df.loc['Aaron':'Dean']

enter image description here

複雑なスライスはPythonのリストと同じ方法で取得できます。

.ilocは整数位置のみでデータを選択します

それでは.ilocを見てみましょう。 DataFrame内のデータのすべての行と列には、それを定義する整数位置があります。 これは、出力に視覚的に表示されるラベルに加えてです。整数位置は、0から始まる、上/左からの行/列数です。

.ilocに使用できる3つの異なる入力があります

  • 整数
  • 整数のリスト
  • 開始値と終了値として整数を使用したスライス表記

整数を含む.ilocで単一行を選択する

df.iloc[4]

これは5行目(整数位置4)をSeriesとして返します。

age           32
color       gray
food      Cheese
height       180
score        1.8
state         AK
Name: Dean, dtype: object

整数のリストを持つ.ilocで複数の行を選択する

df.iloc[[2, -2]]

これは、最後から3番目と2番目の行のDataFrameを返します。

enter image description here

スライス表記を使用して.ilocで複数行を選択する

df.iloc[:5:3]

enter image description here


.locと.ilocを使用した行と列の同時選択

両方の.loc/.ilocの優れた能力の1つは、行と列の両方を同時に選択できることです。上記の例では、すべての列が各選択から返されました。行と同じ入力タイプの列を選択できます。行と列の選択を コンマ で区切るだけです。

たとえば、次のように、列の高さ、スコア、および状態だけを使用して、行Jane、およびDeanを選択できます。

df.loc[['Jane', 'Dean'], 'height':]

enter image description here

これは行にラベルのリストを使い、列にスライス表記を使う

整数だけを使用して、.ilocで同様の操作を自然に行うことができます。

df.iloc[[1,4], 2]
Nick      Lamb
Dean    Cheese
Name: food, dtype: object

ラベルと整数位置による同時選択

.ixはラベルと整数位置で同時に選択をするために使用されましたが、それは便利ですが混乱を招き、時々あいまいになりました。ラベルと整数位置を組み合わせて選択する必要がある場合は、両方のラベルと整数位置を選択する必要があります。

たとえば、行2と4とともに行NickCorneliaを選択する場合は、次のように整数をラベルに変換することで.locを使用できます。

col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names] 

または、get_locインデックスメソッドを使用してインデックスラベルを整数に変換します。

labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]

ブール選択

.locインデクサーはブール選択もできます。たとえば、30歳以上のすべての行を見つけて、food列とscore列だけを返すことに興味がある場合は、次のようにします。

df.loc[df['age'] > 30, ['food', 'score']] 

これを.ilocで複製することはできますが、ブール級数を渡すことはできません。このようにブール値のSeriesをでこぼこの配列に変換する必要があります。

df.iloc[(df['age'] > 30).values, [2, 4]] 

すべての行を選択

列選択だけに.loc/.ilocを使用することは可能です。このようにコロンを使用してすべての行を選択できます。

df.loc[:, 'color':'score':2]

enter image description here


インデックス演算子[]は、行と列も選択できますが、同時には選択できません。

ほとんどの人はDataFrameインデックス演算子の主な目的、つまり列の選択に精通しています。文字列は単一の列をSeriesとして選択し、文字列のリストは複数の列をDataFrameとして選択します。

df['food']

Jane          Steak
Nick           Lamb
Aaron         Mango
Penelope      Apple
Dean         Cheese
Christina     Melon
Cornelia      Beans
Name: food, dtype: object

リストを使用して複数の列を選択する

df[['food', 'score']]

enter image description here

あまり知られていないのは、スライス表記が使用されている場合、選択は行ラベルまたは整数位置によって行われるということです。これは非常に混乱を招くものであり、私が使用することはほとんどありませんが、機能します。

df['Penelope':'Christina'] # slice rows by label

enter image description here

df[2:6:2] # slice rows by integer location

enter image description here

行を選択するための.loc/.ilocの明示性は非常に好ましいです。インデックス演算子だけでは、行と列を同時に選択することはできません。

df[3:5, 'color']
TypeError: unhashable type: 'slice'
79
Ted Petrou