Application/Python

[Python] 파이썬 pandas 입문 — 엑셀처럼 데이터 다루기

devsalix 2026. 6. 4. 08:51
728x90

파이썬 pandas 입문 — 엑셀처럼 데이터 다루기

지난 글에서 requests로 API를 호출해서 데이터를 받아봤잖아요. 그런데 받아놓고 나니까 좀 답답하셨을 거예요. 딕셔너리가 리스트 안에 잔뜩 들어있는데, 이걸 보기 좋게 정리하려고 하면 for문이 자꾸 길어지거든요.

저도 처음에 이 부분에서 막혔어요. "엑셀에 붙여넣으면 한눈에 보일 텐데" 싶었거든요.

그 생각을 그대로 코드로 옮긴 게 바로 pandas예요. 엑셀 같은 걸 코드로 다룬다고 생각하시면 됩니다.


pandas가 뭐길래 — python 데이터분석의 표준

pandas는 표 형태의 데이터를 다루는 라이브러리예요. 행과 열이 있는 표, 딱 엑셀 시트 한 장을 떠올리시면 돼요.

데이터분석, 업무 자동화, 머신러닝 전처리까지 거의 모든 곳에서 사실상 표준으로 쓰입니다. 깊게 들어가면 끝이 없는데, 솔직히 기본기만 익혀도 일상에서 다루는 데이터 작업은 거의 다 해결돼요.

설치는 한 줄입니다.

pip install pandas

 

그리고 거의 모든 사람이 이렇게 줄여서 써요. 관례라 그대로 따라가시면 됩니다.

import pandas as pd  # pd로 줄여서 쓰는 게 관례

 


DataFrame과 Series, 이 둘만 구분하시면 됩니다

핵심 개념은 딱 두 개예요. DataFrame은 표 전체, Series는 그 표의 한 컬럼(열)이에요. 표를 통째로 다루다가 한 줄만 뽑으면 Series가 되는 거죠. 99% 작업은 DataFrame 위에서 일어납니다.

학생 점수 표를 직접 만들어볼게요.

import pandas as pd

# 딕셔너리로 컬럼별 데이터 정의
data = {
    '이름': ['민수', '지영', '철수', '영희'],
    '국어': [90, 85, 70, 95],
    '수학': [80, 95, 60, 100]
}

df = pd.DataFrame(data)  # 딕셔너리를 표로 변환
print(df)

 

실행하면 이렇게 나와요.

   이름  국어   수학
0  민수  90   80
1  지영  85   95
2  철수  70   60
3  영희  95  100

 

오, 진짜 표가 나오죠. 왼쪽의 0, 1, 2, 3이 자동으로 붙은 인덱스인데, 엑셀의 행 번호라고 생각하시면 됩니다.


데이터 둘러보기

새 데이터를 받았을 때 가장 먼저 하는 건 "이게 뭔지 슥 훑어보기"예요. 이때 자주 쓰는 네 가지가 있습니다.

print(df.head())      # 위에서 5행 미리보기
print(df.info())      # 컬럼명, 타입, 결측치 개수
print(df.describe())  # 숫자 컬럼의 평균, 최댓값 같은 통계
print(df.shape)       # (행 수, 열 수)

 

describe() 결과에 mean(평균), std(표준편차), min(최솟값), max(최댓값) 같은 게 한 번에 나와요. 데이터 처음 받았을 때 이거 하나면 분위기 파악이 됩니다.

 

참고로 스크립트로 돌릴 때는 print()로 감싸야 보여요. Jupyter 노트북에서는 그냥 df.head()만 써도 출력됩니다.

파이썬 데이터 처리 기본 — 선택, 필터, 정렬

열과 행 선택

print(df['국어'])           # Series 한 줄로 뽑기
print(df[['이름', '국어']])  # 여러 컬럼 → DataFrame

 

대괄호 한 번이면 Series, 두 번이면 DataFrame이에요. 처음에 진짜 헷갈리는 포인트인데, 두 번 쓴 건 "컬럼 이름들의 리스트"를 넘긴다고 생각하시면 됩니다.

행을 고를 때는 lociloc가 있어요.

print(df.iloc[0])  # 위치 기준: 첫 번째 행
print(df.loc[0])   # 라벨 기준: 인덱스 이름이 0인 행

 

지금은 결과가 같지만, 인덱스에 이름을 줘버리면 달라져요. iloc는 "줄 세워놓고 몇 번째"고, loc는 "이름표로 찾기"예요. 이 정도만 기억해두셔도 충분합니다.


조건으로 필터링

엑셀 자동 필터랑 똑같은 발상이에요.

# 국어 80점 이상만
high = df[df['국어'] >= 80]
print(high)

# 두 조건 동시에 (괄호 + & 주의!)
both = df[(df['국어'] >= 80) & (df['수학'] >= 80)]
print(both)

 

여기서 한 가지 함정. 두 조건을 묶을 때 and/or를 쓰면 에러가 나요. &(그리고), |(또는)를 써야 하고, 각 조건은 반드시 괄호로 감싸야 합니다. 괄호 빼먹으면 연산 우선순위가 꼬여서 엉뚱한 에러가 떠요. 저도 처음에 이거 모르고 한참 헤맸어요.


정렬과 새 컬럼

# 국어 점수 내림차순
print(df.sort_values('국어', ascending=False))

# 평균 컬럼 추가 — 엑셀에서 수식 넣는 거랑 같음
df['평균'] = (df['국어'] + df['수학']) / 2
print(df)

CSV 다루기와 한글 인코딩

df.to_csv('성적.csv', index=False, encoding='utf-8-sig')  # 저장
df_loaded = pd.read_csv('성적.csv', encoding='utf-8-sig')   # 불러오기

 

index=False는 왼쪽 인덱스(0, 1, 2...)를 파일에 안 넣겠다는 뜻이에요. 안 넣으면 매번 이상한 컬럼이 하나 생깁니다.

그리고 한글 인코딩은 진짜 자주 만나는 함정이에요. encoding='utf-8-sig'로 저장하면 윈도우 엑셀에서 열어도 안 깨져요. 반대로 한국 공공기관에서 받은 CSV는 cp949인 경우가 많은데, 그땐 이렇게 쓰시면 됩니다.

df = pd.read_csv('공공데이터.csv', encoding='cp949')

 

한글이 �로 깨져 나오면 99% 인코딩 문제니까 utf-8-sigcp949 이 두 개를 번갈아 시도해보세요.


groupby — 엑셀 피벗 테이블의 그 기능

df2 = pd.DataFrame({
    '반': ['A', 'A', 'B', 'B'],
    '점수': [80, 90, 70, 100]
})

# 반별 평균 점수
print(df2.groupby('반')['점수'].mean())

 

결과는 이렇게 나옵니다.

반
A    85.0
B    85.0
Name: 점수, dtype: float64

 

엑셀 피벗 테이블 만들어본 적 있으시면 바로 감이 오실 거예요. "어떤 기준으로 묶어서, 어떤 값을, 어떻게 집계할지" 한 줄로 끝나요.


API 응답을 DataFrame으로

지난 글에서 requests로 받은 데이터 기억나시죠? 출력하면 줄줄이 늘어졌잖아요. 그걸 한 줄로 표로 만들 수 있어요.

import requests
import pandas as pd

data = requests.get('https://jsonplaceholder.typicode.com/users').json()
df = pd.DataFrame(data)  # 딕셔너리 리스트 → 표
print(df[['id', 'name', 'email']].head())

 

처음 이거 봤을 때 좀 감탄했어요. for문 길게 돌리던 게 두 줄로 끝나니까요.


실습 과제

직접 해보셔야 머리에 박힙니다.

  1. 학생 5명의 이름, 국어, 수학, 영어 점수를 딕셔너리로 만들기
  2. DataFrame으로 변환하고 평균 컬럼 추가
  3. 평균 80점 이상인 학생만 필터링
  4. CSV로 저장(utf-8-sig)
  5. 다시 읽어서 평균 내림차순 정렬해 출력

막히시면 위 코드들 조합하시면 다 풀려요.


슬슬 코드가 길어지면

pandas가 처음엔 낯설어도 한번 익히면 데이터 다루는 게 진짜 빨라지거든요. 그런데 이쯤 되면 슬슬 느끼실 거예요. 한 파일에 import도 한가득, 함수도 한가득, 데이터 파일까지 같이 두고 짜면 금방 엉킵니다.

다음 글에서는 지금까지 배운 것들을 진짜 프로젝트답게 폴더로 나누는 법을 이야기해볼게요. 실무에서 파이썬 코드를 어떻게 정리하는지, 그 구조부터 한번 잡아봅시다.


 


제 글이 도움이 되셨다면 댓글 & 공감 부탁드려요 😀

 

 
728x90