| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
- 프로덕트분석
- retention
- amplitude
- 데이터전처리
- 로그
- 퍼널분석
- 코드잇스프린트
- 파이썬시각화
- 결측값
- SQL
- 데이터분석가
- 데이터분석공부
- 탐색적데이터분석
- 지표
- 데이터분석프로젝트
- 파이썬라이브러리
- 태블로
- 파이썬
- aarrr
- 로그설계
- 데이터분석가공부
- 지표설계
- 스프린트미션
- 데이터분석
- seaborn
- 프로덕트데이터
- 코드잇
- Tableau
- 부트캠프
- 데이터분석가부트캠프
- Today
- Total
StuDyata.zip
Python으로 데이터 다루기 | numpy, pandas, 전처리, 데이터 합치기, 집계 분석 내용 전체 정리 본문
Python으로 데이터 다루기 | numpy, pandas, 전처리, 데이터 합치기, 집계 분석 내용 전체 정리
자유를원해 2026. 3. 21. 00:36이 글은 코드잇 스프린트 데이터 분석가 과정 학습 기록입니다.
수업 내용과 느낀 점을 매일 정리하며 데이터 분석 공부 과정을 기록하고 있습니다.
🖥️데이터 분석을 위한 Python으로 데이터 다루기 총정리
이번 주부터는 부트캠프 Part 1에서 정말 중요하다고 하신 ‘Python으로 데이터 다루기’ 내용을 본격적으로 배우기 시작했다. 강사님 말씀으로는 화, 수, 목에 배우는 이 내용이 이번 파트 전체를 통틀어 가장 중요하다고 하셨는데, 그 이유는 이후 실습과 미션, 데이터 전처리, 탐색, 분석 과정에서 이 개념들이 계속 반복해서 등장하기 때문이라고..!
본격적인 실습에 들어가기 전에 먼저 데이터 분석 프로세스를 다시 리마인드 했고, 이번 이론 수업은 특히 데이터 전처리(Data Preprocessing) 와 탐색적 데이터 분석(EDA, Exploratory Data Analysis)을 중심으로 보게 된다고 안내해주셨다. 실제 데이터 분석에서는 모델링보다도 전처리에 훨씬 더 많은 시간이 들어가며, 강의에서도 이 부분을 특히 강조하셨다.
💾라이브러리란 무엇인가
이제 파이썬에서 라이브러리를 사용하기 시작했다. 라이브러리는 말 그대로 ‘도서관’이라는 뜻인데, 강사님께서 이걸 도서관의 여러 섹션에 비유해서 설명해주셨다. 예를 들어 도서관에 자기계발, 외국어, 소설, 자격증 코너가 따로 있듯이, 파이썬에서도 목적에 따라 알맞은 기능들이 모여 있는 라이브러리를 가져다 쓰는 것이다. 즉, 어떤 목적의 작업을 하려면 그 목적에 맞는 함수들이 들어 있는 라이브러리를 불러와 사용하게 된다.
간단히 소개된 주요 라이브러리는 다음과 같았다. (이번 이론 수업은 numpy와 pandas만 다룬다!)
- pandas
데이터프레임 형태로 데이터를 불러오고, 정리하고, 가공하고, 분석할 때 가장 많이 사용하는 라이브러리다. 강사님께서는 Part 1에서 pandas만 제대로 익혀도 성공이라고 하실 정도로 중요하게 말씀하셨다. 전처리 작업의 비중이 매우 크고, 실무에서도 정말 자주 쓰인다. - numpy
Numerical Python의 줄임말로, 다차원 배열과 행렬 연산, 각종 수치 계산을 수행할 때 사용하는 라이브러리다. - matplotlib
가장 기본적이고 강력한 시각화 라이브러리다. 세부적인 그래프 커스터마이징을 할 때 특히 유용하다. - seaborn
통계적 시각화에 특화되어 있다. 비교적 적은 코드로 예쁜 그래프를 그릴 수 있지만, 커스터마이징 면에서는 제한이 있다. - plotly
인터랙티브한 시각화를 지원한다. 줌, 호버, 클릭 등 상호작용이 가능한 그래프를 만들 수 있다.
🧮numpy 라이브러리
실습이 시작되고, 첫 번째로 배운 라이브러리는 numpy이다.
📍numpy란
numpy는 대규모 수치 연산과 배열 계산을 위한 라이브러리이다. numerical python, 이름 그대로 복잡한 수학 계산, 통계 계산, 배열 기반 연산에 특히 적합하다.
📍numpy의 특징
- 내부적으로 C 언어 기반으로 구현되어 있어 연산 속도가 빠르다.
- pandas, scipy, scikit-learn, tensorflow 등 다른 많은 라이브러리들이 numpy를 기반으로 동작한다.
📍numpy 불러오기
라이브러리는 import를 사용해서 불러온다.
import numpy
그런데 이렇게 하면 매번 numpy를 길게 입력해야 하므로 별칭을 붙여서 사용한다.
import numpy as np
이때 np는 거의 관례처럼 굳어진 표준 별칭이다. 다른 라이브러리들도 자주 쓰는 별칭이 있다.
- numpy → np
- pandas → pd
- matplotlib.pyplot → plt
- seaborn → sns
- plotly.express → px
1️⃣array
numpy의 핵심은 배열(array) 이다. 파이썬의 기본 리스트와 달리 numpy의 배열은 수치 계산에 최적화되어 있다.
📍array 생성하기
np.array()
이 함수는 파이썬의 리스트(list), 튜플(tuple) 등을 numpy의 ndarray 객체로 바꿔준다.
📍자주 사용하는 배열 생성 함수
- np.zeros(): 0으로 채워진 배열을 생성한다.
np.zeros(n)
→ 0이 n개 들어 있는 배열이 생성된다.
- np.ones(): 1로 채워진 배열을 생성한다.
np.ones(n)
→ 1이 n개 들어 있는 배열이 생성된다.
- np.arange(): 정수 범위의 배열을 생성한다.
np.arange(a)
np.arange(a, b)
np.arange(a, b, c)
- np.arange(a) → 0 이상 a 미만
- np.arange(a, b) → a 이상 b 미만
- np.arange(a, b, c) → a 이상 b 미만, 간격 c
기본적으로 파이썬의 range()와 매우 비슷하게 생각하면 된다.

- np.linspace(): 구간을 균등하게 나눠 수열을 생성한다.
np.linspace(a, b, num=n)
→ a부터 b까지를 n개로 균등 분할한 값을 생성한다. np.arange(a, b, c)와 헷갈리지 않기! (이건 간격이 아니라 n개로 분할한다는 것)

아래는 난수 생성 관련 함수이다.
- np.random.randint(a, b, size=n)
→ a 이상 b 미만의 정수 난수 n개를 생성한다. - np.random.choice(list, size=n)
→ 리스트에서 n개의 샘플을 추출한다.
기본값은 replace=True라서 중복 허용 추출이다. 중복 없이 뽑고 싶다면 replace=False를 써야 한다. - np.random.normal(loc, scale, size=n)
→ 평균(loc), 표준편차(scale)를 갖는 정규분포 난수 n개를 생성한다.

함수 안의 인자는 순서대로만 넣어도 되지만, 아래처럼 이름을 직접 써주면 더 보기 좋다.
np.random.normal(50, 10, 5)
np.random.normal(loc=50, scale=10, size=5)
📍ndarray 자료형 확인
배열에 type()을 쓰면 numpy.ndarray가 출력된다. 즉, numpy 배열은 n차원 배열 객체이다.

📍배열의 기본 속성
- size
배열 안에 들어 있는 전체 원소 수이다. - shape
배열의 구조를 튜플 형태로 반환한다. - ndim
배열의 차원 수이다.
→ 배열에 .을 붙이고 원하는 속성을 확인하면 된다.

📍1차원 array
1차원 배열은 리스트처럼 생각하면 비교적 이해하기 쉽다. 인덱싱과 슬라이싱도 거의 똑같게 사용한다.
array[n]
array[a:b:c]
- array[n] → n번째 인덱스 값 선택
- array[a:b:c] → a 이상 b 미만 구간에서 c칸 간격으로 선택
인덱스는 항상 0부터 시작함을 주의하자.

📍2차원 array
2차원 배열은 리스트 안에 리스트가 있는 형태로 생각하면 된다. 예를 들어 2차원 배열에서 array[0]을 하면 첫 번째 행 전체가 나온다.
어떤 하나의 요소를 뽑고 싶다면 행과 열을 둘 다 지정해야 한다.
array[0][1]
또는 numpy에서는 보통 아래 방식도 많이 쓴다.
array[0, 1]
둘 다 같은 위치의 값을 가리킨다.

2️⃣조건에 맞는 데이터 선택하기
numpy에서는 불린 인덱싱(Boolean Indexing) 으로 조건에 맞는 데이터를 선택할 수 있다.
📍불린 인덱싱이란
조건식의 결과인 True / False를 이용해서 원하는 데이터만 추출하는 방식이다.
- 특정 값 이상인 값만 보고 싶을 때
- 특정 범위 안의 값만 보고 싶을 때
유용하게 사용된다.
원리는 단순하다.
- 조건을 만족하면 True
- 만족하지 않으면 False
그리고 True인 위치의 값들만 골라서 보여준다.

조건이 여러 개인 경우엔 and, or, not의 기호인 &, |, ~ 를 이용하여 조건을 연결시켜주면 된다.

3️⃣조건에 따라 값 변경하기
📍np.where()
조건에 따라 값을 선택하거나 바꾸는 함수이다.
np.where(조건, 참일 때 값, 거짓일 때 값)
엑셀의 IF 함수와 비슷하게 생각하면 이해가 쉽다.
예를 들어 점수가 60 이상이면 "합격", 아니면 "불합격"처럼 분기 처리를 할 수 있다.

4️⃣기본 연산
📍배열과 스칼라 연산
여기서 스칼라는 그냥 하나의 숫자 값이라고 생각하면 된다.
배열에 숫자를 더하거나 빼면, 모든 요소에 한 번에 적용된다.
array + 1000
array - 3
array * 2
array / 10
사칙연산이 모두 동일하게 적용된다.

📍배열과 배열 연산
배열끼리 연산하면 같은 위치의 요소끼리 계산된다.
즉, 첫 번째 요소끼리, 두 번째 요소끼리 계산하는 방식이다.

📍numpy의 대표적인 함수
- mean(): 평균
- sum(): 합계
- min(): 최솟값
- max(): 최댓값
- std(): 표준편차(Standard Deviation)
- var(): 분산(Variance)
표준편차와 분산은 데이터가 평균으로부터 얼마나 퍼져 있는지, 즉 변동성을 나타낸다. - round(데이터, 반올림 할 자리수): 반올림
엑셀에서 보던 함수들과 꽤 비슷한 느낌이라 낯설지는 않았다.
📍축 지정: axis
배열의 합계, 평균 등을 구할 때 axis를 지정할 수 있다.
이 부분은 처음에 헷갈리기 쉬운데, 정확히 정리하면 다음과 같다.
- axis=0 : 행 방향으로 내려가며 계산 → 결과는 열별 계산
- axis=1 : 열 방향으로 가로질러 계산 → 결과는 행별 계산
즉,
- axis=0 → 각 열(column) 별로 계산
- axis=1 → 각 행(row) 별로 계산
축을 지정하지 않으면 전체 요소를 대상으로 계산한다.

📍np.any()
조건을 만족하는 값이 하나라도 있으면 True를 반환한다.
불린 인덱싱처럼 선택하는 용도라기보다, 조건 만족 여부를 빠르게 판단하는 함수다.

🐼pandas 라이브러리
numpy 다음으로는 가장 핵심적인 라이브러리인 pandas를 배웠다.
📍pandas란
pandas는 데이터를 표 형태(DataFrame) 로 다루고 분석하는 라이브러리다.
강사님께서 계속 가장 중요하다고 강조하신 라이브러리이기도 하다.
📍pandas의 주요 기능
- 데이터 불러오기
- 데이터 가공
- 데이터 분석
pandas는 numpy를 기반으로 만들어진 고수준 데이터 분석 라이브러리다.
📍numpy만으로 데이터 분석하기 불편한 이유
numpy array는 계산에는 강하지만, 실제 분석에서는 한계가 있다.
- 가독성이 떨어진다
행과 열의 의미를 한눈에 파악하기 어렵다. - 레이블(행/열 이름)을 붙이기 어렵다
데이터의 의미를 표현하기 불편하다. - 한 가지 데이터 타입만 다루기 적합하다
실제 데이터는 숫자, 문자열, 날짜 등이 섞여 있는 경우가 많다.
그래서 실제 분석에서는 numpy만으로 하기보다는 pandas를 함께 써야한다.
1️⃣pandas 시작하기
📍pandas 불러오기
import pandas as pd
그리고 중요한 점. 코랩에서는 코드 셀은 남아 있어도 만약 런타임이 다시 시작되면 라이브러리는 다시 불러와야 한다. 따라서 코드가 맞는데도 실행이 안 된다면 먼저 import가 되어 있는지 확인해야 한다. 필요한 라이브러리가 설치되어 있지 않다면 아래처럼 설치할 수도 있다.
!pip install 패키지명
다만 보통 pandas, numpy 같은 기본 라이브러리는 코랩에 이미 설치되어 있는 경우가 많다!
📍DataFrame 생성하기
서로 다른 형태의 자료를 그대로 분석하기는 불편하다. 예를 들어 딕셔너리, 리스트, 배열은 각각 구조가 다르다.
이럴 때 pd.DataFrame()을 사용하면 데이터프레임 형태로 바꿀 수 있다.
pd.DataFrame()
여기서 D와 F는 대문자라는 점도 중요하다. 데이터프레임으로 변환하고 출력하면, 훨씬 보기 쉬운 테이블 형태가 된다.

보통 변수명은 이름_df처럼 만드는 경우가 많다. type()으로 확인하면 다음과 같은 자료형이 나온다.
pandas.core.frame.DataFrame
즉, 데이터프레임 객체라는 뜻이다.
📍파일 입출력(csv, Excel) - 코랩에서 파일 불러오기
- 직접 업로드
코랩 왼쪽의 파일 아이콘을 클릭해서 세션 저장소에 업로드하거나 드래그 앤 드롭하는 방법이다.
데이터가 적을 때는 괜찮지만 파일이 많아지면 번거롭다. - 구글 드라이브 마운트
데이터 파일이 많을 때는 이 방법이 훨씬 편하다.
과정은 대략 이렇다.
- 내 구글 드라이브에 데이터용 폴더 생성
- 그 안에 csv, xlsx 파일 업로드
- 코랩 왼쪽 파일 아이콘 클릭
- 마운트 아이콘 클릭
- 자동 생성된 코드 실행
- 실행 후 drive 폴더 생성 확인

이렇게 하면 파일을 하나하나 업로드하지 않아도 구글 드라이브에 있는 데이터를 바로 불러올 수 있다.
📍현재 작업 디렉토리 확인 및 변경
- os.getcwd()
현재 작업 디렉토리를 확인한다.
코랩에서 직접 업로드한 경우 보통 /content/가 현재 작업 경로로 잡혀 있다. - os.chdir()
작업 디렉토리를 변경한다.
구글 드라이브를 마운트했다면 os.chdir()로 작업 디렉토리를 드라이브 안의 폴더로 바꿔둘 수 있다.
그러면 매번 긴 경로를 쓰지 않고도 파일명만 입력해서 불러올 수 있다. 경로는 드라이브 내 폴더의 경로를 복사하면 된다.

즉, 현재 디렉토리를 잘 설정해두면 이후 read_csv("파일명.csv")처럼 훨씬 간단하게 불러올 수 있다.
📍csv 파일 불러오기
- pd.read_csv()
csv 파일을 읽을 때 사용한다.
pd.read_csv("파일명 또는 경로")
불러올 때 변수에 할당하는 것도 중요하다.
df = pd.read_csv("파일명.csv")
- index_col
특정 컬럼을 인덱스로 지정해서 읽어올 수 있다.
pd.read_csv("파일명.csv", index_col="컬럼명")
다만 보통은 특별한 이유가 있을 때만 쓰고, 일반적으로는 따로 지정하지 않는 경우가 많다.
- head()
상위 몇 행만 미리 확인할 수 있다.
df.head()
df.head(10)
기본값은 상위 5행이다.

📍여기서 csv란?
CSV는 Comma Separated Values의 줄임말이다.
즉, 쉼표로 구분된 데이터 파일이다. 만약 파일을 열었을 때 구분자가 쉼표가 아니라 탭(\t)처럼 되어 있다면 sep 옵션으로 구분자를 지정할 수도 있다.
pd.read_csv("파일명.csv", sep="\t")
📍Excel 파일 불러오기
- pd.read_excel()
xlsx 파일을 읽을 때 사용한다.
pd.read_excel("파일명.xlsx")
불러오기 옵션
- header : 열 이름이 시작되는 행 번호 지정
- sheet_name : 불러올 시트 이름 또는 번호 지정
- usecols : 불러올 열 선택
실습에서는 xlsx 파일을 읽었는데 아무 데이터가 안 보이고 표 모양만 보이는 경우가 있었다.
확인해보니 데이터가 첫 번째 시트가 아니라 두 번째 시트에 있었다. pandas는 기본적으로 첫 번째 시트를 읽기 때문에, 이럴 때는 sheet_name을 지정해야 한다.
pd.read_excel("파일명.xlsx", sheet_name=1)
또 어떤 경우는 시트를 읽었더니 앞의 몇 열이 전부 NaN으로 나왔다.
보니 실제 데이터가 더 아래 행에서 시작하고 있었다. 이럴 때는 header를 조정해야 한다.
pd.read_excel("파일명.xlsx", header=2)
또한 열도 선택해서 불러올 수 있다.
pd.read_excel("파일명.xlsx", usecols="A:C")
또는 위처럼 알파벳이 아닌 숫자 범위도 가능하다.

정리하면, Excel 파일은 실제 시트 구조가 정돈되어 있지 않으면 읽을 때 옵션을 많이 조정해야 해서 번거롭다. 그래서 가능하면 애초에 데이터를 정리된 형태로 준비하는 것이 가장 좋다.
📍데이터 파일 내보내기
- df.to_csv()
데이터프레임을 csv 파일로 저장한다.
df.to_csv("파일명.csv")
경로를 따로 지정하지 않으면 현재 작업 디렉토리에 저장된다.
- index=False
맨 앞의 인덱스 열을 제외하고 저장하고 싶다면 다음과 같이 쓴다.
df.to_csv("파일명.csv", index=False)
여기서 옵션명은 index=False이지 index_col이 아니다.
- df.to_excel()
데이터프레임을 Excel 파일로 저장한다.
df.to_excel("파일명.xlsx")
내보내기 옵션
- sheet_name: 시트 이름 지정
- startrow: 시작 행 지정
- startcol: 시작 열 지정
- index=False: 인덱스 열 제외
df.to_excel("파일명.xlsx", sheet_name="Sheet1", startrow=0, startcol=0, index=False)
- pd.ExcelWriter
여러 개의 데이터프레임을 하나의 엑셀 파일에 여러 시트로 저장할 때 사용한다.
with pd.ExcelWriter("파일명.xlsx") as writer:
df_1.to_excel(writer, sheet_name="name1", index=False)
df_2.to_excel(writer, sheet_name="name2", index=False)
엑셀에서 직접 시트 나누고, 인덱스 지우고, 이름 바꾸고 하는 작업을 손으로 하면 번거롭고 실수도 나기 쉬운데, pandas로는 코드 몇 줄이면 끝낼 수 있다는 점이 정말 편리하다.
2️⃣DataFrame 구조 이해하기
📍데이터 파악하기
데이터를 불러왔다면 가장 먼저 해야 할 일은 구조를 파악하는 것이다.
- head(): 상위 n개 행을 출력한다.

- tail(): 하위 n개 행을 출력한다.

- shape: 행과 열의 개수를 튜플로 반환한다.

- dtypes: 각 컬럼의 데이터 타입을 확인할 수 있다. (예: int64, float64, object)

여기서 object는 문자열 컬럼으로 보면 된다.
- info(): 데이터프레임의 전체 구조를 한 번에 보여준다. 행/열 개수, 컬럼명, 각 컬럼의 자료형, 결측치 개수 여부(non-null count) 등.

데이터 구조를 빠르게 파악할 때 정말 유용하다.
- describe(): 수치형 컬럼의 기술 통계량을 확인할 수 있다. (count, mean, std, min, 25%, 50%, 75%, max)

여기서,
- 25% = 1사분위수(Q1)
- 50% = 2사분위수(Q2, 중앙값)
- 75% = 3사분위수(Q3)
이다. 나중에 더 자세히 나온다!
- describe(include='all') : 문자형 컬럼까지 포함해서 요약 통계를 확인할 수 있다.

문자열 컬럼의 경우 평균, 표준편차 같은 값은 계산할 수 없기 때문에 NaN으로 나오고,
- count: 데이터 수
- unique: 범주 수
- top : 최빈값
- freq : 최빈값의 빈도
대신 위 통계값이 나온다.
- sort_values(): 특정 컬럼에 대해 데이터를 정렬한다.
df.sort_values(by="컬럼명", ascending=True)
- ascending=True : 오름차순
- ascending=False : 내림차순
📍인덱스와 컬럼 구조 이해하기
- 인덱스 설정하기
데이터프레임을 읽으면 기본적으로 0, 1, 2, 3 ... 같은 숫자 인덱스가 붙는다.
그런데 어떤 컬럼이 각 행을 대표하는 고유 식별자라면, 그 컬럼을 인덱스로 설정하는 것이 더 편할 수 있다.
- 인덱스로 쓸 수 있는지 확인
인덱스 후보 컬럼은 보통 다음 조건을 만족하는 것이 좋다.
- 고유해야 한다
- 결측값이 없어야 한다
→ 이를 확인하는 방법:
- count() : 전체 개수
- unique() : 고유값 목록
- nunique() : 고유값 개수
- isnull().sum() 또는 isna().sum() : 결측 개수 (뒤에서 더 자세히 나온다.)
특히 고유성은 count()와 nunique()를 비교해서 확인하는 방식이 더 자연스럽다.
unique()는 실제 고유값 목록 자체를 보여준다.
- set_index()
특정 컬럼을 인덱스로 지정한다.
df.set_index("컬럼명")

주의할 점은, pandas의 많은 함수들은 원본을 바로 바꾸지 않고 결과만 반환한다는 점이다. (앞으로도 계속 주의!)
따라서 다음 중 하나를 해줘야 한다.
df = df.set_index("컬럼명")
변수 할당 또는
df.set_index("컬럼명", inplace=True)
inplace=True (대체하겠다는 의미)를 입력한다.
- reset_index()
설정한 인덱스를 다시 일반 컬럼으로 되돌릴 때 사용한다.
df.reset_index()
이 역시 원본에 반영하려면 변수 재할당 또는 inplace=True가 필요하다.
📍컬럼명 설정하기
- df.columns
컬럼명을 리스트 형태로 전체 확인할 수 있다.
분석하다 보면 컬럼명을 바꾸고 싶을 때가 많다.
- 방법 1. 컬럼 개수가 적을 때
df.columns로 컬럼 목록을 확인한 뒤, 새로운 컬럼명 리스트를 통째로 할당한다.
df.columns = ["새이름1", "새이름2", "새이름3"]
- 방법 2. 컬럼 개수가 많을 때
rename() 함수를 사용한다.
new_columns = {"이전이름": "새이름", "old": "new"}
df = df.rename(columns=new_columns)
역시 원본 반영 여부를 꼭 신경 써야 한다.
📍데이터 타입 다루기
데이터 타입 확인은 다음으로 할 수 있다.
- df.info()
- df.dtypes
특정 컬럼 하나만 보고 싶다면
df["컬럼명"].dtype
- astype():자료형을 변환한다.
df["컬럼명"] = df["컬럼명"].astype(자료형)
예를 들어 문자형으로 바꾸고 싶다면 str 또는 object를 사용할 수 있다. 다만 일반적으로 문자열 처리를 위해서는 str로 인식하는 편이 더 직관적이다.

📍DataFrame과 Series 구조 차이
- Series
1차원 데이터 구조이다. 즉, 하나의 열이다.
type()을 통해 출력하면 pandas.core.series.Series가 나온다. - DataFrame
여러 개의 Series가 모여 있는 2차원 표 구조이다.
즉,
- 데이터프레임에서 열 하나를 꺼내면 Series
- 여러 열을 선택하면 DataFrame
Series는 1차원 배열과 비슷하지만,
- 인덱스를 가진다는 점
- 다양한 데이터 타입을 다룰 수 있다는 점
에서 차이가 있다.
📍문자열 처리 기초
이 파트는 정말 많이 사용된다고 강조하셨다.
- unique()
범주의 종류를 출력한다.
출력 결과에 NaN이 보인다면 결측값이 있다는 뜻이다. - nunique()
범주의 개수만 출력한다.
기본적으로 결측값은 세지 않는다. - value_counts()
범주별로 빈도수를 확인한다.

출력 옵션
- dropna=True : 결측값 제외(기본값)
- dropna=False : 결측값 포함
- normalize=True : 비율로 출력

즉, 개수뿐 아니라 비율도 쉽게 볼 수 있다.
3️⃣DataFrame 다루기
📍데이터 선택(loc, iloc, 대괄호)
데이터프레임에서 원하는 행, 열을 선택하는 방법은 매우 중요하다.
- iloc: 정수 기반 인덱스로 데이터를 선택한다.
df.iloc[행번호, 열번호]
행번호와 열번호 모두 숫자 위치 기준이다. 여러 개를 선택할 때는 리스트를 쓴다.
df.iloc[[0, 1, 2], [1, 3]]

- loc: 레이블(이름)을 기반으로 데이터를 선택한다.
df.loc["행이름", "열이름"]
행/열 이름을 직접 넣기 때문에 더 직관적이다. 여러 개 선택도 가능하다.
df.loc[["행1", "행2"], ["열1", "열2"]]

- 대괄호로 선택
df["column1"]
→ 하나의 열 선택, 결과는 Series
df[["column1", "column2"]]
→ 여러 열 선택, 결과는 DataFrame
df[0:3]
→ 0~2번째 행 선택

📍조건 필터링(불린 인덱싱, query)
- 불린 인덱싱: 컬럼에 조건식을 직접 붙이면 각 행이 조건을 만족하는지 True/False로 나온다.
df["컬럼명"] > 10
특정 조건을 만족하는 행만 보고 싶다면 그 조건식을 다시 df[] 안에 넣는다.
df[df["컬럼명"] > 10]
조건을 만족하는 행에서 특정 컬럼만 보고 싶다면 열을 다시 선택하면 된다.
df[df["컬럼명"] > 10][["다른컬럼1", "다른컬럼2"]]

- 여러 조건 결합하기
중요한 점은 조건 하나하나를 괄호로 감싸는 것이다.
(df["컬럼명"] > 10) & (df["컬럼명"] < 5)
- and → &
- or → |
- not → ~
로 연결한다. 그리고 비교할 때는 =이 아니라 ==를 써야 한다는 것도 주의해야 한다.
- 조건식을 변수로 만들기
위의 예시처럼 조건을 따로 변수로 저장해두면 더 읽기 쉬워진다.
condition1 = df["컬럼명"] > 10
condition2 = df["컬럼명"] < 5
df[condition1 & condition2]
- query(): 문자열 형태의 조건식으로 필터링을 할 수 있다.
df.query("컬럼명 > 10")
컬럼명에는 따로 따옴표가 필요없다. 불린 인덱싱보다 코드가 짧고, 여러 조건일 때 가독성이 좋다.

이는 문자열 컬럼에도 사용할 수 있다. 즉, 숫자형만 가능한 것은 아니다. 예를 들어:
df.query("컬럼명 == '특정 문자열'")

문자열 비교 시에는 따옴표를 잘 구분해야 한다!!
- 외부 변수 참조: 조건식 안에서 파이썬 변수를 사용하려면 앞에 @를 붙인다.
avg = df["컬럼명"].mean()
df.query("컬럼명 > @avg")

- 여러 값 중 하나인지 확인: or가 여러 개 붙는 상황에서는 in이 편할 수 있다.
예를 들어 특정 컬럼 값이 여러 범주 중 하나인 경우:
df.query("컬럼명 in ['특정 문자열1', '특정 문자열2']")

not in도 가능하다.
추가로, 위에서 나왔던 and, or, not의 기호인 &, |, ~ 을 이용하여 조건식을 연결할 수도 있다.
📍데이터 수정 및 추가
- 특정 값 수정: 보통 loc를 많이 쓴다.
df.loc[행 인덱스, "컬럼명"] = 새값

- 특정 행 전체 수정: 특정 행 전체를 리스트로 바꿀 수 있다.
df.loc[행 인덱스] = [값1, 값2, 값3]

- 특정 열 전체 수정: 특정 열에 값을 한 번에 넣을 수 있다.
df["컬럼명"] = 값 또는 리스트
- 새로운 열 추가
df["새컬럼"] = 값
- 조건에 따라 값 추가/수정
df.loc[조건, "새컬럼"] = 값

조건을 만족하는 행에만 특정 값을 넣고 싶을 때 유용하다.
📍데이터 삭제
- drop(): 행 또는 열을 삭제한다. 기본값은 행 삭제(axis=0) 이다.
- 열(컬럼) 삭제
df.drop(columns="삭제할 컬럼")
또는
df.drop("삭제할 컬럼", axis=1)
로 컬럼을 삭제할 수 있도록 열로 지정을 해준다.

여러 열 삭제는 리스트로 가능하다.
df.drop(columns=["컬럼1", "컬럼2"])
- 행 삭제: 행은 인덱스 기준으로 삭제한다.
df.drop(행 인덱스)

마찬가지로 원본에 반영하려면 변수 재할당 또는 inplace=True가 필요하다.
4️⃣데이터 전처리 : 품질 관리
강사님께서는 데이터 분석에서 전처리에 80%의 시간이 들어간다고 하셨다. 그리고 전처리는 어디까지가 전처리라고 딱 잘라 말하기 어려울 정도로 범위가 넓다. 기본적으로 우리가 계속 확인하게 되는 것은 결측값, 중복값, 이상치이다.
이 파트를 설명하시면서 나온 말이 바로 GIGO(Garbage In, Garbage Out) 이다. 즉, 쓰레기가 들어오면 쓰레기가 나간다는 뜻. 입력 데이터 품질이 나쁘면 결과도 나빠질 수밖에 없다는 강한 표현이다..!
📍결측값 확인 함수
- isna() / isnull(): 둘 다 결측치 확인 함수이다. 사실상 같은 기능으로 보면 된다.
df.isna()
각 값이 결측인지 아닌지를 True/False로 보여준다.
📍결측치 개수 확인
df.isna().sum()
→ 컬럼별 결측치 개수
df.isna().sum().sum()
→ 전체 데이터프레임의 총 결측치 개수 (na는 not available의 의미이다.)

📍결측이 아닌 값 확인
df["컬럼명"].notna()
→ 결측이 아닌 값인지 여부
df[df["컬럼명"].notna()]
→ 해당 컬럼이 결측이 아닌 행만 보기
📍결측값 처리하기
- 삭제: dropna()
결측치가 있는 행을 제거한다.
df.dropna()
하지만 결측치는 무조건 지우면 안 된다! 결측이 많은 컬럼인지, 삭제 시 손실이 큰지 먼저 판단해야 한다.
- 대체: fillna()
결측값을 다른 값으로 채운다.
df["컬럼명"] = df["컬럼명"].fillna(대체값)
수치형 데이터는 대표값으로 평균, 중앙값, 최빈값 등을 많이 사용한다.
예를 들어 평균으로 채우려면:
mean_value = df["컬럼명"].mean()
df["컬럼명"] = df["컬럼명"].fillna(mean_value)

여기서 중요한 점은 할당이다. 만약, 아래처럼 쓰면 컬럼 하나만 남은 Series가 되어버릴 수 있으므로 주의해야 한다.
잘못된 할당:
df = df["컬럼명"].fillna(mean_value)
올바른 할당:
df["컬럼명"] = df["컬럼명"].fillna(mean_value)
📍중복값 확인하기
- duplicated(): 중복 여부를 불린값으로 반환
df.duplicated()
- 중복 행 수 확인
df.duplicated().sum()

- 중복 행만 보기
df[df.duplicated()]
기본적으로는 첫 번째는 남기고, 그 다음 중복부터 True가 된다. 이를 따로 지정하려면 keep 옵션을 사용한다.
- keep='first' : 첫 번째는 제외하고 이후 중복 표시
- keep='last' : 마지막은 제외하고 이전 중복 표시
- keep=False : 중복된 모든 행 표시

- 특정 컬럼 기준 중복 확인 (subset)
df.duplicated(subset="컬럼명")

여러 컬럼 기준이면 리스트를 쓴다.
df.duplicated(subset=["컬럼1", "컬럼2"])
중복값을 더 보기 좋게 정렬 옵션을 지정한다. (ascending=True)
df.sort_values(by="컬럼명", ascending=True)
📍중복값 처리하기
- drop_duplicates(): 중복되는 행을 제거한다.
df.drop_duplicates()
- 특정 컬럼 기준 중복 제거 (subset)
df.drop_duplicates(subset="컬럼명")
여러 컬럼 기준으로도 가능하다.
df.drop_duplicates(subset=["컬럼1", "컬럼2"])

전처리가 오래 걸리는 이유는, 단순히 함수 사용이 어려워서가 아니라 무엇을 어떤 기준으로 처리할지 결정하는 과정이 오래 걸리기 때문이라는 말이 인상 깊었다.
📍이상점 처리
이상점(outlier)은 다른 값들과 동떨어져 있는 너무 크거나 너무 작은 값을 말한다. 즉, 대부분의 데이터와 비교했을 때 유난히 극단적인 값이다. (문자열에서는 보통 오탈자)
📍이상치 탐지 기준
정답은 없지만 보통 다음이 많이 사용된다.
- IQR
- Z-score
📍IQR 기반 이상치 탐지
IQR(Interquartile Range)은 Q3 - Q1 이며 데이터를 오름차순으로 정렬했을 때,
- Q1 = 25%
- Q2 = 50% (중앙값)
- Q3 = 75%
이때,
- 하한 = Q1 - 1.5 × IQR
- 상한 = Q3 + 1.5 × IQR
이 범위를 벗어나면 일반적으로 이상치로 본다.
📍Q1, Q3 구하는 방법
- describe(): (위에서 나온) 기술 통계량을 확인하는 함수이다.
df["컬럼명"].describe()
- quantile(): 분위수에 해당하는 값을 반환한다.
q1 = df["컬럼명"].quantile(0.25)
q3 = df["컬럼명"].quantile(0.75)
- IQR, 상한, 하한 계산 (단순 공식 적용)
iqr = q3 - q1
lower_limit = q1 - 1.5 * iqr
upper_limit = q3 + 1.5 * iqr
- 이상치 조건 만들어보기
outlier = (df["컬럼명"] < lower_limit) | (df["컬럼명"] > upper_limit)
df[outlier]

여기서도 조건식을 괄호로 감싸는 것이 보기 좋다.
📍이상치 처리 방법
이상치도 무조건 삭제하는 게 아니라 데이터 의미를 보고 판단해야 한다.
- 그대로 두기
극단적이지만 실제로 충분히 가능한 값이라면 그대로 둔다. - 삭제하기
입력 오류, 측정 오류, 비현실적인 값이라면 제거할 수 있다.
예) 나이가 1000살인 경우.. - 정상 범위로 조정하기
상한/하한으로 잘라내거나, 논리적으로 가능한 값으로 대체하는 방식이다.
예) 양수여야 하는 값이 음수라면 0으로 조정
5️⃣데이터 전처리 : 문자열 처리
문자열 처리도 매우 많이 사용하는 파트다. 데이터는 항상 깔끔하게 들어오지 않기 때문에, 문자열을 정리하는 작업이 자주 필요하다.
📍대소문자 처리하기
사람 눈에는 apple, Apple, APPLE이 비슷해 보여도 컴퓨터는 서로 다른 값으로 인식한다. 그래서 대소문자가 섞여 있으면 통일이 필요하다. 문자열 전용 메서드를 데이터프레임에 적용할 때는 .str 접근자를 쓴다.
- str.upper(): 모든 문자를 대문자로 변환한다.
df["컬럼명"].str.upper()

- str.lower(): 모든 문자를 소문자로 변환한다.
df["컬럼명"].str.lower()

- str.capitalize(): 첫 글자만 대문자로, 나머지는 소문자로 변환한다.
df["컬럼명"].str.capitalize()

변환 전에는 unique()로 범주를 먼저 확인해보면 어떤 식으로 대소문자가 섞여 있는지 파악하기 쉽다.

(주의!) 그리고 결과를 원본에 반영할 때는 해당 컬럼에만 할당해야 한다.
df["컬럼명"] = df["컬럼명"].str.lower()
📍문자열 분리하기
주소, 상품명, 제조사, 코드 등 하나의 문자열 안에 정보가 여러 개 들어 있는 경우 문자열 분리가 필요하다.
- str.split(): 문자열을 구분자를 기준으로 나눈다.
df["컬럼명"].str.split("구분자")
이렇게 하면 각 값이 리스트 형태가 된다. 분리 후 특정 위치의 값만 가져오고 싶다면
df["컬럼명"].str.split("구분자").str[0]
처럼 쓸 수 있다.

분리 후 원래 합쳐져 있던 컬럼이 필요 없다면 삭제한다.
📍불필요한 문자 제거하기
- str.strip(): 양쪽 공백을 제거한다.
df["컬럼명"].str.strip()
필요하면 unique()로 잘 제거되었는지 확인할 수 있다.
- str.replace(): 필요없는 특정 문자열을 치환한다.
df["컬럼명"].str.replace("제거할문자", "")
- regex=True : 정규표현식을 사용한다.
- regex=False : 단순 문자를 치환한다.
정규표현식까지 가면 더 복잡해지지만, 기본적인 문자 제거에는 아주 자주 쓰인다.

📍문자열 탐색하기
- str.startswith()
특정 문자열로 시작하는지 확인한다. - str.endswith()
특정 문자열로 끝나는지 확인한다. - str.contains()
특정 문자열이 포함되어 있는지 확인한다.
예를 들어 특정 문자열로 시작하는 행만 보고 싶다면,
df[df["컬럼명"].str.startswith("문자열")]

문자열 탐색은 결측치나 중복처럼 무조건 해야 하는 것은 아니고, 상황에 따라 필요한 경우 사용한다.
📍문자열 포맷 맞추기
- str.len(): 문자열의 길이를 먼저 확인한다.
df["컬럼명"].str.len()
- str.pad(): 문자열 길이를 맞추기 위해 특정 문자를 채운다.
df["컬럼명"].str.pad(width=길이, side=어느 쪽에 채울건지, fillchar="채울 문자")

많이 쓰는 편은 아니지만, 코드 길이 맞추기 같은 상황에서 유용할 수 있다.
📍범주형 데이터 타입 다루기
- pd.Categorical(): 범주의 순서를 지정할 수 있다.
예를 들어 낮음 < 보통 < 높음처럼 순서가 있는 범주형 데이터라면 일반 문자열 정렬보다 범주형 타입으로 바꾸는 것이 더 적절하다.
df["컬럼명"] = pd.Categorical(
df["컬럼명"],
categories=["낮음", "보통", "높음"],
ordered=True
)
ordered=True는 전달한 순서를 유지시킨다. 이 이후 정렬하면 지정한 범주 순서대로 정렬된다.
df.sort_values(by="컬럼명")

6️⃣데이터 전처리 : 수치 데이터 처리
📍파생 변수 생성
기존 컬럼끼리 계산해서 새로운 컬럼을 만드는 것을 파생 변수를 생성한다고 한다.
df["새컬럼"] = df["컬럼1"] + df["컬럼2"]
사칙연산 모두 가능하다.
df["비율"] = df["매출"] / df["방문자수"]
파생 변수는 실제 분석에서 정말 많이 쓰인다.

📍스케일링 : 정규화, 표준화
스케일링은 숫자 데이터의 크기 범위를 맞추는 과정이다. 서로 단위가 다른 데이터를 비교하거나 모델에 넣을 때 중요하다.
- 정규화(Normalization)
정규화는 데이터를 0과 1 사이 값으로 변환하는 것이다. 대표적으로 Min-Max Scaling이 있다.

파이썬으로는 다음처럼 구현할 수 있다.
df["정규화컬럼"] = (df["컬럼명"] - df["컬럼명"].min()) / (df["컬럼명"].max() - df["컬럼명"].min())
정규화가 잘 되었는지는 describe()로 확인했을 때 최소값이 0, 최대값이 1에 가까운지 보면 된다.

- 표준화(Standardization)
표준화는 데이터가 평균으로부터 얼마나 떨어져 있는지를 표준편차 단위로 나타내는 것이다. Z-score라고도 한다.

파이썬으로는 다음처럼 구할 수 있다.
df["표준화컬럼"] = (df["컬럼명"] - df["컬럼명"].mean()) / df["컬럼명"].std()
표준화 후에는 평균이 0, 표준편차가 1에 가까운지 확인한다.

위에서 평균이 -9.034918e-16처럼 나왔던 것은 사실상 0으로 보면 된다. 1.000000e+00은 1이다. 이런 형태는 지수 표기법이다.
📍구간화
구간화(binning)는 연속형 수치 데이터를 여러 구간으로 나눠서 범주형 데이터처럼 바꾸는 작업이다.
- pd.cut(): 숫자 데이터를 지정한 구간으로 나누는 함수이다.
df["새로운컬럼"] = pd.cut(
df["숫자형컬럼"],
bins=[경계1, 경계2, 경계3, ...],
labels=["라벨1", "라벨2", ...],
right=False)
옵션
- bins : 구간 경계값
- labels : 각 구간 이름
- right=False : 오른쪽 경계 포함하지 않음

구간을 나누기 전에 describe()로 최소/최대값을 먼저 보는 게 좋다.
📍apply 활용
- apply(): Series나 DataFrame에 함수를 적용할 수 있다.
예를 들어 제곱근 함수를 적용하려면,
df["컬럼명"].apply(np.sqrt)

- lambda: 이름 없는 간단한 함수를 사용할 때 사용한다.
df["새컬럼"] = df["기존컬럼"].apply(lambda x: x * 2)
즉, apply(lambda ...)는 즉석에서 간단한 로직을 작성해서 각 값에 적용하는 방식이다. 조건문 형태도 가능하다.

7️⃣날짜와 시간 데이터 다루기
강사님께서 이 부분도 중요하다고 하셨다. 날짜 데이터는 일반 문자열과 다르게 처리해야 하고, 시계열 분석이나 시간 단위 집계에서 자주 사용된다.
📍날짜 데이터 타입 설정하기
- pd.to_datetime(): 문자열이나 숫자를 날짜/시간 타입으로 변환한다.
df["날짜컬럼"] = pd.to_datetime(df["날짜컬럼"])
변환 후 데이터 타입은 보통 datetime64 형태로 보인다.

📍날짜 데이터 형식 추출하기
날짜형 컬럼에서는 .dt를 이용해 다양한 정보를 뽑을 수 있다.
df["날짜컬럼"].dt.year
df["날짜컬럼"].dt.month
df["날짜컬럼"].dt.day
뽑을 수 있는 요소
- 년도: dt.year
- 월: dt.month
- 일: dt.day
- 요일 번호: dt.dayofweek 또는 dt.weekday (월요일 = 0, 일요일 = 6)
참고: https://pandas.pydata.org/docs/reference/api/pandas.Series.dt.weekday.html - 시간: dt.hour
- 분: dt.minute
- 초: dt.second

년-월 형태로도 가능하다.
df["날짜컬럼"].dt.to_period("M")

보통 자주 보는 단위는 연도, 월, 년-월, 요일, 시간 정도이다.
- strftime(): 원하는 문자열 형식으로 날짜를 출력할 수도 있다.
참고: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
df["날짜컬럼"].dt.strftime("%Y년 %m월 %d일 %H시 %M분 %S초")

📍날짜와 시간을 더하고 빼기
날짜 컬럼끼리 빼면 기간 차이를 계산할 수 있다.
df["기간"] = df["종료일"] - df["시작일"]
이 결과의 자료형은 timedelta64이다.

8️⃣데이터 합치기
merge, concat 순으로 많이 사용하고 join은 상대적으로 덜 쓴다고 한다.
📍concat() : 같은 형식의 데이터 합치기
- pd.concat(): 행 방향 또는 열 방향으로 단순히 이어 붙이는 함수이다.
pd.concat([df1, df2])
기본값은 위아래(행 방향)로 붙인다.

- 인덱스 다시 매기기
위 예시처럼 원래 있던 인덱스가 그대로 붙기 때문에 (0,1, 2, 0,1, 2 식으로..) 새로 번호를 매기고 싶다면,
pd.concat([df1, df2], ignore_index=True)

- 옆(열 방향)으로 붙이기 (axis=1)
pd.concat([df1, df2], axis=1)
이 함수는 연도별 매출 데이터, 월별 파일 등처럼 형식이 같은 데이터를 이어붙일 때 유용하다.
📍merge() : 컬럼 기준 데이터 합치기
- 조인(Join) 개념
- 두 데이터셋에 공통으로 존재하는 값을 기준(Key) 으로 연결하는 방식이다.
예) 고객 ID, 주문 번호, 회원 번호 등
- 조인의 종류
- Inner Join
양쪽 모두에 존재하는 키만 결합(기본값) - Left Outer Join
왼쪽 데이터는 모두 유지하고, 오른쪽에서 일치하는 것만 붙임
엑셀의 VLOOKUP과 비슷한 느낌으로 이해할 수 있다. - Right Outer Join
오른쪽 데이터는 모두 유지하고, 왼쪽에서 일치하는 것만 붙임 - Full Outer Join
양쪽의 모든 키를 포함해 결합
실무에서는 보통 inner join과 left join을 많이 쓴다.
- 기본 사용법 (how 옵션에는 위의 조인의 종류 중 하나를 선택하여 입력한다.)
pd.merge(df1, df2, on="기준컬럼", how="inner")
- 기준 컬럼명이 다를 때
pd.merge(
df1, df2,
left_on="왼쪽기준컬럼",
right_on="오른쪽기준컬럼",
how="left"
)

즉, merge는 단순히 붙이는 게 아니라 핵심이 되는 컬럼을 기준으로 연결한다는 점이 concat과 가장 큰 차이이다.
📍join() : 인덱스 기준 데이터 합치기
- join(): 주로 인덱스를 기준으로 데이터를 합친다.
df1.join(df2, lsuffix="_x", rsuffix="_y", how="left")
- lsuffix : 왼쪽 컬럼명 충돌 시 붙일 접미사
- rsuffix : 오른쪽 컬럼명 충돌 시 붙일 접미사

정리하면
- merge()는 컬럼 기준
- join()는 인덱스 기준
다만 상황에 따라 각각 비슷하게 활용되는 경우도 있다.
9️⃣집계 및 요약 분석
데이터를 정리한 뒤에는 묶고, 계산하고, 요약하는 작업이 필요하다. 이때 핵심이 되는 것이 groupby, pivot table, resample 등이다.
📍그룹화 : groupby
- groupby(): 특정 컬럼 기준으로 데이터를 묶어 집계한다.
예를 들어 어떤 범주별 평균을 보고 싶다면,
df.groupby("컬럼명").mean(numeric_only=True)
- numeric_only=True : 숫자형 컬럼만 계산
특정 컬럼만 보고 싶다면,
df.groupby("컬럼명")["집계할컬럼"].mean()

📍다양한 통계 계산
groupby 이후 여러 가지 집계 함수를 사용할 수 있다. 자주 쓰는 함수는 size() : 전체 행 개수, count() : 결측 제외 값 개수, mean(), sum(), max(), min() 정도이다.
- agg(): 여러 통계값을 한 번에 계산한다.
df.groupby("컬럼명").agg(["mean", "max", "min"])
컬럼마다 다른 집계를 적용할 수도 있다.
df.groupby("컬럼명").agg({
"컬럼1": "mean",
"컬럼2": ["min", "max"]
})

📍정렬
집계 후에 결과를 정렬하면 보기 쉽다.
df.groupby("컬럼명").agg({
"score": "mean"
}).sort_values(by="score", ascending=False)
📍문자열 집계/요약
groupby는 숫자뿐 아니라 문자열도 집계할 수 있다.
예를 들어 그룹별 문자열을 쉼표로 연결하려면,
df.groupby("컬럼명")["문자열컬럼"].apply(lambda x: ", ".join(x))

단, 이때 결측값이 섞여 있으면 처리 방식에 유의해야 한다.
📍멀티 인덱스
두 개 이상의 기준으로 그룹화하면 결과 인덱스가 여러 단계가 된다.
df.groupby(["기준1", "기준2"])["집계컬럼"].mean()

이렇게 하면 위 예시처럼 멀티 인덱스 구조가 생긴다.
📍피벗 테이블
피벗 테이블은 데이터를 집계하고 요약해서 한눈에 보기 쉽게 만드는 표이다.
엑셀 피벗 테이블과 거의 같은 개념이라고 생각하면 된다.
- pivot_table()
pd.pivot_table(
df,
values="계산할컬럼",
index="행기준",
columns="열기준",
aggfunc="집계방법"
)

예를 들어 행에는 지역, 열에는 연도, 값에는 매출 평균을 놓는 식으로 구조화할 수 있다.
📍시간 단위 리샘플링
날짜형 데이터는 특정 시간 단위로 다시 묶어서 집계할 수 있다.
- 먼저 날짜 컬럼을 인덱스로 설정한다.
df = df.set_index("날짜컬럼")
- resample(): 시간 단위로 기준을 집계한다.
df.resample("YE").sum(numeric_only=True)
df.resample("ME").sum(numeric_only=True)
df.resample("D").sum(numeric_only=True)
각각 연 단위, 월 단위, 일 단위이다.

👏마무리
이렇게 해서 ‘Python으로 데이터 다루기’ 파트의 진도가 드디어 끝났다.................ㅠㅠ
이번 내용은 단순히 한 번 배우고 지나가는 개념이 아니라, 앞으로 계속해서 반복해서 보게 될 기본기이자 핵심 도구들이라는 점에서 정말 중요했다.
특히 이번 파트는 단순 문법 암기보다도,
- 데이터를 어떻게 불러오고
- 구조를 어떻게 파악하고
- 어떤 기준으로 선택하고
- 어떻게 수정, 삭제, 결합하고
- 결측값, 중복값, 이상치 같은 품질 문제를 어떻게 처리하며
- 문자열, 숫자, 날짜 데이터를 각각 어떤 방식으로 다뤄야 하는지
를 전체 흐름으로 익히는 시간이었던 것 같다.
실제로 데이터 분석에서는 데이터를 예쁘게 모델에 넣기 전까지의 과정, 즉 전처리와 탐색이 훨씬 더 길고 중요하다는 말을 계속 들었는데, 이번 3일 동안 그 이유를 조금 더 실감할 수 있었다. pandas가 왜 그렇게 중요하다고 하셨는지도 점점 이해가 갔다.
무엇보다 이번 파트는 함수 개수가 정말 많아서 처음에는 헷갈릴 수밖에 없지만, 중요한 건 모든 걸 완벽히 외우는 것보다 “이 상황에서 어떤 기능을 써야 하는지 떠올릴 수 있는 것”, 그리고 출력 결과를 보고 왜 그렇게 나왔는지 이해하는 것이라는 말이 꽤 위안이 되었다. 앞으로 스프린트 미션이나 실습에서 이 내용들이 계속 등장할 테니, 이번 글도 필요할 때마다 다시 보면서 복습해야겠다~!(이번 글 정리 정말 어려웠다!!!!!!!!!!!)
'Codeit Sprint > 공부 기록' 카테고리의 다른 글
| SQL로 하는 데이터 분석 | SQL 기초부터 함수, JOIN, 서브쿼리, CTE까지 전체 정리 (1) | 2026.04.28 |
|---|---|
| Tableau로 대시보드 제작하기 | BI 개념부터 다양한 차트, 분석 기능, 대시보드 제작까지 전체 정리 (1) | 2026.03.30 |
| Python으로 하는 데이터 시각화 | 기술 통계부터 matplotlib, seaborn, plotly까지 전체 정리 (1) | 2026.03.30 |
| 데이터 분석을 위한 Python 기본기 | 파이썬 기초 내용 전체 정리(자료형, 함수, 리스트, 제어문) (1) | 2026.03.13 |
| Excel로 하는 데이터 분석 | 데이터 분석 실습 내용 전체 정리(참조, 함수, 피벗테이블, 차트, 전처리) (1) | 2026.03.12 |
