국비과정에서 배운 Pandas의 불리언 인덱싱(조건 필터링)과 결측치 처리를 정리했다. 데이터 분석에서 가장 실전적으로 쓰이는 파트다.
조건을 걸어 원하는 행(Row)만 추출하는 방법이다. 조건 결과가 True인 데이터만 남긴다고 해서 불리언 인덱싱이라 부른다.
| 연산자 | 의미 | 예시 |
|---|---|---|
== | 같다 | df['class'] == 'Business' |
!= | 다르다 | df['airline'] != 'Korean Air' |
>, < | 크다, 작다 | df['price'] > 500000 |
& | AND (그리고) | (조건1) & (조건2) |
\| | OR (또는) | (조건1) \| (조건2) |
가장 기본적인, 조건 하나로 걸러내는 방식이다.
import pandas as pd
# 1. 데이터 불러오기
df = pd.read_csv('Clean_Dataset.csv')
# 2. 'Business' 좌석 등급만 골라내기
# df[조건식] 형태로 작성
business_df = df[df['class'] == 'Business']
print("--- 비즈니스석 데이터 상위 5행 ---")
print(business_df.head())
print(f"전체 건수: {len(business_df)}건")
여러 조건을 동시에 만족하는 데이터를 찾을 때 쓴다.
⚠️ 조건마다 반드시 괄호
()를 쳐야 한다. 괄호 없이&나|를 쓰면 연산자 우선순위 문제로 에러가 난다.
import pandas as pd
df = pd.read_csv('Clean_Dataset.csv')
# 항공사가 'AirAsia'이면서 가격이 6,000원 이하인 항공권 찾기
condition = (df['airline'] == 'AirAsia') & (df['price'] <= 6000)
target_df = df[condition]
print("--- AirAsia & 6000원 이하 데이터 ---")
print(target_df.head())
데이터에 값이 비어 있는 상태인 NaN(Not a Number)을 처리하는 과정이다.
먼저 실습용으로 일부러 구멍(NaN)을 뚫어놓은 데이터를 만들어본다.
import pandas as pd
import numpy as np
# 1. 실습용 '구멍 난' 데이터 생성
data = {
'이름': ['자바', '바미', '초코', np.nan],
'나이': [3, np.nan, 5, 1],
'몸무게': [4.5, 3.2, np.nan, np.nan],
'소속': [np.nan, np.nan, np.nan, np.nan] # 모든 값이 결측치인 컬럼
}
df = pd.DataFrame(data)
print("--- 원본 데이터 (NaN 확인) ---")
print(df)
dropna() — "불량품은 버린다"
결측치가 있는 행이나 열을 삭제하는 도구다. how 옵션으로 얼마나 엄격하게 지울지 정한다.
how='any' (기본값): 행에 결측치가 하나라도 있으면 삭제how='all': 행의 모든 값이 결측치여야 삭제# 하나라도 NaN이 있으면 삭제 (대부분의 행이 사라질 수 있음)
df_any = df.dropna(how='any')
# 모든 값이 NaN인 행만 삭제 (여기서는 삭제되는 행이 없음)
df_all = df.dropna(how='all')
fillna() — "빈칸을 메운다"
삭제 대신 적절한 값으로 채워 넣는 도구다. 컬럼마다 다른 값으로 채우고 싶으면 딕셔너리로 지정할 수 있다.
import pandas as pd
import numpy as np
data = {
'이름': ['자바', '바미', '초코', np.nan],
'나이': [3, np.nan, 5, np.nan],
'몸무게': [4.5, 3.2, np.nan, np.nan],
'소속': ["한코딩", np.nan, np.nan, np.nan]
}
df = pd.DataFrame(data)
df_custom = df.fillna({'이름': '이름 없음', '나이': 0, '몸무게': 0, "소속": "무소속"})
print(df_custom)
값을 채우거나 삭제하기 전에, 어떤 컬럼에 결측치가 얼마나 있는지 먼저 파악해야 한다.
import pandas as pd
df = pd.read_csv('Clean_Dataset.csv')
# 각 컬럼별로 비어있는 데이터가 몇 개인지 합계 출력
print("--- 컬럼별 결측치 개수 ---")
print(df.isnull().sum())
import pandas as pd
import numpy as np
data = {
'이름': ['자바', '바미', '초코', np.nan],
'나이': [3, np.nan, 5, np.nan],
'몸무게': [4.5, 3.2, np.nan, np.nan],
'소속': ['SBS', np.nan, np.nan, np.nan]
}
df = pd.DataFrame(data)
print(df.isnull().sum())
isnull()은 각 셀이 결측치면 True, 아니면 False를 반환하고, 여기에 .sum()을 붙이면 컬럼별로 결측치 개수를 셀 수 있다.
지시사항에 따라 삭제(dropna)할지, 특정 값으로 채울지(fillna) 결정한다.
import pandas as pd
df = pd.read_csv('Clean_Dataset.csv')
# 방법 1: 결측치가 하나라도 있는 행을 통째로 삭제 (axis=0)
df_drop = df.dropna(axis=0)
# 방법 2: 결측치를 특정 값(예: 0)으로 채우기
df_fill_zero = df.fillna(0)
# 방법 3: 결측치를 해당 컬럼의 평균값으로 채우기 (가장 많이 권장됨)
price_mean = df['price'].mean()
df['price'] = df['price'].fillna(price_mean)
print("--- 결측치 처리 완료 ---")
import pandas as pd
import numpy as np
data = {
'이름': ['자바', '바미', '초코', np.nan],
'나이': [3, np.nan, 5, np.nan],
'몸무게': [4.5, 3.2, np.nan, np.nan],
'소속': ['SBS', np.nan, np.nan, np.nan]
}
df = pd.DataFrame(data)
# 방법 1: 결측치가 하나라도 있는 행을 통째로 삭제
df_drop = df.dropna(axis=0)
# 방법 2: 결측치를 특정 값(예: 0)으로 채우기
df_fill_zero = df.fillna(0)
print("--- 결측치 처리 완료 ---")
💡 무조건 삭제(
dropna)하면 데이터 손실이 크므로, 실무에서는 컬럼의 평균/중앙값 등으로 채우는fillna가 더 자주 권장된다.
Clean_Dataset.csv를 사용해서, 출발 도시(source_city)가 'Delhi'이고 도착 도시(destination_city)가 'Mumbai'인 데이터만 추출한 뒤, 가격(price) 높은 순서로 상위 10개를 출력하기.
import pandas as pd
df = pd.read_csv("Clean_Dataset.csv")
# 1. 조건 지정
condition = (df['source_city'] == 'Delhi') & (df['destination_city'] == 'Mumbai')
# 2. 필터링된 데이터프레임 생성
filtered_df = df[condition]
# 3. 필터링된 데이터에서 가격이 높은 순서대로 정렬
result = filtered_df.sort_values(by='price', ascending=False)
# 4. 출력
print(result.head(10))
다른 정답
import pandas as pd
df = pd.read_csv("clean_dataset.csv")
filtered_df = df[(df['source_city'] == 'Delhi') & (df['destination_city'] == 'Mumbai')]
result_df = filtered_df.sort_values(by='price', ascending=False)
print(result_df.head(10)[['source_city','destination_city','price']])
결과 값
source_city destination_city price
206787 Delhi Mumbai 95657
206878 Delhi Mumbai 91575
210742 Delhi Mumbai 90281
210743 Delhi Mumbai 90281
207626 Delhi Mumbai 87929
208388 Delhi Mumbai 87817
206877 Delhi Mumbai 86776
206875 Delhi Mumbai 86137
206876 Delhi Mumbai 86137
208731 Delhi Mumbai 85801
df[(조건1) & (조건2)] 형태를 기본 틀로 외워두면 편하다.isnull().sum()으로 먼저 현황을 파악한 뒤, 상황에 맞게 dropna()(삭제) 또는 fillna()(채우기)를 선택한다.국비과정에서 배운 데이터 시각화를 정리했다. 환경 설정(한글 폰트)부터 막대 그래프, 히스토그램, 박스 플롯까지 AICE 시험에서 자주 나오는 차트 위주로 다룬다.
파이썬 시각화의 기본은 Matplotlib과 세련된 디자인의 Seaborn이다. 한국어 데이터를 다룰 땐 한글 폰트 설정이 필수다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 1. 데이터 불러오기
df = pd.read_csv('Clean_Dataset.csv', index_col=0)
# 2. 한글 깨짐 방지 설정 (Windows 기준)
plt.rc('font', family='Malgun Gothic')
plt.rcParams['axes.unicode_minus'] = False # 마이너스 기호 깨짐 방지
print("시각화 준비 완료!")
💡 한글 폰트 설정을 빼먹으면 그래프의 한글 글자가 전부 네모(□)로 깨져서 나온다. 한국어 라벨을 쓸 계획이면 시각화 코드의 맨 앞에 항상 넣어두는 습관을 들이자.
| 분류 | 메소드 (함수) | 역할 및 목적 | 주요 파라미터 |
|---|---|---|---|
| 기본 설정 | plt.rc() / plt.rcParams | 한글 폰트, 마이너스 기호 깨짐 등 설정 | family(글꼴), size(글자 크기) |
| 기본 설정 | plt.figure() | 그래프를 그릴 도화지(Canvas) 준비 | figsize=(가로, 세로) (단위: inch) |
| 비교 (범주) | sns.barplot() | 막대 그래프. 그룹별 평균값 비교 | x, y, data, palette(색상) |
| 비교 (범주) | sns.countplot() | 항목별 데이터 개수를 자동으로 세어줌 | x, data, hue(추가 분류) |
| 분포 (수치) | sns.histplot() | 히스토그램. 데이터가 어디에 몰려 있는지 확인 | bins(막대 개수), kde(곡선 여부) |
| 분포 (수치) | sns.boxplot() ⭐ | 상자 그림. 사분위수와 이상치 확인 (시험 빈출) | x, y, data |
| 관계 | sns.scatterplot() | 산점도. 두 숫자 데이터 간 상관관계 확인 | x, y, data |
| 관계 | sns.heatmap() ⭐ | 히트맵. 상관계수를 색상으로 시각화 | data, annot=True(숫자 표시) |
| 꾸미기 | plt.title() | 그래프 상단에 제목 달기 | fontsize(글자 크기) |
| 꾸미기 | plt.xlabel() / ylabel() | X축/Y축에 이름(라벨) 붙이기 | label |
| 꾸미기 | plt.xticks(rotation=45) | X축 글자가 겹칠 때 각도를 회전 | rotation |
| 마무리 | plt.show() | 완성된 그래프를 화면에 출력 (마침표 역할) | - |
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 1. 데이터 불러오기
df = pd.read_csv('Clean_Dataset.csv')
plt.rc('font', family='Malgun Gothic')
# 2. 도화지 꺼내기
plt.figure(figsize=(12, 6))
# 3. 그림 그리기
# hue='airline'으로 색상 기준을 명시하고, legend=False로 중복 범례를 숨긴다.
sns.barplot(x='airline', y='price', data=df, hue='airline', palette='viridis', legend=False)
# 4. 이름표 붙이기
plt.title('항공사별 평균 항공권 가격 현황', fontsize=15)
plt.xlabel('항공사 이름')
plt.ylabel('평균 가격(INR)')
# 5. X축 글자 회전
plt.xticks(rotation=45)
# 6. 출력하기
plt.show()
| 메소드 | 기능 | 주요 매개변수 |
|---|---|---|
plt.plot() | 선 그래프 그리기 | x, y: 데이터, label: 범례에 표시할 이름, color: 색상 |
plt.title() | 그래프 제목 설정 | label: 제목 텍스트, fontsize: 글자 크기 |
plt.xlabel() | X축 라벨 설정 | xlabel: 축 이름 |
plt.ylabel() | Y축 라벨 설정 | ylabel: 축 이름 |
plt.legend() | 범례 표시 | loc: 위치(best, upper right 등) |
plt.show() | 그래프 출력 | 없음 (마지막에 호출) |
항공사별/남은 일수별 평균 가격 추이를 선 그래프로 그려보면:
import pandas as pd
import matplotlib.pyplot as plt
# 1. 데이터 불러오기
df = pd.read_csv('Clean_Dataset.csv', index_col=0)
# 2. 데이터 가공 (항공사별/남은일수별 평균 가격)
vistara = df[df['airline'] == 'Vistara'].groupby('days_left')['price'].mean()
air_india = df[df['airline'] == 'Air_India'].groupby('days_left')['price'].mean()
# 3. 그래프 그리기
plt.figure(figsize=(10, 5))
# 선 그래프 그리기
plt.plot(vistara.index, vistara.values, label='Vistara')
plt.plot(air_india.index, air_india.values, label='Air_India')
plt.title('Price Trend')
plt.xlabel('Days Left')
plt.ylabel('Avg Price')
plt.legend()
plt.show()
groupby()로 그룹별 평균을 미리 구해두고, 그 결과의 .index(x축)와 .values(y축)를 plt.plot()에 넣는 패턴이 자주 쓰인다.
"어느 항공사가 가장 비싼가?"처럼 그룹 간의 수치를 비교할 때 가장 좋은 차트다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('Clean_Dataset.csv', index_col=0)
plt.rc('font', family='Malgun Gothic')
# 항공사별 평균 가격 시각화
plt.figure(figsize=(10, 6))
# sns.barplot은 자동으로 평균을 계산해서 그려준다
sns.barplot(x='airline', y='price', data=df)
plt.title('항공사별 평균 항공권 가격')
plt.xlabel('항공사')
plt.ylabel('평균 가격')
plt.show()
다른 데이터로도 같은 패턴을 반복해서 익힐 수 있다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('student.csv', index_col=0)
plt.rc('font', family='Malgun Gothic')
plt.figure(figsize=(10, 6))
sns.barplot(x='name', y='age', data=df)
plt.title('이름별 평균 나이')
plt.xlabel('이름')
plt.ylabel('나이')
plt.show()
"항공권 가격은 주로 어느 가격대에 몰려 있는가?"처럼 분포를 확인할 때 사용한다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('Clean_Dataset.csv', index_col=0)
plt.rc('font', family='Malgun Gothic')
# 전체 항공권 가격 분포 확인
plt.figure(figsize=(10, 6))
# bins는 막대의 개수, kde는 부드러운 곡선 표시 여부
sns.histplot(df['price'], bins=50, kde=True, color='skyblue')
plt.title('항공권 가격 분포도')
plt.show()
AICE 시험에서 가장 중요하게 다루는 차트다. 최솟값, 최댓값, 중앙값, 그리고 이상치(점 모양)를 한눈에 보여준다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('Clean_Dataset.csv', index_col=0)
plt.rc('font', family='Malgun Gothic')
# 좌석 등급(class)별 가격 분포와 이상치 확인
plt.figure(figsize=(8, 6))
sns.boxplot(x='class', y='price', data=df)
plt.title('좌석 등급별 가격 분포 (Economy vs Business)')
plt.show()
박스 플롯 읽는 법
| 특징 | 의미 |
|---|---|
| 상자의 높낮이 | 평균적인 가격대 (비즈니스가 훨씬 높음) |
| 상자의 세로 길이 | 가격의 일관성 |
| 상자 밖의 점들 | 예외적인 가격 (평균치를 벗어난 이상치) |
Clean_Dataset.csv를 활용해서 '출발 도시(source_city)별 비행 시간(duration)의 평균'을 막대 그래프로 그리기.
sns.barplotpalette='Set2' 옵션 추가import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('Clean_Dataset.csv', index_col=0)
plt.figure(figsize=(10, 5))
sns.barplot(x='source_city', y='duration', data=df, hue='source_city', palette='Set1')
plt.show()
plt.figure() → 그래프 그리기 → plt.title/xlabel/ylabel → plt.show() 순서가 기본 뼈대라는 걸 기억하면 어떤 차트를 그리든 헷갈리지 않는다.