안녕하세요, IT와 테크 지식을 공부하고 기록하는 루카(Luka)입니다.

데이터, 그 무한한 가능성의 시작: 왜 Pandas인가?

현대 사회는 데이터의 홍수 속에 살고 있습니다. 기업의 비즈니스 의사결정부터 과학 연구, 개인의 일상에 이르기까지, 데이터는 이제 선택이 아닌 필수가 되었죠. 하지만 '날것'의 데이터는 그 자체로 가치를 가지기 어렵습니다. 복잡하고, 누락되어 있으며, 때로는 오류를 포함하기도 합니다. 이러한 데이터를 가공하고, 정제하며, 의미 있는 정보로 탈바꿈시키는 과정이 바로 '데이터 분석'이며, 이때 가장 강력하고 대중적으로 사용되는 도구가 바로 파이썬의 pandas 라이브러리입니다.

pandas는 파이썬에서 정형 데이터(테이블 형태의 데이터)를 다루는 데 최적화된 도구입니다. 엑셀 스프레드시트나 SQL 데이터베이스처럼 행과 열로 이루어진 데이터를 효율적으로 처리할 수 있게 해주죠. 이 글에서는 pandas를 처음 접하는 분들이나 기본적인 사용법을 다시 한번 다지고 싶은 분들을 위해, 데이터 정제(Data Cleaning)부터 기초적인 데이터 분석(Basic Data Analysis)까지, 핵심적인 내용들을 실질적인 예시와 함께 쉽고 깊이 있게 다뤄보겠습니다. 저와 함께 데이터 전문가로 성장하는 첫걸음을 내딛어 볼까요?

1. Pandas, 데이터 과학의 심장 (기본 개념 이해하기)

pandas는 "Panel Data"에서 유래된 이름으로, 시리즈(Series)와 데이터프레임(DataFrame)이라는 두 가지 핵심 데이터 구조를 기반으로 합니다.

1.1. Series: 1차원 데이터의 표현

Series는 엑셀의 한 열과 같은 1차원 배열 형태의 데이터입니다. 각 값에 인덱스(index)를 부여할 수 있어 특정 값을 빠르게 찾거나 조작할 수 있습니다.

import pandas as pd

# Series 생성 예시
s = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
print(s)

1.2. DataFrame: 2차원 테이블 데이터의 핵심

DataFramepandas의 핵심이자 가장 많이 사용되는 구조로, 여러 개의 Series가 모여 행과 열을 이루는 2차원 테이블 형태의 데이터입니다. 마치 관계형 데이터베이스의 테이블이나 엑셀 시트와 같다고 생각하시면 됩니다.

# DataFrame 생성 예시
data = {
    '이름': ['김철수', '박영희', '이민지', '최현우'],
    '나이': [25, 30, 22, 28],
    '도시': ['서울', '부산', '제주', '서울']
}
df = pd.DataFrame(data)
print(df)

2. 데이터 불러오기: 분석의 첫 단추

pandas의 가장 기본적인 기능 중 하나는 다양한 형식의 데이터를 불러오는 것입니다. CSV, Excel, SQL 등 대부분의 정형 데이터를 지원합니다.

# CSV 파일 불러오기 예시
# df_sales = pd.read_csv('sales_data.csv')

# Excel 파일 불러오기 예시
# df_excel = pd.read_excel('customer_data.xlsx')

# 예시를 위해 샘플 데이터프레임을 계속 사용하겠습니다.
df_sample = pd.DataFrame({
    '상품명': ['A', 'B', 'C', 'A', 'D', None, 'C', 'B'],
    '가격': [1000, 2000, 1500, 1000, 3000, 2500, 1500, 2000],
    '판매량': [10, 5, 8, 12, 3, 7, 9, None],
    '판매일': ['2023-10-01', '2023-10-01', '2023-10-02', '2023-10-03', '2023-10-03', '2023-10-04', '2023-10-05', '2023-10-05']
})
print("원본 DataFrame:")
print(df_sample)

데이터를 불러온 후에는 df.head(), df.info(), df.describe() 등을 통해 데이터의 전반적인 구조와 통계 정보를 빠르게 파악할 수 있습니다.

3. 지저분한 데이터, 깨끗하게! 데이터 정제 A to Z

실제 데이터는 대부분 지저분합니다. 결측치(missing values), 중복값(duplicates), 잘못된 데이터 타입 등으로 가득하죠. pandas는 이러한 문제를 해결하는 강력한 기능을 제공합니다.

3.1. 결측치(Missing Values) 처리

결측치는 데이터 분석을 방해하는 주요 요소입니다. pandas를 이용해 결측치를 확인하고 처리하는 방법을 알아봅시다.

3.1.1. 결측치 확인

isnull() 또는 isna() 메서드를 사용하면 각 셀이 결측치인지 아닌지를 True/False로 반환합니다. sum()과 함께 사용하면 각 열의 결측치 개수를 쉽게 파악할 수 있습니다.

print("\n각 열의 결측치 개수:")
print(df_sample.isnull().sum())

3.1.2. 결측치 제거 (dropna())

가장 간단한 방법은 결측치가 있는 행이나 열을 제거하는 것입니다. dropna() 메서드를 사용하며, axis 인자로 행(axis=0, 기본값) 또는 열(axis=1)을 지정할 수 있습니다. how='any' (하나라도 결측치면 제거) 또는 how='all' (모든 값이 결측치일 때만 제거)도 중요합니다.

# 결측치가 있는 행 제거
df_cleaned_row = df_sample.dropna(axis=0)
print("\n결측치 행 제거 후:")
print(df_cleaned_row)

# '상품명' 열에 결측치가 있어도 해당 열을 모두 제거하려면 (주의! 데이터 손실 큼)
# df_cleaned_col = df_sample.dropna(axis=1)
# print("\n결측치 열 제거 후 (이 예시에서는 상품명 열만 남을 것):")
# print(df_cleaned_col)

팁: dropna()는 원본 데이터를 변경하지 않고 새로운 DataFrame을 반환합니다. 원본을 변경하려면 inplace=True 인자를 사용하세요.

3.1.3. 결측치 채우기 (fillna())

결측치를 제거하는 것이 항상 좋은 방법은 아닙니다. 데이터 손실이 크거나 특정 값을 대체해야 할 때는 fillna()를 사용합니다. * 특정 값으로 채우기: 0, 평균, 중앙값 등. * 이전/이후 값으로 채우기: method='ffill' (forward fill, 이전 값으로 채움), method='bfill' (backward fill, 이후 값으로 채움).

# '판매량' 열의 결측치를 해당 열의 중앙값으로 채우기
median_sales = df_sample['판매량'].median()
df_filled_median = df_sample.fillna({'판매량': median_sales})
print(f"\n'판매량' 결측치를 중앙값({median_sales})으로 채운 후:")
print(df_filled_median)

# '상품명' 열의 None을 '알 수 없음'으로 채우기
df_filled_str = df_sample.fillna({'상품명': '알 수 없음'})
print("\n'상품명' 결측치를 '알 수 없음'으로 채운 후:")
print(df_filled_str)

3.2. 중복 데이터(Duplicate Data) 처리

동일한 행이 여러 번 나타나는 중복 데이터는 분석 결과를 왜곡할 수 있습니다.

3.2.1. 중복 데이터 확인 (duplicated())

duplicated() 메서드는 각 행이 이전 행과 중복되는지 여부를 True/False로 반환합니다. sum()을 붙여 중복 행의 개수를 확인할 수 있습니다.

print("\n중복 행 확인:")
print(df_sample.duplicated())
print(f"총 중복 행 개수: {df_sample.duplicated().sum()}")

3.2.2. 중복 데이터 제거 (drop_duplicates())

drop_duplicates() 메서드는 중복 행을 제거합니다. keep 인자를 통해 어떤 중복을 남길지 설정할 수 있습니다 ('first', 'last', False).

# 중복 행 제거 (기본값: 첫 번째 값만 남기고 나머지는 제거)
df_no_duplicates = df_sample.drop_duplicates()
print("\n중복 행 제거 후:")
print(df_no_duplicates)

# 특정 열 기준으로 중복 제거 (예: '상품명'과 '가격'이 같으면 중복으로 간주)
df_unique_products = df_sample.drop_duplicates(subset=['상품명', '가격'])
print("\n'상품명'과 '가격' 기준으로 중복 제거 후:")
print(df_unique_products)

3.3. 데이터 타입(Data Type) 변환

데이터가 올바른 타입으로 저장되어 있어야 정확한 연산과 분석이 가능합니다. df.dtypes로 현재 타입을 확인하고, astype()으로 변환합니다.

print("\n원본 데이터 타입:")
print(df_sample.dtypes)

# '판매일' 열을 datetime 타입으로 변환
df_sample['판매일'] = pd.to_datetime(df_sample['판매일'])

# '가격' 열이 만약 문자열로 되어있었다면 숫자로 변환
# df_sample['가격'] = df_sample['가격'].astype(int)

print("\n데이터 타입 변환 후:")
print(df_sample.dtypes)

4. 데이터, 이제 분석하자! Pandas로 하는 기초 분석

깨끗하게 정제된 데이터를 가지고 기본적인 분석을 시작해봅시다.

4.1. 기술 통계(Descriptive Statistics) 확인

describe() 메서드는 숫자형 데이터 열에 대한 기본적인 통계 요약(개수, 평균, 표준편차, 최솟값, 최댓값, 사분위수 등)을 제공합니다.

print("\n기술 통계 요약:")
print(df_sample.describe())

# 개별 통계 값 확인
print(f"\n상품 가격 평균: {df_sample['가격'].mean()}원")
print(f"최대 판매량: {df_sample['판매량'].max()}개")

4.2. 데이터 필터링 및 선택

원하는 조건에 맞는 데이터만 추출하는 것은 분석의 기본입니다. loc (라벨 기반), iloc (정수 위치 기반), 그리고 불리언 인덱싱을 활용할 수 있습니다.

# 가격이 2000원 이상인 상품만 선택
df_high_price = df_sample[df_sample['가격'] >= 2000]
print("\n가격이 2000원 이상인 상품:")
print(df_high_price)

# 특정 '상품명'만 선택
df_product_a = df_sample[df_sample['상품명'] == 'A']
print("\n상품 A의 판매 내역:")
print(df_product_a)

# 여러 조건 필터링 (예: 가격이 1500원 이상이고 판매량이 10개 미만)
df_filtered = df_sample[(df_sample['가격'] >= 1500) & (df_sample['판매량'] < 10)]
print("\n가격 1500원 이상 & 판매량 10개 미만 상품:")
print(df_filtered)

4.3. 데이터 그룹화 (groupby())

groupby()는 특정 열의 값들을 기준으로 데이터를 그룹으로 묶고, 각 그룹에 대한 집계 함수(평균, 합계, 개수 등)를 적용할 때 사용됩니다. 이는 데이터에서 패턴이나 인사이트를 발견하는 데 매우 유용합니다.

# 상품명별 평균 가격 및 총 판매량 계산
df_grouped = df_sample.groupby('상품명').agg(
    평균_가격=('가격', 'mean'),
    총_판매량=('판매량', 'sum')
)
print("\n상품명별 평균 가격 및 총 판매량:")
print(df_grouped)

# 판매일별 총 판매량 계산
df_daily_sales = df_sample.groupby('판매일')['판매량'].sum().reset_index()
print("\n판매일별 총 판매량:")
print(df_daily_sales)

4.4. 데이터 정렬 (sort_values())

데이터를 특정 열의 값을 기준으로 오름차순 또는 내림차순으로 정렬하여 추세나 순위를 파악할 수 있습니다.

# 가격을 기준으로 내림차순 정렬
df_sorted_price = df_sample.sort_values(by='가격', ascending=False)
print("\n가격을 기준으로 내림차순 정렬:")
print(df_sorted_price)

# 상품명 오름차순, 판매량 내림차순으로 다중 정렬
df_sorted_multi = df_sample.sort_values(by=['상품명', '판매량'], ascending=[True, False])
print("\n상품명 오름차순, 판매량 내림차순 다중 정렬:")
print(df_sorted_multi)

5. Pandas, 실전 활용을 위한 팁

  • 메서드 체이닝(Method Chaining): 여러 pandas 작업을 한 줄로 연결하여 코드를 더 간결하고 읽기 쉽게 만들 수 있습니다. python # 예시: 결측치 채우고, 중복 제거 후, 특정 조건으로 필터링 df_result = df_sample.fillna({'판매량': 0}).drop_duplicates().loc[lambda x: x['가격'] > 1000] # print(df_result)
  • 원본 데이터 보존: 중요한 분석 단계에서는 df = df.copy()를 사용하여 원본 데이터를 복사한 후 작업하는 습관을 들이는 것이 좋습니다.
  • 시각화 연동: pandas DataFrame은 matplotlibseaborn 같은 시각화 라이브러리와 쉽게 연동되어 데이터를 그래프로 표현하는 데 용이합니다.

마치며: 데이터와 소통하는 즐거움, Pandas와 함께!

지금까지 파이썬 pandas 라이브러리를 활용한 데이터 정제 및 기초 분석의 핵심적인 내용들을 살펴보았습니다. 데이터를 불러와 결측치와 중복값을 처리하고, 데이터 타입을 변환하며, 나아가 기술 통계와 필터링, 그룹화, 정렬을 통해 데이터 속 숨겨진 의미를 찾아내는 과정은 데이터 분석의 기본이자 가장 중요한 단계입니다.

pandas는 단순히 데이터를 조작하는 도구가 아니라, 데이터를 이해하고, 데이터를 통해 질문하고, 데이터로부터 통찰을 얻는 '데이터와 소통하는 언어'라고 생각합니다. 오늘 배운 내용을 바탕으로 다양한 실제 데이터를 직접 다루면서 자신만의 분석 노하우를 쌓아가시길 바랍니다.

데이터의 세계는 무궁무진하며, pandas와 함께라면 여러분도 훌륭한 데이터 탐험가가 될 수 있을 겁니다! 궁금한 점이 있다면 언제든지 댓글로 질문해 주세요. 다음번에는 더 흥미로운 IT 및 테크 지식으로 찾아오겠습니다.

감사합니다. 루카(Luka) 드림.