🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

데이터 선택과 필터링 완벽 가이드 - 슬라이드 1/8
A

AI Generated

2025. 12. 16. · 11 Views

데이터 선택과 필터링 완벽 가이드

Pandas DataFrame에서 원하는 데이터만 골라내는 방법을 실무 상황 스토리로 배워봅니다. 컬럼 선택부터 복잡한 조건 필터링까지 술술 읽히는 이북 스타일로 정리했습니다.


목차

  1. 컬럼_선택하기
  2. loc으로_행과_열_선택
  3. iloc으로_인덱스_기반_선택
  4. 조건부_필터링_기초
  5. 여러_조건_결합하기
  6. isin으로_여러_값_필터링
  7. query_메서드_활용

1. 컬럼 선택하기

데이터 분석가 김개발 씨는 오늘도 수백 개의 컬럼이 있는 거대한 고객 데이터를 받았습니다. 그런데 분석에 필요한 것은 딱 세 개의 컬럼뿐입니다.

어떻게 하면 필요한 컬럼만 깔끔하게 추출할 수 있을까요?

DataFrame에서 특정 컬럼을 선택하는 것은 데이터 분석의 가장 기본이 되는 작업입니다. 마치 도서관에서 필요한 책만 골라 꺼내는 것처럼, 수십 개의 컬럼 중에서 분석에 필요한 컬럼만 선택할 수 있습니다.

단일 컬럼 선택과 여러 컬럼 동시 선택 방법을 알아두면 데이터를 훨씬 효율적으로 다룰 수 있습니다.

다음 코드를 살펴봅시다.

import pandas as pd

# 샘플 데이터 생성
df = pd.DataFrame({
    'name': ['김철수', '이영희', '박민수'],
    'age': [25, 30, 35],
    'city': ['서울', '부산', '대구'],
    'salary': [3000, 4000, 5000]
})

# 단일 컬럼 선택 - Series 반환
names = df['name']

# 여러 컬럼 선택 - DataFrame 반환
subset = df[['name', 'age', 'city']]
print(subset)

김개발 씨는 입사 1개월 차 데이터 분석가입니다. 오늘 팀장님으로부터 고객 데이터베이스에서 분석 보고서를 작성하라는 미션을 받았습니다.

그런데 데이터를 열어보니 컬럼이 무려 50개나 됩니다. "이 중에서 이름, 나이, 도시만 있으면 되는데..." 김개발 씨는 당황했습니다.

엑셀처럼 일일이 컬럼을 숨기고 보여주기를 반복할 수는 없습니다. 바로 그때 옆자리 선배 박시니어 씨가 다가왔습니다.

"컬럼 선택은 Pandas의 가장 기본이에요. 쉽게 알려드릴게요." 컬럼 선택이란 무엇일까요?

쉽게 비유하자면, 컬럼 선택은 마치 뷔페에서 원하는 음식만 접시에 담는 것과 같습니다. 수십 가지 음식이 있지만 내가 먹고 싶은 것만 골라 담듯이, 수십 개의 컬럼 중에서 필요한 것만 선택하는 것입니다.

Pandas가 없던 시절에는 어땠을까요? 개발자들은 데이터를 반복문으로 돌면서 필요한 컬럼의 인덱스를 일일이 찾아야 했습니다.

코드가 복잡해지고, 컬럼 순서가 바뀌면 프로그램이 망가지기 일쑤였습니다. 더 큰 문제는 가독성이었습니다.

숫자 인덱스만 보고는 어떤 데이터인지 알 수 없었으니까요. 바로 이런 문제를 해결하기 위해 Pandas의 컬럼 선택 기능이 등장했습니다.

컬럼 이름으로 직관적으로 데이터에 접근할 수 있게 되었습니다. 또한 단 한 줄의 코드로 여러 컬럼을 동시에 선택할 수 있게 되었습니다.

무엇보다 코드를 읽는 사람이 즉시 어떤 데이터를 다루는지 이해할 수 있다는 큰 이점이 있습니다. 위의 코드를 한 줄씩 살펴보겠습니다.

먼저 df['name'] 부분을 보면 단일 컬럼을 선택하는 것을 알 수 있습니다. 이 부분이 핵심입니다.

대괄호 안에 컬럼 이름을 문자열로 넣으면 해당 컬럼이 Series 형태로 반환됩니다. 다음으로 df[['name', 'age', 'city']] 부분에서는 여러 컬럼을 동시에 선택하는 동작이 일어납니다.

대괄호가 이중으로 사용된 것을 주목하세요. 바깥 대괄호는 인덱싱을, 안쪽 대괄호는 리스트를 의미합니다.

결과는 DataFrame 형태로 반환됩니다. 실제 현업에서는 어떻게 활용할까요?

예를 들어 전자상거래 서비스를 운영한다고 가정해봅시다. 주문 데이터에는 주문번호, 고객ID, 상품코드, 수량, 가격, 배송지, 연락처 등 수많은 정보가 들어있습니다.

하지만 매출 분석을 위해서는 날짜, 상품코드, 가격 세 가지만 있으면 충분합니다. 이때 컬럼 선택을 활용하면 필요한 데이터만 깔끔하게 추출할 수 있습니다.

많은 데이터 분석팀에서 이런 패턴을 적극적으로 사용하고 있습니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수 중 하나는 단일 컬럼을 선택할 때도 이중 대괄호를 사용하는 것입니다. 이렇게 하면 Series가 아닌 DataFrame이 반환되어 이후 연산에서 문제가 발생할 수 있습니다.

따라서 반환 타입을 명확히 이해하고 상황에 맞게 사용해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다. "아, 그래서 이중 대괄호를 쓰는 거였군요!" 컬럼 선택을 제대로 이해하면 더 깔끔하고 읽기 쉬운 데이터 분석 코드를 작성할 수 있습니다.

여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.

실전 팁

💡 - 단일 컬럼은 df['name'], 여러 컬럼은 df[['name', 'age']] 형식을 사용하세요

  • 컬럼 이름에 공백이나 특수문자가 있으면 반드시 대괄호 표기법을 사용해야 합니다
  • 존재하지 않는 컬럼을 선택하면 KeyError가 발생하므로 주의하세요

2. loc으로 행과 열 선택

김개발 씨는 이번에는 특정 고객의 특정 정보만 뽑아내야 하는 상황에 직면했습니다. 단순히 컬럼만 선택하는 것이 아니라, 특정 행과 특정 컬럼을 동시에 선택해야 합니다.

어떻게 해야 할까요?

loc은 라벨 기반으로 행과 열을 선택하는 강력한 도구입니다. 마치 주소록에서 이름으로 사람을 찾는 것처럼, 인덱스 이름과 컬럼 이름을 사용해 원하는 데이터에 정확히 접근할 수 있습니다.

행과 열을 동시에 선택할 수 있어 복잡한 데이터 추출 작업을 한 줄로 해결할 수 있습니다.

다음 코드를 살펴봅시다.

import pandas as pd

# 인덱스가 있는 데이터 생성
df = pd.DataFrame({
    'name': ['김철수', '이영희', '박민수'],
    'age': [25, 30, 35],
    'salary': [3000, 4000, 5000]
}, index=['emp001', 'emp002', 'emp003'])

# 특정 행 선택
person = df.loc['emp001']

# 특정 행의 특정 컬럼 선택
age = df.loc['emp002', 'age']

# 여러 행과 여러 컬럼 선택
subset = df.loc[['emp001', 'emp003'], ['name', 'salary']]
print(subset)

김개발 씨는 이제 컬럼 선택에 익숙해졌습니다. 하지만 오늘 받은 새로운 요청은 조금 달랐습니다.

"emp002 직원의 나이만 알려주세요"라는 구체적인 질문이었습니다. "음, 컬럼 선택으로는 안 되는데..." 김개발 씨는 또 막막해졌습니다.

전체 나이 데이터를 가져온 다음 거기서 또 찾아야 하나요? 박시니어 씨가 웃으며 말했습니다.

"이럴 때 바로 loc을 쓰는 거예요. 행과 열을 동시에 선택할 수 있답니다." loc이란 정확히 무엇일까요?

쉽게 비유하자면, loc은 마치 아파트 주소와 같습니다. "101동 503호"라고 말하면 정확히 그 집을 찾을 수 있듯이, "emp002행의 age 컬럼"이라고 지정하면 정확히 그 데이터를 가져올 수 있습니다.

동 번호가 행 인덱스, 호수가 컬럼 이름에 해당한다고 생각하면 됩니다. loc이 없던 시절에는 어땠을까요?

개발자들은 먼저 조건으로 행을 필터링한 다음, 거기서 다시 컬럼을 선택하는 두 단계 작업을 해야 했습니다. 코드가 길어지고, 중간 변수를 만들어야 해서 메모리도 낭비되었습니다.

더 큰 문제는 실수하기 쉽다는 점이었습니다. 여러 단계를 거치다 보면 어디선가 오류가 발생하기 마련이었으니까요.

바로 이런 문제를 해결하기 위해 loc 인덱서가 등장했습니다. 한 줄의 코드로 행과 열을 동시에 선택할 수 있게 되었습니다.

또한 라벨 기반이라 코드를 읽는 사람이 직관적으로 이해할 수 있게 되었습니다. 무엇보다 슬라이싱도 지원하여 범위 선택까지 가능하다는 큰 이점이 있습니다.

위의 코드를 한 줄씩 살펴보겠습니다. 먼저 df.loc['emp001'] 부분을 보면 특정 행 전체를 선택하는 것을 알 수 있습니다.

이 부분이 핵심입니다. 인덱스 이름만 지정하면 해당 행의 모든 컬럼이 Series 형태로 반환됩니다.

다음으로 df.loc['emp002', 'age'] 부분에서는 특정 행의 특정 컬럼, 즉 하나의 값을 선택하는 동작이 일어납니다. 첫 번째 인자가 행 인덱스, 두 번째 인자가 컬럼 이름입니다.

결과는 스칼라 값으로 반환됩니다. 마지막으로 df.loc[['emp001', 'emp003'], ['name', 'salary']] 부분에서는 여러 행과 여러 컬럼을 동시에 선택합니다.

리스트를 사용해 원하는 행과 컬럼을 지정하면 해당 부분만 담긴 DataFrame이 반환됩니다. 실제 현업에서는 어떻게 활용할까요?

예를 들어 회원제 웹사이트를 운영한다고 가정해봅시다. 회원 ID를 인덱스로 설정한 데이터프레임이 있습니다.

고객센터에서 "USER12345 회원의 이메일 주소를 알려주세요"라는 요청이 왔습니다. 이때 df.loc['USER12345', 'email'] 한 줄이면 즉시 정보를 찾을 수 있습니다.

많은 서비스 기업에서 이런 패턴을 적극적으로 사용하고 있습니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수 중 하나는 숫자 인덱스를 가진 데이터프레임에서 loc과 iloc을 혼동하는 것입니다. loc은 항상 라벨을 사용합니다.

만약 인덱스가 0, 1, 2라면 **df.loc[0]**은 라벨이 0인 행을 찾습니다. 이것은 첫 번째 행과는 다를 수 있습니다.

따라서 라벨 기반인지 위치 기반인지 명확히 구분해서 사용해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 설명을 들은 김개발 씨는 환하게 웃었습니다. "이제 정확히 원하는 데이터만 골라낼 수 있겠어요!" loc을 제대로 이해하면 더 정확하고 효율적인 데이터 접근 코드를 작성할 수 있습니다.

여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.

실전 팁

💡 - loc은 라벨 기반, iloc은 위치 기반입니다. 상황에 맞게 선택하세요

  • 슬라이싱도 가능합니다: df.loc['emp001':'emp003'] (끝 포함)
  • 불린 배열과 함께 사용하면 조건부 선택도 가능합니다

3. iloc으로 인덱스 기반 선택

김개발 씨는 "위에서 5개 행만 보여주세요"라는 요청을 받았습니다. 인덱스 이름이 뭔지는 중요하지 않고, 그냥 순서대로 처음 5개만 필요한 상황입니다.

loc으로는 어떻게 할 수 있을까요?

iloc은 정수 위치 기반으로 행과 열을 선택하는 도구입니다. 마치 줄을 서 있는 사람들에게 "앞에서 3명"이라고 말하는 것처럼, 인덱스 이름이나 컬럼 이름과 관계없이 순서만으로 데이터에 접근할 수 있습니다.

데이터의 라벨을 모르거나 순서가 중요할 때 유용합니다.

다음 코드를 살펴봅시다.

import pandas as pd

df = pd.DataFrame({
    'name': ['김철수', '이영희', '박민수', '정지훈', '최수연'],
    'age': [25, 30, 35, 28, 32],
    'salary': [3000, 4000, 5000, 3500, 4500]
})

# 첫 번째 행 선택 (인덱스 0)
first_row = df.iloc[0]

# 특정 위치의 값 선택 (1행 2열)
value = df.iloc[1, 2]

# 처음 3개 행, 처음 2개 컬럼 선택
subset = df.iloc[0:3, 0:2]

# 마지막 2개 행 선택
last_two = df.iloc[-2:]
print(last_two)

김개발 씨는 loc을 마스터했습니다. 하지만 오늘 팀장님의 요청은 조금 달랐습니다.

"데이터가 너무 많으니 일단 처음 10개만 보여주세요." 김개발 씨는 당황했습니다. 인덱스 이름을 일일이 확인해서 loc에 넣어야 하나요?

데이터가 수천 개인데 그럴 수는 없는 일입니다. 박시니어 씨가 지나가다 말했습니다.

"순서로 선택할 때는 iloc을 쓰면 돼요. 훨씬 간단하답니다." iloc이란 정확히 무엇일까요?

쉽게 비유하자면, iloc은 마치 영화관 좌석번호와 같습니다. "A열 5번"이 아니라 "앞에서 두 번째 줄, 왼쪽에서 다섯 번째"처럼 순서로 위치를 지정하는 것입니다.

좌석 번호를 몰라도 순서만 알면 자리를 찾을 수 있듯이, iloc도 라벨을 몰라도 위치만 알면 데이터에 접근할 수 있습니다. 위치 기반 선택이 없던 시절에는 어땠을까요?

개발자들은 먼저 인덱스를 리스트로 변환하고, 그 중에서 원하는 위치의 인덱스를 찾아내고, 그걸 다시 loc에 넣는 복잡한 과정을 거쳐야 했습니다. 특히 "처음 N개" 같은 간단한 요청도 여러 줄의 코드가 필요했습니다.

더 큰 문제는 코드 가독성이었습니다. 의도를 파악하기 어려웠으니까요.

바로 이런 문제를 해결하기 위해 iloc 인덱서가 등장했습니다. Python의 리스트 인덱싱과 똑같은 방식으로 데이터에 접근할 수 있게 되었습니다.

또한 음수 인덱스도 지원하여 뒤에서부터 세는 것도 가능해졌습니다. 무엇보다 슬라이싱이 직관적이어서 "처음 N개", "마지막 N개" 같은 작업을 한 줄로 처리할 수 있다는 큰 이점이 있습니다.

위의 코드를 한 줄씩 살펴보겠습니다. 먼저 df.iloc[0] 부분을 보면 첫 번째 행을 선택하는 것을 알 수 있습니다.

이 부분이 핵심입니다. Python의 리스트처럼 0부터 시작하는 인덱스를 사용합니다.

다음으로 df.iloc[1, 2] 부분에서는 1번 행(두 번째 행)의 2번 컬럼(세 번째 컬럼)에 있는 값을 선택하는 동작이 일어납니다. 행과 열 모두 0부터 시작하는 정수 위치를 사용합니다.

df.iloc[0:3, 0:2] 부분에서는 슬라이싱이 사용됩니다. Python의 일반적인 슬라이싱 규칙을 따라 시작점은 포함되고 끝점은 포함되지 않습니다.

따라서 0, 1, 2번 행과 0, 1번 컬럼이 선택됩니다. 마지막으로 df.iloc[-2:] 부분에서는 음수 인덱스를 사용합니다.

-2는 뒤에서 두 번째를 의미하므로, 마지막 2개 행이 선택됩니다. 결과는 DataFrame 형태로 반환됩니다.

실제 현업에서는 어떻게 활용할까요? 예를 들어 실시간 주식 데이터를 수집하는 시스템을 개발한다고 가정해봅시다.

매초 새로운 데이터가 추가되는데, 화면에는 최근 20개의 데이터만 보여주면 됩니다. 이때 **df.iloc[-20:]**를 사용하면 항상 최신 20개 데이터만 간단히 가져올 수 있습니다.

많은 금융 서비스에서 이런 패턴을 적극적으로 사용하고 있습니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수 중 하나는 데이터프레임의 인덱스가 재정렬되어 있을 때 iloc의 동작을 오해하는 것입니다. iloc은 항상 현재 순서를 기준으로 작동합니다.

만약 데이터를 정렬했다면 iloc[0]은 정렬된 후의 첫 번째 행을 가리킵니다. 따라서 순서 변경 작업 후에는 iloc이 가리키는 데이터가 달라질 수 있음을 인지해야 합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 손뼉을 쳤습니다.

"이제 처음 N개, 마지막 N개 같은 요청은 쉽게 처리할 수 있겠어요!" iloc을 제대로 이해하면 더 간결하고 Python스러운 데이터 접근 코드를 작성할 수 있습니다. 여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.

실전 팁

💡 - iloc은 Python 리스트와 같은 인덱싱 규칙을 따릅니다 (0부터 시작, 슬라이싱 끝점 미포함)

  • 음수 인덱스로 뒤에서부터 접근 가능합니다: df.iloc[-1]은 마지막 행
  • loc은 끝점 포함, iloc은 끝점 미포함이라는 차이를 기억하세요

4. 조건부 필터링 기초

김개발 씨는 "나이가 30살 이상인 직원만 보여주세요"라는 요청을 받았습니다. 이제는 특정 위치가 아니라 특정 조건을 만족하는 데이터를 찾아야 합니다.

어떻게 해야 할까요?

조건부 필터링은 특정 조건을 만족하는 행만 선택하는 강력한 기능입니다. 마치 쇼핑몰에서 "가격 5만원 이하" 필터를 적용하는 것처럼, 원하는 조건에 맞는 데이터만 골라낼 수 있습니다.

비교 연산자를 사용해 불린 마스크를 만들고, 이를 인덱싱에 활용하는 방식으로 작동합니다.

다음 코드를 살펴봅시다.

import pandas as pd

df = pd.DataFrame({
    'name': ['김철수', '이영희', '박민수', '정지훈', '최수연'],
    'age': [25, 30, 35, 28, 32],
    'city': ['서울', '부산', '서울', '대구', '서울'],
    'salary': [3000, 4000, 5000, 3500, 4500]
})

# 조건 생성 - 불린 Series 반환
condition = df['age'] >= 30

# 조건으로 필터링
filtered = df[condition]

# 한 줄로 작성
result = df[df['salary'] > 4000]
print(result)

김개발 씨는 이제 위치 기반 선택에 익숙해졌습니다. 하지만 오늘 받은 요청은 완전히 다른 종류였습니다.

"연봉이 4000 이상인 직원 명단을 뽑아주세요." "위치를 알 수 없는데 어떻게 찾지?" 김개발 씨는 고민에 빠졌습니다. 일일이 데이터를 확인해서 위치를 찾을 수는 없는 노릇입니다.

박시니어 씨가 커피를 한 모금 마시며 말했습니다. "이제 진짜 데이터 분석의 핵심인 조건부 필터링을 배울 때가 왔네요." 조건부 필터링이란 정확히 무엇일까요?

쉽게 비유하자면, 조건부 필터링은 마치 학교에서 키 순서로 줄을 세우는 것과 같습니다. 선생님이 "키가 170cm 이상인 학생들은 앞으로 나오세요"라고 하면, 조건을 만족하는 학생들만 자동으로 선별됩니다.

Pandas도 똑같이 작동합니다. 조건을 주면 그 조건을 만족하는 행만 자동으로 골라냅니다.

조건부 필터링이 없던 시절에는 어땠을까요? 개발자들은 for 반복문으로 모든 행을 하나씩 순회하면서 조건을 체크하고, 만족하는 행만 새로운 리스트에 추가하는 방식을 써야 했습니다.

코드가 길고 복잡했으며, 무엇보다 느렸습니다. 데이터가 수백만 건이면 처리 시간이 엄청나게 오래 걸렸습니다.

바로 이런 문제를 해결하기 위해 불린 인덱싱 방식의 조건부 필터링이 등장했습니다. 벡터화 연산을 통해 모든 행을 동시에 검사할 수 있게 되었습니다.

또한 코드가 한 줄로 간결해져 가독성이 크게 향상되었습니다. 무엇보다 C로 구현된 내부 연산 덕분에 처리 속도가 획기적으로 빨라졌다는 큰 이점이 있습니다.

위의 코드를 한 줄씩 살펴보겠습니다. 먼저 df['age'] >= 30 부분을 보면 조건식이 만들어지는 것을 알 수 있습니다.

이 부분이 핵심입니다. 이 연산은 각 행에 대해 True 또는 False 값을 가지는 불린 Series를 반환합니다.

다음으로 df[condition] 부분에서는 불린 Series를 인덱싱에 사용하는 동작이 일어납니다. True인 위치의 행만 선택되어 새로운 DataFrame이 생성됩니다.

False인 행은 자동으로 제외됩니다. df[df['salary'] > 4000] 부분에서는 조건 생성과 필터링을 한 줄로 합쳤습니다.

안쪽의 df['salary'] > 4000이 먼저 평가되어 불린 Series가 되고, 이것이 바로 바깥쪽 대괄호 안에서 필터링에 사용됩니다. 결과는 연봉이 4000을 초과하는 행만 담긴 DataFrame입니다.

실제 현업에서는 어떻게 활용할까요? 예를 들어 온라인 쇼핑몰의 주문 관리 시스템을 개발한다고 가정해봅시다.

배송 담당자는 "오늘 서울 지역 주문 중 10만원 이상인 것만 보여주세요"라는 요청을 자주 합니다. 이때 df[df['region'] == '서울'][df['amount'] >= 100000] 같은 필터링을 사용하면 원하는 주문만 즉시 추출할 수 있습니다.

많은 이커머스 기업에서 이런 패턴을 적극적으로 사용하고 있습니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수 중 하나는 조건식을 작성할 때 and, or 같은 Python 키워드를 사용하는 것입니다. Pandas에서는 &, | 같은 비트 연산자를 사용해야 합니다.

그리고 각 조건을 괄호로 묶어야 연산 순서가 올바르게 적용됩니다. 따라서 여러 조건을 결합할 때는 문법에 주의해야 합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 감탄했습니다.

"이제 원하는 조건의 데이터를 자유자재로 뽑아낼 수 있겠어요!" 조건부 필터링을 제대로 이해하면 더 강력하고 유연한 데이터 분석 코드를 작성할 수 있습니다. 여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.

실전 팁

💡 - 조건식은 먼저 변수에 저장하면 디버깅이 쉽습니다

  • 필터링 결과가 빈 DataFrame일 수 있으니 체크하세요
  • ==, !=, >, <, >=, <= 등 다양한 비교 연산자를 활용할 수 있습니다

5. 여러 조건 결합하기

김개발 씨는 이번에는 "서울에 사는 사람 중에 나이가 30살 이상인 사람"을 찾아야 합니다. 두 가지 조건을 동시에 만족하는 데이터를 어떻게 찾을 수 있을까요?

여러 조건 결합은 복잡한 필터링을 가능하게 하는 핵심 기술입니다. 마치 부동산 앱에서 "강남구 + 3억 이하 + 방 2개 이상" 같은 복합 조건으로 검색하는 것처럼, AND와 OR 연산자를 사용해 여러 조건을 조합할 수 있습니다.

비트 연산자 &와 |를 사용하며, 각 조건은 반드시 괄호로 묶어야 합니다.

다음 코드를 살펴봅시다.

import pandas as pd

df = pd.DataFrame({
    'name': ['김철수', '이영희', '박민수', '정지훈', '최수연'],
    'age': [25, 30, 35, 28, 32],
    'city': ['서울', '부산', '서울', '대구', '서울'],
    'salary': [3000, 4000, 5000, 3500, 4500]
})

# AND 조건: 서울에 살고 나이가 30 이상
result_and = df[(df['city'] == '서울') & (df['age'] >= 30)]

# OR 조건: 부산에 살거나 연봉이 4500 이상
result_or = df[(df['city'] == '부산') | (df['salary'] >= 4500)]

# 복잡한 조건 결합
complex = df[(df['city'] == '서울') & ((df['age'] >= 30) | (df['salary'] >= 4000))]
print(complex)

김개발 씨는 단순 조건 필터링에 자신감이 붙었습니다. 하지만 오늘 마케팅 팀에서 날아온 요청은 훨씬 복잡했습니다.

"서울에 사는 30대 중에서 연봉이 4000 이상인 사람들에게 프로모션을 보내려고 해요." "세 가지 조건을 다 만족하는 사람을 어떻게 찾지?" 김개발 씨는 또 막막해졌습니다. 필터링을 세 번 연속으로 해야 하나요?

박시니어 씨가 화이트보드에 그림을 그리며 설명하기 시작했습니다. "ANDOR 연산자로 조건을 결합하면 한 번에 처리할 수 있어요." 여러 조건 결합이란 정확히 무엇일까요?

쉽게 비유하자면, 여러 조건 결합은 마치 채용 공고의 지원 자격과 같습니다. "4년제 대졸 이상 AND 경력 3년 이상 AND (Python 가능 OR Java 가능)" 같은 복합 조건으로 지원자를 필터링하는 것입니다.

모든 조건을 동시에 검사해서 최종 결과를 얻을 수 있습니다. 복합 조건이 없던 시절에는 어땠을까요?

개발자들은 조건을 하나씩 적용해야 했습니다. 첫 번째 조건으로 필터링한 결과를 변수에 저장하고, 그 결과에 두 번째 조건을 적용하고, 또 그 결과에 세 번째 조건을 적용하는 식이었습니다.

코드가 길어지고, 중간 변수가 많아져 메모리를 낭비했으며, 무엇보다 실수하기 쉬웠습니다. 바로 이런 문제를 해결하기 위해 비트 연산자를 활용한 조건 결합이 등장했습니다.

여러 조건을 한 줄의 코드로 표현할 수 있게 되었습니다. 또한 벡터화 연산이라 속도가 매우 빠릅니다.

무엇보다 SQL의 WHERE 절처럼 직관적으로 조건을 읽고 쓸 수 있다는 큰 이점이 있습니다. 위의 코드를 한 줄씩 살펴보겠습니다.

먼저 (df['city'] == '서울') & (df['age'] >= 30) 부분을 보면 AND 연산이 사용된 것을 알 수 있습니다. 이 부분이 핵심입니다.

& 연산자는 두 조건이 모두 True인 행만 True를 반환합니다. 각 조건이 괄호로 묶여 있어 연산 순서가 명확합니다.

다음으로 (df['city'] == '부산') | (df['salary'] >= 4500) 부분에서는 OR 연산이 일어납니다. | 연산자는 두 조건 중 하나라도 True이면 True를 반환합니다.

부산에 살거나, 또는 연봉이 4500 이상이면 선택됩니다. 마지막 complex 변수에서는 AND와 OR이 함께 사용됩니다.

서울에 살면서, 동시에 (나이가 30 이상이거나 연봉이 4000 이상)인 조건입니다. 괄호를 사용해 OR 조건을 먼저 평가한 다음, 그 결과와 서울 조건을 AND로 결합합니다.

실제 현업에서는 어떻게 활용할까요? 예를 들어 금융 서비스에서 대출 자격을 판단하는 시스템을 개발한다고 가정해봅시다.

"나이 20세 이상 65세 미만 AND 신용점수 700 이상 AND (재직기간 1년 이상 OR 자산 5천만원 이상)" 같은 복잡한 조건으로 고객을 필터링해야 합니다. 이때 조건 결합을 사용하면 복잡한 비즈니스 로직을 명확한 코드로 표현할 수 있습니다.

많은 핀테크 기업에서 이런 패턴을 적극적으로 사용하고 있습니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수 중 하나는 Python의 and, or 키워드를 사용하는 것입니다. Pandas는 시리즈 전체에 대한 벡터 연산을 수행하므로 반드시 &, | 비트 연산자를 써야 합니다.

또한 각 조건을 괄호로 묶지 않으면 연산자 우선순위 때문에 예상과 다른 결과가 나올 수 있습니다. 따라서 항상 조건마다 괄호를 사용하는 습관을 들여야 합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 눈이 반짝였습니다.

"이제 아무리 복잡한 조건도 처리할 수 있겠어요!" 여러 조건 결합을 제대로 이해하면 더 정교하고 강력한 데이터 분석 코드를 작성할 수 있습니다. 여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.

실전 팁

💡 - and, or 대신 &, | 비트 연산자를 사용하세요

  • 각 조건은 반드시 괄호로 묶어야 합니다
  • NOT 조건은 ~(틸드) 연산자로 표현합니다: ~(df['age'] > 30)

6. isin으로 여러 값 필터링

김개발 씨는 "서울, 부산, 대구에 사는 사람들"을 찾아야 합니다. OR 조건을 세 번 쓰면 되긴 하는데, 도시가 10개라면 코드가 너무 길어질 것 같습니다.

더 간단한 방법은 없을까요?

isin() 메서드는 특정 컬럼의 값이 주어진 리스트에 포함되는지 확인하는 편리한 도구입니다. 마치 "VIP 고객 명단에 있는 사람"을 찾는 것처럼, 여러 값 중 하나라도 일치하면 True를 반환합니다.

여러 개의 OR 조건을 간결하게 하나로 표현할 수 있어 코드 가독성이 크게 향상됩니다.

다음 코드를 살펴봅시다.

import pandas as pd

df = pd.DataFrame({
    'name': ['김철수', '이영희', '박민수', '정지훈', '최수연'],
    'age': [25, 30, 35, 28, 32],
    'city': ['서울', '부산', '서울', '대구', '인천'],
    'department': ['개발', '마케팅', '개발', '영업', '개발']
})

# 특정 도시들에 사는 사람 찾기
cities = ['서울', '부산', '대구']
result = df[df['city'].isin(cities)]

# 특정 부서들 찾기
departments = ['개발', '디자인']
dev_team = df[df['department'].isin(departments)]

# isin과 다른 조건 결합
complex = df[df['city'].isin(['서울', '부산']) & (df['age'] >= 30)]
print(complex)

김개발 씨는 조건 결합도 마스터했습니다. 하지만 오늘 HR팀에서 온 요청은 좀 특이했습니다.

"개발팀, 디자인팀, 기획팀, 마케팅팀, 운영팀 소속 직원들의 명단을 뽑아주세요." 김개발 씨는 코드를 작성하기 시작했습니다. "(department == '개발') | (department == '디자인') | (department == '기획')..." 아직 두 개밖에 안 썼는데 벌써 코드가 너무 길어 보입니다.

박시니어 씨가 웃으며 말했습니다. "이럴 때 isin() 메서드를 쓰면 훨씬 간단해요.

리스트로 한 방에 처리할 수 있답니다." isin() 메서드란 정확히 무엇일까요? 쉽게 비유하자면, isin()은 마치 클럽 입장 시 명단 체크와 같습니다.

경비원이 손님의 이름을 VIP 명단과 대조해보고, 명단에 있으면 입장시키는 것입니다. isin()도 똑같이 작동합니다.

주어진 리스트에 값이 있는지 확인하고, 있으면 True를 반환합니다. isin()이 없던 시절에는 어땠을까요?

개발자들은 OR 조건을 수없이 반복해야 했습니다. 확인할 값이 10개면 OR를 9번 써야 했습니다.

코드가 지나치게 길어져 읽기 어려웠고, 값을 하나 추가하려면 코드를 다시 수정해야 했습니다. 더 큰 문제는 실수하기 쉽다는 점이었습니다.

괄호를 잘못 닫거나 연산자를 빠뜨리면 버그가 발생했습니다. 바로 이런 문제를 해결하기 위해 isin() 메서드가 등장했습니다.

리스트 하나면 모든 OR 조건을 표현할 수 있게 되었습니다. 또한 코드가 한 줄로 간결해져 가독성이 크게 향상되었습니다.

무엇보다 리스트만 수정하면 되므로 유지보수가 쉬워졌다는 큰 이점이 있습니다. 위의 코드를 한 줄씩 살펴보겠습니다.

먼저 df['city'].isin(cities) 부분을 보면 컬럼의 각 값이 리스트에 포함되는지 검사하는 것을 알 수 있습니다. 이 부분이 핵심입니다.

isin() 메서드는 각 행에 대해 True 또는 False 값을 가지는 불린 Series를 반환합니다. cities 변수에는 확인하고 싶은 값들의 리스트가 들어 있습니다.

이 리스트는 변수로 분리해두면 재사용하기 편리합니다. 나중에 도시를 추가하거나 제거할 때도 리스트만 수정하면 됩니다.

df[df['department'].isin(departments)] 부분에서는 부서 컬럼에 isin()을 적용합니다. '개발' 또는 '디자인' 부서에 속한 직원만 선택됩니다.

결과는 조건을 만족하는 행만 담긴 DataFrame입니다. 마지막 complex 변수에서는 isin()과 일반 비교 조건을 결합합니다.

서울 또는 부산에 살면서 동시에 나이가 30 이상인 사람을 찾습니다. isin()도 불린 Series를 반환하므로 & 연산자로 다른 조건과 자유롭게 결합할 수 있습니다.

실제 현업에서는 어떻게 활용할까요? 예를 들어 교육 플랫폼에서 특정 과목 수강생들에게 공지를 보내는 시스템을 개발한다고 가정해봅시다.

"Python, JavaScript, Java, C++, Go 수강생들에게만 알림을 보내주세요"라는 요청이 왔습니다. 이때 **df[df['course'].isin(['Python', 'JavaScript', 'Java', 'C++', 'Go'])]**를 사용하면 해당 과목 수강생만 즉시 추출할 수 있습니다.

많은 에듀테크 기업에서 이런 패턴을 적극적으로 사용하고 있습니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수 중 하나는 isin()에 단일 값을 넘기는 것입니다. isin()은 반드시 리스트나 시퀀스를 받아야 합니다.

단일 값을 확인하려면 == 연산자를 사용하는 것이 더 적절합니다. 또한 isin()은 정확히 일치하는 값만 찾으므로, 부분 문자열 검색이 필요하면 str.contains() 메서드를 사용해야 합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 무릎을 쳤습니다.

"이제 여러 값을 확인하는 조건도 간단하게 작성할 수 있겠어요!" isin() 메서드를 제대로 이해하면 더 간결하고 유지보수하기 쉬운 필터링 코드를 작성할 수 있습니다. 여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.

실전 팁

💡 - 반대 조건(NOT IN)은 ~를 사용하세요: df[~df['city'].isin(cities)]

  • isin()은 리스트뿐 아니라 set, tuple 등 모든 시퀀스를 받을 수 있습니다
  • 큰 리스트를 반복 사용한다면 변수에 저장해두면 편리합니다

7. query 메서드 활용

김개발 씨는 이제 복잡한 필터링도 자유자재로 할 수 있게 되었습니다. 하지만 조건이 복잡할수록 괄호가 많아져 코드가 지저분해 보입니다.

더 깔끔하게 작성할 방법은 없을까요?

query() 메서드는 SQL의 WHERE 절처럼 문자열로 조건을 작성할 수 있는 편리한 기능입니다. 마치 자연어로 질문하듯이 조건을 표현할 수 있어 가독성이 뛰어납니다.

복잡한 괄호와 비트 연산자 대신 and, or 같은 직관적인 키워드를 사용할 수 있습니다.

다음 코드를 살펴봅시다.

import pandas as pd

df = pd.DataFrame({
    'name': ['김철수', '이영희', '박민수', '정지훈', '최수연'],
    'age': [25, 30, 35, 28, 32],
    'city': ['서울', '부산', '서울', '대구', '서울'],
    'salary': [3000, 4000, 5000, 3500, 4500]
})

# 기본 사용
result1 = df.query('age >= 30')

# 여러 조건 결합
result2 = df.query('city == "서울" and age >= 30')

# 변수 사용 (@ 기호)
min_age = 28
max_age = 33
result3 = df.query('@min_age <= age <= @max_age')

# isin 대체
cities = ['서울', '부산']
result4 = df.query('city in @cities')
print(result4)

김개발 씨는 이제 Pandas 필터링의 달인이 되었습니다. 하지만 오늘 작성한 코드를 보니 뭔가 아쉬운 느낌이 듭니다.

조건이 복잡할수록 괄호가 산처럼 쌓이고, & 기호와 | 기호가 난무합니다. "코드를 읽는 사람이 이해하기 쉽게 쓸 방법은 없을까?" 김개발 씨는 고민에 빠졌습니다.

박시니어 씨가 새로운 파일을 열며 말했습니다. "SQL을 써본 적 있나요?

query() 메서드를 쓰면 SQL의 WHERE 절처럼 조건을 작성할 수 있어요." query() 메서드란 정확히 무엇일까요? 쉽게 비유하자면, query()는 마치 구글 검색창과 같습니다.

복잡한 명령어를 외울 필요 없이 자연스러운 문장으로 질문하면 결과를 찾아주는 것입니다. "나이가 30 이상이고 서울에 사는 사람"이라고 쓰면 그대로 이해하고 데이터를 찾아줍니다.

query()가 없던 시절에는 어땠을까요? 개발자들은 앞서 배운 대괄호 인덱싱 방식으로 조건을 작성해야 했습니다.

조건이 복잡할수록 괄호가 중첩되고, 비트 연산자 때문에 코드가 직관적이지 않았습니다. 특히 Pandas를 처음 배우는 사람들은 왜 and 대신 **&**를 써야 하는지 혼란스러워했습니다.

바로 이런 문제를 해결하기 위해 query() 메서드가 등장했습니다. SQL처럼 익숙한 문법으로 조건을 작성할 수 있게 되었습니다.

또한 and, or 같은 자연스러운 키워드를 사용할 수 있어 가독성이 크게 향상되었습니다. 무엇보다 외부 변수도 @ 기호로 간단히 참조할 수 있다는 큰 이점이 있습니다.

위의 코드를 한 줄씩 살펴보겠습니다. 먼저 df.query('age >= 30') 부분을 보면 가장 기본적인 사용법을 알 수 있습니다.

이 부분이 핵심입니다. 조건을 문자열로 작성하면 query()가 이를 해석하여 필터링을 수행합니다.

컬럼 이름을 따옴표 없이 그대로 쓸 수 있습니다. 다음으로 df.query('city == "서울" and age >= 30') 부분에서는 여러 조건이 결합됩니다.

and 키워드를 사용할 수 있어 Python의 일반적인 문법과 일치합니다. 문자열 값은 큰따옴표나 작은따옴표로 묶어야 합니다.

바깥쪽 따옴표와 다른 종류를 사용하면 됩니다. df.query('@min_age <= age <= @max_age') 부분에서는 외부 변수를 사용합니다.

@ 기호를 변수 앞에 붙이면 Python 네임스페이스의 변수를 참조할 수 있습니다. 범위 조건도 수학적 표기법 그대로 작성할 수 있어 직관적입니다.

마지막으로 df.query('city in @cities') 부분에서는 in 연산자를 사용합니다. isin() 메서드 대신 SQL의 IN 문법을 그대로 사용할 수 있습니다.

외부 리스트 변수도 @ 기호로 참조합니다. 결과는 조건을 만족하는 행만 담긴 DataFrame입니다.

실제 현업에서는 어떻게 활용할까요? 예를 들어 데이터 분석 보고서를 자동으로 생성하는 시스템을 개발한다고 가정해봅시다.

비즈니스 팀에서 "지난 분기 매출이 1억 이상이고 성장률이 10% 이상인 제품"을 분석하고 싶다고 합니다. 이때 df.query('revenue >= 100000000 and growth_rate >= 0.1') 같은 쿼리를 사용하면 비개발자도 조건을 쉽게 이해할 수 있습니다.

많은 데이터 분석 팀에서 이런 패턴을 적극적으로 사용하고 있습니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수 중 하나는 컬럼 이름에 공백이나 특수문자가 있을 때 query()를 그대로 사용하는 것입니다. 이런 경우 백틱 기호로 컬럼 이름을 감싸야 합니다.

예를 들어 df.query('first name == "김철수"') 같은 식입니다. 또한 query()는 문자열을 파싱하므로 매우 복잡한 조건에서는 기존 방식보다 약간 느릴 수 있습니다.

따라서 성능이 중요한 상황에서는 벤치마크를 해보는 것이 좋습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 설명을 들은 김개발 씨는 감탄했습니다. "이제 복잡한 조건도 읽기 쉽게 작성할 수 있겠어요!" query() 메서드를 제대로 이해하면 더 읽기 쉽고 유지보수하기 좋은 데이터 필터링 코드를 작성할 수 있습니다.

여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.

실전 팁

💡 - 컬럼 이름에 공백이 있으면 백틱으로 감싸세요: column name

  • @를 사용해 외부 변수를 참조할 수 있습니다
  • and, or, not 같은 자연스러운 키워드를 사용할 수 있습니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#Pandas#DataFrame#데이터선택#필터링

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.