인덱싱과 선택
DataFrame에서 원하는 행과 열을 정확히 선택하는 것은 데이터 분석의 기본입니다. Pandas는 loc(라벨 기반), iloc(정수 위치 기반), 조건 필터링, query() 등 다양한 선택 방법을 제공합니다.
학습 목표
loc과 iloc의 차이를 이해하고 상황에 맞게 사용할 수 있다
불리언 조건으로 행을 필터링할 수 있다
query() 메서드로 간결한 조건 필터링을 작성할 수 있다
멀티인덱스의 기본 개념을 이해한다
왜 중요한가
데이터 분석에서는 전체 데이터가 아닌 특정 조건을 만족하는 부분 집합을 다루는 경우가 대부분입니다. 피처 열을 선택하고, 조건에 맞는 행을 필터링하며, 특정 셀의 값을 수정하는 것은 모든 분석 작업의 기초입니다.
loc — 라벨 기반 선택
import pandas as pd
import numpy as np
df = pd.DataFrame({
'이름' : [ '김철수' , '이영희' , '박민수' , '최지은' ],
'나이' : [ 25 , 30 , 28 , 35 ],
'부서' : [ '개발' , '마케팅' , '개발' , '인사' ],
'연봉' : [ 4000 , 4500 , 3800 , 5200 ]
}, index = [ 'a' , 'b' , 'c' , 'd' ])
# 단일 행
print (df.loc[ 'a' ])
# 행 범위 (라벨이므로 끝 포함)
print (df.loc[ 'a' : 'c' ]) # a, b, c 행 모두 포함
# 특정 행 + 특정 열
print (df.loc[ 'b' , '나이' ]) # 30
# 여러 행 + 여러 열
print (df.loc[[ 'a' , 'c' ], [ '이름' , '연봉' ]])
iloc — 정수 위치 기반 선택
# 단일 행 (0부터 시작)
print (df.iloc[ 0 ])
# 행 범위 (정수이므로 끝 미포함)
print (df.iloc[ 0 : 3 ]) # 0, 1, 2 행 (3 미포함)
# 특정 행 + 특정 열
print (df.iloc[ 1 , 2 ]) # 1행 2열의 값
# 슬라이싱
print (df.iloc[: 2 , 1 : 3 ]) # 상위 2행, 1~2열
구분 loc iloc 기준 라벨(이름) 정수 위치 범위 끝 포함 미포함 용도 열 이름/인덱스 이름으로 접근 위치 번호로 접근
조건 필터링
# 단일 조건
young = df[df[ '나이' ] < 30 ]
print (young)
# 복합 조건 (AND)
dev_young = df[(df[ '부서' ] == '개발' ) & (df[ '나이' ] < 30 )]
# 복합 조건 (OR)
high_salary = df[(df[ '연봉' ] >= 5000 ) | (df[ '부서' ] == '마케팅' )]
# isin으로 여러 값 필터링
selected = df[df[ '부서' ].isin([ '개발' , '인사' ])]
# between으로 범위 필터링
mid_age = df[df[ '나이' ].between( 25 , 30 )] # 25 이상 30 이하
# 문자열 조건
has_kim = df[df[ '이름' ].str.startswith( '김' )]
query() 메서드
query()는 문자열 표현식으로 필터링하며, 복잡한 조건도 가독성 있게 작성할 수 있습니다.
# 기본 사용
result = df.query( '나이 < 30' )
# 복합 조건
result = df.query( '나이 < 30 and 부서 == "개발"' )
# 변수 참조 (@)
min_salary = 4000
result = df.query( '연봉 >= @min_salary' )
# 리스트 포함 여부
depts = [ '개발' , '인사' ]
result = df.query( '부서 in @depts' )
조건이 복잡하거나 열 이름에 한글/공백이 없을 때는 query()가 가독성이 좋습니다. 열 이름에 공백이 있으면 백틱으로 감싸세요: df.query('`column name` > 10').
값 수정
# loc으로 특정 셀 수정
df.loc[ 'a' , '연봉' ] = 4200
# 조건에 맞는 행의 특정 열 수정
df.loc[df[ '부서' ] == '개발' , '연봉' ] = df.loc[df[ '부서' ] == '개발' , '연봉' ] * 1.1
# 새 열 추가 (조건 기반)
df[ '고연봉' ] = df[ '연봉' ] >= 4500
df[df['조건']]['열'] = 값 형태는 SettingWithCopyWarning을 발생시킵니다. 항상 df.loc[조건, '열'] = 값 형태를 사용하세요.
멀티인덱스 기초
# 멀티인덱스 생성
df_multi = df.set_index([ '부서' , '이름' ])
print (df_multi)
# 레벨별 선택
print (df_multi.loc[ '개발' ]) # 부서가 '개발'인 행
print (df_multi.loc[( '개발' , '김철수' )]) # 부서 + 이름으로 정확한 행
# xs로 특정 레벨의 값 선택
print (df_multi.xs( '김철수' , level = '이름' ))
AI/ML에서의 활용
피처 선택 : df[feature_columns]로 학습에 사용할 피처만 추출합니다
데이터 분할 : 조건 필터링으로 특정 조건의 서브셋을 만듭니다
레이블 분리 : X = df.drop('target', axis=1), y = df['target']
데이터 정제 : loc으로 이상치나 오류 값을 수정합니다
at은 단일 스칼라 값에 접근할 때 loc보다 빠릅니다. df.at['a', '나이']처럼 사용합니다. 여러 행이나 열을 선택할 때는 loc을, 단일 값 접근이 빈번할 때는 at을 사용하세요.
SettingWithCopyWarning은 왜 발생하나요?
체인 인덱싱(df[조건]['열'])은 중간에 복사본이 생성될 수 있어, 수정이 원본에 반영되지 않을 수 있습니다. df.loc[조건, '열']을 사용하면 이 문제를 피할 수 있습니다.
체크리스트
다음 문서