판다스의 Series와 Dataframe 데이터 구조는 각각 1차원과 2차원이다. 각각은 Python의 [] 기호를 통해서 인덱싱도 가능하지만 .loc과 .iloc을 사용하여 인덱싱 하는 것이 훨씬 편리하다. Python에서 리스트 객체에 사용하는 일반적인 [] 인덱싱은 Series와 Dataframe에서는 오류가 날 가능성이 있기 때문에 loc과 iloc을 사용하는 것이 좋다. 자세한 사례는 stackoverflow에 올라온 질문을 통해 확인해 볼 수 있다.
https://stackoverflow.com/questions/38886080/python-pandas-series-why-use-loc
위의 내용을 정리해보면 그렇다.
1. row나 column 이름이 True 같은 Boolean 값이면 Dataframe에서 loc없이 인덱싱할 경우 ValueError 오류가 날 수 있다.
2. loc과 iloc을 사용한 인덱싱 방법이 일반적인 인덱싱보다 훨씬 빠르다.
loc과 iloc은 이렇듯 장점이 확실하고 편리한 인덱싱 방법이다. 그렇다면 둘은 어떻게 사용하고 둘의 차이점은 무엇일까?
1. loc
.loc은 주로 레이블 기반으로 사용하고, 불리언 값으로 사용도 가능한 인덱싱 방법이다.
df = pd.read_csv('/content/drive/MyDrive/ML_Data/titanic/train.csv')
df.loc[:]
=>
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 2 Montvila, Rev. Juozas male 27.0 0 0 211536 13.0000 NaN S
887 888 1 1 Graham, Miss. Margaret Edith female 19.0 0 0 112053 30.0000 B42 S
888 889 0 3 Johnston, Miss. Catherine Helen "Carrie" female NaN 1 2 W./C. 6607 23.4500 NaN S
889 890 1 1 Behr, Mr. Karl Howell male 26.0 0 0 111369 30.0000 C148 C
890 891 0 3 Dooley, Mr. Patrick male 32.0 0 0 370376 7.7500 NaN Q
891 rows × 12 columns
1.1. 기본적인 인덱싱 방법
다음과 같이 인덱싱하면 인덱스 기준(row 기준)으로 인덱싱할 수 있다.
df.loc[0:5]
=>
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
5 6 0 3 Moran, Mr. James male NaN 0 0 330877 8.4583 NaN Q
df.loc[[0,2]]
=>
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.250 NaN S
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.925 NaN S
인덱스가 integer가 아니라면 (예를 들어, string 타입) 다음과 같은 방식으로 인덱싱할 수 있다.
s1 = pd.Series(np.random.randn(6), index=list('abcdef'))
s1.loc['c':]
=>
c -2.462258
d -2.733875
e -1.487532
f 2.144902
dtype: float64
인덱스 기준(row 기준)과 컬럼 기준(column 기준) 모두 혼합해서 인덱싱도 가능하다.
df.loc[0:5,'Name':]
=>
Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
5 Moran, Mr. James male NaN 0 0 330877 8.4583 NaN Q
1.2. 불리언 인덱싱
판다스의 인덱싱은 불리언 인덱싱 기능도 제공한다.
아래와 같은 방법으로 .loc 불리언 인덱싱이 가능하다.
df.loc[df['Age'] > 25, 'Ticket':]
=>
Ticket Fare Cabin Embarked
1 PC 17599 71.2833 C85 C
2 STON/O2. 3101282 7.9250 NaN S
3 113803 53.1000 C123 S
4 373450 8.0500 NaN S
6 17463 51.8625 E46 S
... ... ... ... ...
883 C.A./SOTON 34068 10.5000 NaN S
885 382652 29.1250 NaN Q
886 211536 13.0000 NaN S
889 111369 30.0000 C148 C
890 370376 7.7500 NaN Q
여러 개의 조건으로 불리언 인덱싱을 하고 싶을 때에는 반드시 괄호를 사용하여 구분해 주어야 한다.
df.loc[(df['Age'] > 25) & (df['Sex'] == 'male'), 'Ticket':]
=>
Ticket Fare Cabin Embarked
4 373450 8.0500 NaN S
6 17463 51.8625 E46 S
13 347082 31.2750 NaN S
20 239865 26.0000 NaN S
21 248698 13.0000 D56 S
... ... ... ... ...
881 349257 7.8958 NaN S
883 C.A./SOTON 34068 10.5000 NaN S
886 211536 13.0000 NaN S
889 111369 30.0000 C148 C
890 370376 7.7500 NaN Q
만약 괄호를 사용하지 않는다면 아래처럼 오류가 난다.
df.loc[df['Age'] > 25 & df['Sex'] == 'male', 'Ticket':]
=>
TypeError: Cannot perform 'rand_' with a dtyped [object] array and scalar of type [bool]
1.3. 값 변경하기
loc과 iloc은 모두 인덱싱으로 데이터를 조회할 뿐만 아니라 값의 변경도 가능하다.
df['Age'] = 0
df
=>
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 0 0 0 373450 8.0500 NaN S
... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 2 Montvila, Rev. Juozas male 0 0 0 211536 13.0000 NaN S
887 888 1 1 Graham, Miss. Margaret Edith female 0 0 0 112053 30.0000 B42 S
888 889 0 3 Johnston, Miss. Catherine Helen "Carrie" female 0 1 2 W./C. 6607 23.4500 NaN S
889 890 1 1 Behr, Mr. Karl Howell male 0 0 0 111369 30.0000 C148 C
890 891 0 3 Dooley, Mr. Patrick male 0 0 0 370376 7.7500 NaN Q
# Age column이 전부 다 0으로 변경된 것을 볼 수 있다.
좀 더 세부적인 인덱싱을 통해 원하는 행과 열만 골라내어 값 변경도 가능하다.
df.loc[100:300, 'Sex'] = None
df.loc[95:300]
=>
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
95 96 0 3 Shorney, Mr. Charles Joseph male 0 0 0 374910 8.0500 NaN S
96 97 0 1 Goldschmidt, Mr. George B male 0 0 0 PC 17754 34.6542 A5 C
97 98 1 1 Greenfield, Mr. William Bertram male 0 0 1 PC 17759 63.3583 D10 D12 C
98 99 1 2 Doling, Mrs. John T (Ada Julia Bone) female 0 0 1 231919 23.0000 NaN S
99 100 0 2 Kantor, Mr. Sinai male 0 1 0 244367 26.0000 NaN S
... ... ... ... ... ... ... ... ... ... ... ... ...
296 297 0 3 Hanna, Mr. Mansour None 0 0 0 2693 7.2292 NaN C
297 298 0 1 Allison, Miss. Helen Loraine None 0 1 2 113781 151.5500 C22 C26 S
298 299 1 1 Saalfeld, Mr. Adolphe None 0 0 0 19988 30.5000 C106 S
299 300 1 1 Baxter, Mrs. James (Helene DeLaudeniere Chaput) None 0 0 1 PC 17558 247.5208 B58 B60 C
300 301 1 3 Kelly, Miss. Anna Katherine "Annie Kate" None 0 0 0 9234 7.7500 NaN Q
2. iloc
.iloc은 정수 인덱스 포지션을 기반으로 인덱싱하는 방법이다. (개인적으로 .loc보다 편리해서 자주 사용하고 있는 인덱싱 기법이다.) 아래는 인덱스와 컬럼을 지정해서 인덱싱한 경우이다.
df.iloc[3,3] # 3번째 인덱스와 3번째 컬럼(Name)의 값
=> 'Futrelle, Mrs. Jacques Heath (Lily May Peel)'
df.iloc[1:5,3:5] # 1~4번째 인덱스와 3~4번째 컬럼의 값. 데이터프레임을 리턴한다.
=>
Name Sex
1 Cumings, Mrs. John Bradley (Florence Briggs Th... female
2 Heikkinen, Miss. Laina female
3 Futrelle, Mrs. Jacques Heath (Lily May Peel) female
4 Allen, Mr. William Henry male
df.iloc[[2,5,7],[3,6]] # integer 배열
=>
Name SibSp
2 Heikkinen, Miss. Laina 0
5 Moran, Mr. James 0
7 Palsson, Master. Gosta Leonard 3
.iloc도 마찬가지로 데이터에 접근하여 값 변경이 가능하다.
df.iloc[2:4, [3,6]] = 0 # Name, SibSp 컬럼의 2~4번째 인덱스 값을 0으로 변경
df.head()
=>
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 0 female 0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 0 female 0 0 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 0 0 0 373450 8.0500 NaN S
참고자료
[1] Runner Bean, "Pandas: Pandas Series - Why use loc?", stackoverflow, https://stackoverflow.com/questions/38886080/python-pandas-series-why-use-loc
[2] "User Guide: Indexing and selecting data" , Pandas, https://pandas.pydata.org/docs/user_guide/indexing.html
'Python > Pandas' 카테고리의 다른 글
[Pandas] 판다스 결측치 처리 (2) | 2023.06.19 |
---|---|
[Pandas] 판다스 데이터프레임 합치기 (merge, concatenate) (0) | 2023.02.07 |
[Pandas] 판다스 기본 함수들 (1) | 2023.02.03 |
[Pandas] 판다스(Pandas)와 데이터 구조 (1) | 2023.01.31 |