何らかの理由で、次の2つのiloc
/loc
の呼び出しは、異なる動作を生成します。
>>> import pandas as pd
>>> df = pd.DataFrame(dict(A=range(3), B=range(3)))
>>> df.iloc[:1]
A B
0 0 0
>>> df.loc[:1]
A B
0 0 0
1 1 1
loc
は行ラベルを考慮し、iloc
は行の整数ベースのインデックスを考慮することを理解しています。しかし、loc
の上限が包括的であると見なされ、iloc
の上限が排他的であると見なされるのはなぜですか?
クイックアンサー:
ラベルを使用する場合は、DataFrameの他の行に関する知識が少なくて済むため、エンドインクルーシブスライスを実行する方が理にかなっていることがよくあります。
位置ではなくラベルを気にするときはいつでも、エンドエクスクルーシブなラベルスライスは不便な方法で位置依存性をもたらします。
長い答え:
関数の動作はトレードオフです。あるユースケースを他のユースケースよりも優先します。最終的に、_.iloc
_の操作は、Pandas開発者による主観的な設計上の決定です(@ALlollzによるコメントが示すように、この動作 意図的 )。彼らがなぜそれをそのように設計したのかを理解するために、ラベルスライスが位置スライスと異なる理由を考えてください。
2つのDataFrame _df1
_と_df2
_があると想像してください。
_df1 = pd.DataFrame(dict(X=range(4)), index=['a','b','c','d'])
df1 = pd.DataFrame(dict(X=range(4)), index=['b','c','z'])
_
_df1
_に含まれるもの:
_ X
Y
a 0
b 1
c 2
d 3
_
_df2
_に含まれるもの:
_ X
Y
b 0
c 1
z 2
_
実行するラベルベースのタスクがあるとします。_df1
_と_df2
_の両方からb
とc
の間の行を取得し、実行したいとします。両方のDataFrameに同じコードを使用します。 b
とc
は両方のDataFrameで同じ位置にないため、単純な位置スライスではうまくいきません。そこで、ラベルベースのスライスに目を向けます。
_.loc
_がend-exclusiveの場合、b
とc
の間の行を取得するには目的の終了行のラベルだけでなく、その次の行のラベルも知っています。構築されると、この次のラベルは各DataFrameで異なります。
この場合、2つのオプションがあります。
df1.loc['b':'d']
_および_df2.loc['b':'z']
_。これは、必要な行だけでなく追加情報を知る必要があることを意味するため、不便です。df.loc[df.index.get_loc('b'):df.index.get_loc('c')+1]
。これはただの言葉です。しかし、_.loc
_はエンドインクルーシブなので、_.loc['b':'c']
_とだけ言うことができます。はるかに簡単です!
位置ではなくラベルを気にし、位置に依存しないコードを書き込もうとしているときはいつでも、end-inclusive label slicingは、不便な方法で位置依存性を再導入します。
そうは言っても、エンドエクスクルーシブなラベルベースのスライスが本当に必要なユースケースがあるかもしれません。もしそうなら、あなたは使用することができます この質問の@Willzの答え :
_df.loc[start:end].iloc[:-1]
_