ilocとlocはどのように異なりますか?

2015年07月24日に質問されました。  ·  閲覧回数 517.8k回  ·  ソース

AZhao picture
2015年07月24日

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

たとえば、 DataFrameの最初の5行を取得するとします。 これら2つがどのように機能するのですか?

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

誰かが使用法の区別がより明確である3つのケースを提示できますか?


昔々、これら2つの関数がdf.ix[:5]とどのように違うのか知りたかったのですが、 ixはpandas 1.0から削除されたので、もう気にしません!

回答

Alex Riley picture
2015年07月24日
1042

注:パンダバージョン0.20.0以降では、 ix非推奨になり、locilocが推奨されます。 ix代替案を示す例を以下に追加しました


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

  • locは、インデックスから特定のラベルを持つ行(または列)を取得します。
  • ilocは、インデックスの特定の位置で行(または列)を取得します(したがって、整数のみを取ります)。
  • ixは通常、 locように動作しようとしますが、ラベルがインデックスに存在しない場合はilocように動作するようにフォールバックします。

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

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

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


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]と同じシリーズを返すことに注意してください( sのインデックスは整数型です)。

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

ここで、 s.iloc[:6]は、期待どおりにシリーズの最初の6行を返します。 ただし、 s.loc[:6] 6はインデックスにないため、 s.loc[: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]locように機能しようとしますが、インデックスに6が見つからないため、KeyErrorが発生するようになりました。 インデックスは整数型であるため、 ixilocように動作するようにフォールバックしません。

ただし、インデックスが混合タイプの場合、整数ixを指定すると、KeyErrorを発生させる代わりに、すぐにilocように動作します。

>>> 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

ixは引き続き非整数を受け入れ、 locように動作することに注意してください。

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

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


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

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

以前のバージョンのパンダ(0.20.0より前)では、 ix使用すると、これを非常に適切に行うことができます。行をラベルで、列を位置でスライスできます(列の場合、 ix4は列名ではないため、デフォルトでは位置ベースのスライスになります):

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

それ以降のバージョンのパンダでは、 ilocと別の方法を使用して、この結果を得ることができます。

>>> 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()は、「このインデックス内のラベルの位置を取得する」ことを意味するインデックスメソッドです。 ilocスライスはそのエンドポイントを除外するため、行 'c'も必要な場合は、この値に1を追加する必要があることに注意してください。

パンダのドキュメントには、ここにさらに例があり

JoeCondron picture
2015年07月24日
151

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'
Ted Petrou picture
2017年10月25日
128

私の意見では、受け入れられた答えは、値が欠落しているだけの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

太字の単語はすべてラベルです。 ラベルagecolorfoodheightscore 、およびstate列に使用されJaneNickAaronPenelopeDeanChristinaCorneliaインデックスに使用され


DataFrameで特定の行を選択する主な方法は、 .locおよび.ilocインデクサーを使用することです。 これらの各インデクサーを使用して列を同時に選択することもできますが、現時点では行だけに焦点を当てる方が簡単です。 また、各インデクサーは、名前の直後に続く括弧のセットを使用して選択を行います。

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

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

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

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

文字列を含む.locを含む単一の行を選択する

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

df.loc['Penelope']

これにより、データの行がシリーズとして返されます

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で複数の行を選択する

スライス表記は、開始値、停止値、およびステップ値によって定義されます。 ラベルでスライスする場合、パンダはリターンにストップ値を含めます。 アーロンからディーンまでの次のスライス。 そのステップサイズは明示的に定義されていませんが、デフォルトで1になっています。

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

enter image description here

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

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

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

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

  • 整数
  • 整数のリスト
  • 開始値と停止値として整数を使用するスライス表記

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

df.iloc[4]

これにより、5行目(整数位置4)がシリーズとして返されます。

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は、ラベルと整数の位置と同時に選択を行うために使用されました。これは便利でしたが、混乱を招き、あいまいな場合があり、ありがたいことに非推奨になりました。 ラベルと整数の場所を組み合わせて選択する必要がある場合は、選択ラベルまたは整数の場所の両方を作成する必要があります。

たとえば、行NickCorneliaを列2と4とともに選択する場合、整数を次のラベルに変換することで.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複製できますが、ブール系列を渡すことはできません。 ブール系列を次のようにnumpy配列に変換する必要があります。

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

すべての行を選択する

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

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

enter image description here


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

ほとんどの人は、列を選択するという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'