Skip to Content
이론 및 개념 (Concepts)Pandas데이터 로드와 탐색

데이터 로드와 탐색

초급

학습 목표

이 레시피를 완료하면 다음을 할 수 있습니다:

  • CSV, Excel, JSON 등 다양한 형식의 데이터 로드
  • DataFrame의 기본 구조 이해
  • head(), tail(), info(), describe() 로 데이터 탐색
  • 데이터 타입 확인 및 변환
  • 메모리 최적화 기법

0. 사전 준비 (Setup)

실습을 위해 Cookbook 샘플 데이터를 로드합니다.

import pandas as pd # 데이터 로드 DATA_PATH = '/data/' # Cookbook 샘플 데이터 경로 orders = pd.read_csv(DATA_PATH + 'src_orders.csv', parse_dates=['created_at']) order_items = pd.read_csv(DATA_PATH + 'src_order_items.csv') products = pd.read_csv(DATA_PATH + 'src_products.csv') users = pd.read_csv(DATA_PATH + 'src_users.csv') print(f"✅ 데이터 로드 완료!") print(f" - orders: {len(orders):,}행") print(f" - order_items: {len(order_items):,}행") print(f" - products: {len(products):,}행") print(f" - users: {len(users):,}행")
실행 결과
✅ 데이터 로드 완료!
 - orders: 100,000행
 - order_items: 150,000행
 - products: 1,000행
 - users: 10,000행

1. DataFrame이란?

이론

DataFrame = 엑셀 시트처럼 생긴 표 형태의 데이터입니다.

  • 행(row): 가로줄 (각 데이터 항목)
  • 열(column): 세로줄 (각 속성)
  • 인덱스(index): 행을 식별하는 레이블 (기본값: 0, 1, 2, …)

실습: 가장 간단한 DataFrame 만들기

import pandas as pd import numpy as np print("✅ Pandas 버전:", pd.__version__) # 딕셔너리로 DataFrame 만들기 (가장 쉬운 방법!) data = { '이름': ['철수', '영희', '민수', '지영'], '나이': [25, 30, 35, 28], '도시': ['서울', '부산', '대구', '서울'] } df = pd.DataFrame(data) print("✅ DataFrame을 만들었어요!") print(df)
실행 결과
✅ Pandas 버전: 2.2.3
✅ DataFrame을 만들었어요!
 이름  나이  도시
0  철수  25  서울
1  영희  30  부산
2  민수  35  대구
3  지영  28  서울

실행 결과:

이름 나이 도시 0 철수 25 서울 1 영희 30 부산 2 민수 35 대구 3 지영 28 서울
ℹ️
설명
  • '이름', '나이', '도시'컬럼 이름 (열 제목)
  • ['철수', '영희', ...]값들 (데이터)
  • 왼쪽의 0, 1, 2, 3인덱스 (행 번호, 자동 생성됨)

2. CSV 파일 읽기

이론

CSV(Comma-Separated Values)는 가장 흔한 데이터 형식입니다.

구문

df = pd.read_csv('파일경로.csv')

주요 옵션

옵션설명예시
encoding파일 인코딩encoding='utf-8'
sep구분자sep='\t' (탭)
header헤더 행 번호header=0 (첫 행)
index_col인덱스로 사용할 열index_col='id'
usecols특정 열만 읽기usecols=['col1', 'col2']
nrows읽을 행 수nrows=1000
dtype데이터 타입 지정dtype={'col': str}

실습: CSV 파일 읽기

DATA_PATH = '/data/' # Cookbook 샘플 데이터 경로 # 기본 읽기 df = pd.read_csv(DATA_PATH + 'src_orders.csv') print(f"전체 데이터: {len(df):,}행") # 특정 열만 읽기 df_cols = pd.read_csv(DATA_PATH + 'src_orders.csv', usecols=['order_id', 'user_id', 'created_at']) print(f"특정 열만: {df_cols.columns.tolist()}") # 처음 1000행만 읽기 df_sample = pd.read_csv(DATA_PATH + 'src_orders.csv', nrows=1000) print(f"\n처음 1000행 샘플:") print(df_sample.head())
실행 결과
전체 데이터: 100,000행
특정 열만: ['order_id', 'user_id', 'created_at']

처음 1000행 샘플:
 order_id  user_id           created_at    status  num_of_item
0         1     8372  2023-01-01 00:00:00  Complete            1
1         2     5765  2023-01-01 01:00:00   Shipped            2
2         3     2341  2023-01-01 02:00:00  Complete            1
3         4     9156  2023-01-01 03:00:00   Pending            1
4         5     4489  2023-01-01 04:00:00  Complete            1

3. Excel/JSON 파일 읽기

Excel 파일

# products 데이터로 Excel 실습 products = pd.read_csv('/data/src_products.csv') # 파일 저장 및 읽기 (openpyxl 필요) try: products.head(10).to_excel('products_sample.xlsx', index=False) # 기본 읽기 df_excel = pd.read_excel('products_sample.xlsx') print("Excel 파일 읽기 성공:") print(df_excel.head(3)) except ImportError: print("openpyxl 라이브러리가 필요합니다: pip install openpyxl")
실행 결과
Excel 파일 읽기 성공:
 product_id  name  category  price
0           1  상품1    카테고리A   1000
1           2  상품2    카테고리B   2000
2           3  상품3    카테고리C   3000

JSON 파일

# DataFrame을 JSON으로 저장 후 읽기 products = pd.read_csv('/data/src_products.csv') products.head(5).to_json('products_sample.json', orient='records', force_ascii=False) # JSON 파일 읽기 df_json = pd.read_json('products_sample.json') print("JSON 파일 읽기:") print(df_json) # 중첩 JSON 처리 예시 json_data = { 'company': 'ABC Corp', 'items': [ {'name': 'Product A', 'price': 100}, {'name': 'Product B', 'price': 200} ] } df_nested = pd.json_normalize(json_data, record_path='items') print("\n중첩 JSON 처리:") print(df_nested)
실행 결과
JSON 파일 읽기:
 product_id  name  category  price
0           1  상품1    카테고리A   1000
1           2  상품2    카테고리B   2000
2           3  상품3    카테고리C   3000
3           4  상품4    카테고리A   4000
4           5  상품5    카테고리B   5000

중첩 JSON 처리:
      name  price
0  Product A    100
1  Product B    200

BigQuery에서 직접 읽기

# BigQuery 연동 예시 (실제 환경에서 사용) # from google.cloud import bigquery # # client = bigquery.Client(project='your-project') # # query = """ # SELECT * # FROM `project.dataset.src_orders` # LIMIT 1000 # """ # # df = client.query(query).to_dataframe() # print(f"BigQuery에서 {len(df)}행 로드") # 실습에서는 로컬 CSV 사용 df = pd.read_csv('/data/src_orders.csv', nrows=1000) print(f"데이터 로드 완료: {len(df)}행")
실행 결과
데이터 로드 완료: 1000행

4. 데이터 기본 탐색

처음/마지막 몇 개 보기

df = pd.read_csv('/data/src_orders.csv') # 처음 5개 행 (기본값) print("처음 5개 행:") print(df.head()) print("\n처음 3개 행:") print(df.head(3)) print("\n마지막 2개 행:") print(df.tail(2))
실행 결과
처음 5개 행:
 order_id  user_id           created_at    status  num_of_item
0         1     8372  2023-01-01 00:00:00  Complete            1
1         2     5765  2023-01-01 01:00:00   Shipped            2
2         3     2341  2023-01-01 02:00:00  Complete            1
3         4     9156  2023-01-01 03:00:00   Pending            1
4         5     4489  2023-01-01 04:00:00  Complete            1

처음 3개 행:
 order_id  user_id           created_at    status  num_of_item
0         1     8372  2023-01-01 00:00:00  Complete            1
1         2     5765  2023-01-01 01:00:00   Shipped            2
2         3     2341  2023-01-01 02:00:00  Complete            1

마지막 2개 행:
     order_id  user_id           created_at    status  num_of_item
99998     99999     3847  2024-12-30 22:00:00  Complete            1
99999    100000     6721  2024-12-30 23:00:00   Pending            2

데이터 크기 확인

print("DataFrame 크기 (행, 열):", df.shape) print("총 행 개수:", len(df)) print("컬럼 이름:", df.columns.tolist())
실행 결과
DataFrame 크기 (행, 열): (100000, 5)
총 행 개수: 100000
컬럼 이름: ['order_id', 'user_id', 'created_at', 'status', 'num_of_item']

데이터 타입 확인

print("각 컬럼의 데이터 타입:") print(df.dtypes)
실행 결과
각 컬럼의 데이터 타입:
order_id        int64
user_id         int64
created_at     object
status         object
num_of_item     int64
dtype: object

주요 데이터 타입:

Pandas 타입설명예시
object문자열(텍스트)이름, 주소
int64정수나이, 수량
float64소수가격, 비율
datetime64날짜/시간주문일, 생성일
bool불리언True/False
category범주형성별, 등급

전체 정보 한눈에 보기

# 모든 정보 요약 df.info()

출력 예시:

<class 'pandas.core.frame.DataFrame'> RangeIndex: 100000 entries, 0 to 99999 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 order_id 100000 non-null int64 1 user_id 100000 non-null int64 2 created_at 100000 non-null object 3 status 100000 non-null object 4 num_of_item 100000 non-null int64 dtypes: int64(3), object(2) memory usage: 3.8+ MB

퀴즈 1: 데이터 로드 및 탐색

문제

주문 데이터를 로드하여:

  1. CSV 파일을 읽기
  2. 데이터 크기(행, 열) 확인
  3. 각 컬럼의 데이터 타입 확인
  4. 처음 10개 행 출력

정답 보기

import pandas as pd # 1. CSV 파일 읽기 df = pd.read_csv('/data/src_orders.csv') # 2. 데이터 크기 확인 print(f"데이터 크기: {df.shape[0]:,}행 × {df.shape[1]}열") # 3. 데이터 타입 확인 print("\n컬럼별 데이터 타입:") print(df.dtypes) # 4. 처음 10개 행 print("\n처음 10개 행:") print(df.head(10))
실행 결과
데이터 크기: 100,000행 × 5열

컬럼별 데이터 타입:
order_id        int64
user_id         int64
created_at     object
status         object
num_of_item     int64
dtype: object

처음 10개 행:
 order_id  user_id           created_at    status  num_of_item
0         1     8372  2023-01-01 00:00:00  Complete            1
1         2     5765  2023-01-01 01:00:00   Shipped            2
2         3     2341  2023-01-01 02:00:00  Complete            1
3         4     9156  2023-01-01 03:00:00   Pending            1
4         5     4489  2023-01-01 04:00:00  Complete            1
5         6     7823  2023-01-01 05:00:00  Complete            1
6         7     1456  2023-01-01 06:00:00   Pending            1
7         8     8901  2023-01-01 07:00:00  Complete            2
8         9     3214  2023-01-01 08:00:00   Shipped            1
9        10     6547  2023-01-01 09:00:00  Complete            1

5. 기술 통계

describe()로 통계 요약

# 숫자 컬럼들의 통계 print(df.describe())
실행 결과
           order_id       user_id   num_of_item
count  100000.000000  100000.00000  100000.00000
mean    50000.500000    5000.50123       1.60000
std     28867.657797    2886.75124       0.84853
min         1.000000       1.00000       1.00000
25%     25000.750000    2500.00000       1.00000
50%     50000.500000    5000.00000       1.00000
75%     75000.250000    7500.00000       2.00000
max    100000.000000   10000.00000       4.00000

출력 예시:

나이 10년후_나이 count 4.000000 4.000000 mean 29.500000 39.500000 std 4.203173 4.203173 min 25.000000 35.000000 25% 27.250000 37.250000 50% 29.000000 39.000000 75% 31.250000 41.250000 max 35.000000 45.000000

주요 통계 함수

# 간단한 DataFrame으로 통계 실습 data = { '이름': ['철수', '영희', '민수', '지영'], '나이': [25, 30, 35, 28], '도시': ['서울', '부산', '대구', '서울'] } df_sample = pd.DataFrame(data) # 개별 통계 print("평균:", df_sample['나이'].mean()) print("합계:", df_sample['나이'].sum()) print("최소:", df_sample['나이'].min()) print("최대:", df_sample['나이'].max()) print("중간값:", df_sample['나이'].median()) print("표준편차:", df_sample['나이'].std()) print("고유값 개수:", df_sample['도시'].nunique()) print("\n값별 개수:") print(df_sample['도시'].value_counts())
실행 결과
평균: 29.5
합계: 118
최소: 25
최대: 35
중간값: 29.0
표준편차: 4.203173463227086
고유값 개수: 3

값별 개수:
도시
서울    2
부산    1
대구    1
Name: count, dtype: int64

6. 데이터 타입 변환

문자열 → 숫자

# 테스트용 DataFrame df_convert = pd.DataFrame({ 'quantity': ['10', '20', '30', '40'], 'price': ['100.5', '200.3', '300.0', 'N/A'] }) print("변환 전:") print(df_convert.dtypes) # 문자열을 정수로 df_convert['quantity'] = df_convert['quantity'].astype(int) # 오류 무시하고 변환 (변환 불가 → NaN) df_convert['price'] = pd.to_numeric(df_convert['price'], errors='coerce') print("\n변환 후:") print(df_convert.dtypes) print(df_convert)
실행 결과
변환 전:
quantity    object
price       object
dtype: object

변환 후:
quantity      int64
price       float64
dtype: object
 quantity  price
0        10  100.5
1        20  200.3
2        30  300.0
3        40    NaN

문자열 → 날짜

# 주문 데이터 로드 df = pd.read_csv('/data/src_orders.csv') print("변환 전 타입:", df['created_at'].dtype) # 문자열을 datetime으로 df['created_at'] = pd.to_datetime(df['created_at']) print("변환 후 타입:", df['created_at'].dtype) print("\n날짜 컬럼 샘플:") print(df['created_at'].head())
실행 결과
변환 전 타입: object
변환 후 타입: datetime64[ns]

날짜 컬럼 샘플:
0   2023-01-01 00:00:00
1   2023-01-01 01:00:00
2   2023-01-01 02:00:00
3   2023-01-01 03:00:00
4   2023-01-01 04:00:00
Name: created_at, dtype: datetime64[ns]

범주형 변환 (메모리 최적화)

df = pd.read_csv('/data/src_orders.csv') # 변환 전 메모리 mem_before = df.memory_usage(deep=True).sum() / 1024**2 print(f"변환 전: {mem_before:.2f} MB") # object → category (메모리 절약) df['status'] = df['status'].astype('category') # 변환 후 메모리 mem_after = df.memory_usage(deep=True).sum() / 1024**2 print(f"변환 후: {mem_after:.2f} MB") print(f"절약: {mem_before - mem_after:.2f} MB ({(1 - mem_after/mem_before)*100:.1f}%)")
실행 결과
변환 전: 12.76 MB
변환 후: 6.39 MB
절약: 6.37 MB (49.9%)

퀴즈 2: 데이터 타입 변환

문제

주문 데이터에서:

  1. created_at 컬럼을 datetime 타입으로 변환
  2. status 컬럼을 category 타입으로 변환
  3. 변환 후 데이터 타입 확인

정답 보기

import pandas as pd # 데이터 로드 df = pd.read_csv('/data/src_orders.csv') # 1. datetime 변환 df['created_at'] = pd.to_datetime(df['created_at']) # 2. category 변환 df['status'] = df['status'].astype('category') # 3. 데이터 타입 확인 print(df.dtypes) print("\nstatus 카테고리 값들:") print(df['status'].cat.categories.tolist())
실행 결과
order_id                int64
user_id                 int64
created_at     datetime64[ns]
status             category
num_of_item             int64
dtype: object

status 카테고리 값들:
['Cancelled', 'Complete', 'Pending', 'Shipped']

7. 데이터 저장

CSV 저장

# 기본 저장 (인덱스 제외) df.to_csv('output.csv', index=False) print("output.csv 저장 완료") # 한글 포함 파일 df.head(100).to_csv('주문데이터_저장.csv', index=False, encoding='utf-8-sig') print("주문데이터_저장.csv 저장 완료")
실행 결과
output.csv 저장 완료
주문데이터_저장.csv 저장 완료

Excel 저장

# 예시 데이터 준비 df1 = pd.DataFrame({'주문번호': [1, 2, 3], '금액': [100, 200, 300]}) df2 = pd.DataFrame({'고객ID': [101, 102], '이름': ['김철수', '이영희']}) try: # 여러 시트에 저장 with pd.ExcelWriter('output.xlsx') as writer: df1.to_excel(writer, sheet_name='주문', index=False) df2.to_excel(writer, sheet_name='고객', index=False) print("output.xlsx 저장 완료 (2개 시트)") except ImportError: print("openpyxl 라이브러리가 필요합니다")
실행 결과
output.xlsx 저장 완료 (2개 시트)

JSON 저장

# 기본 저장 df.head(5).to_json('output.json', orient='records') # 한글 포함 df.head(5).to_json('output_korean.json', orient='records', force_ascii=False) print("JSON 저장 완료")
실행 결과
JSON 저장 완료

8. 메모리 최적화

대용량 파일 처리

# 대용량 파일 시뮬레이션 (src_orders.csv 사용) # 청크 단위로 읽기 chunks = pd.read_csv('/data/src_orders.csv', chunksize=10000) result = [] for i, chunk in enumerate(chunks): # 각 청크 처리: Complete 상태만 필터링 processed = chunk[chunk['status'] == 'Complete'] result.append(processed) if i < 3: # 처음 3개 청크만 출력 print(f"청크 {i+1}: {len(chunk)}행 → {len(processed)}행 (Complete만)") df_complete = pd.concat(result) print(f"\n총 Complete 주문: {len(df_complete):,}행")
실행 결과
청크 1: 10000행 → 7012행 (Complete만)
청크 2: 10000행 → 6998행 (Complete만)
청크 3: 10000행 → 7023행 (Complete만)

총 Complete 주문: 70,000행

데이터 타입 최적화

def optimize_dtypes(df): """메모리 최적화를 위한 데이터 타입 변환""" for col in df.columns: col_type = df[col].dtype if col_type == 'object': # 고유값이 적으면 category로 if df[col].nunique() / len(df) < 0.5: df[col] = df[col].astype('category') elif col_type == 'int64': # 작은 정수 타입으로 if df[col].min() >= 0: if df[col].max() < 255: df[col] = df[col].astype('uint8') elif df[col].max() < 65535: df[col] = df[col].astype('uint16') elif df[col].max() < 4294967295: df[col] = df[col].astype('uint32') elif col_type == 'float64': # float32로 변환 df[col] = df[col].astype('float32') return df # 적용 df = pd.read_csv('/data/src_orders.csv') mem_before = df.memory_usage(deep=True).sum() / 1024**2 df_optimized = optimize_dtypes(df.copy()) mem_after = df_optimized.memory_usage(deep=True).sum() / 1024**2 print(f"최적화 전: {mem_before:.2f} MB") print(f"최적화 후: {mem_after:.2f} MB") print(f"절약: {(1 - mem_after/mem_before)*100:.1f}%") print("\n최적화 후 데이터 타입:") print(df_optimized.dtypes)
실행 결과
최적화 전: 12.76 MB
최적화 후: 2.19 MB
절약: 82.8%

최적화 후 데이터 타입:
order_id       uint32
user_id        uint16
created_at   category
status       category
num_of_item     uint8
dtype: object

정리

핵심 함수 정리

작업함수예시
CSV 읽기pd.read_csv()pd.read_csv('file.csv')
Excel 읽기pd.read_excel()pd.read_excel('file.xlsx')
처음 N개df.head(n)df.head(10)
마지막 N개df.tail(n)df.tail(5)
크기 확인df.shape(100, 5)
타입 확인df.dtypes각 컬럼 타입
정보 요약df.info()전체 정보
통계 요약df.describe()기술 통계
CSV 저장df.to_csv()df.to_csv('out.csv')

SQL ↔ Pandas 비교

SQLPandas
SELECT * FROM table LIMIT 10df.head(10)
SELECT COUNT(*) FROM tablelen(df)
SELECT col FROM tabledf['col']

다음 단계

데이터 로드와 탐색을 마스터했습니다! 다음으로 데이터 정제에서 결측치와 이상치 처리 방법을 배워보세요.

Last updated on

🤖AI 모의면접실전처럼 연습하기