베이직
datetime 변환
- datetime 객체는 기본적으로 YYYY-MM-DD HH:MM:SS(연-월-일 시:분:초) 형태
datetime 형태로 변환
import pandas as pd
pd.to_datetime(df, format='mixed', errors='coerce')
#errors='coerce': 변환 불가능한 값은 NaT 처리
날짜 형식 지정
- 날짜 및 시간 형식 변환
- strftime: 날짜 객체를 문자열로 변환
- strptime: 문자열을 날짜 객체로 변환
- 주요 포맷 코드
- %Y: 4자리 연도(2025)
- %y: 2자리 연도(25)
- %m: 월
- %B: 월의 전체 이름(January)
- %d: 일
- %H:%M:%S: 시, 분, 초
from datetime import datetime
now = datetime.now()
formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
print(formatted_date, type(formatted_date)) # 2025-02-03 08:48:39 <class 'str'>
date_str = "2025-02-01"
date_obj = datetime.strptime(date_str, "%Y-%m-%d")
print(date_obj, type(date_obj)) # 2025-02-01 00:00:00 <class 'datetime.datetime'>
날짜 속성 추출(dt.month, dt.year, dt.day 등)
df = pd.DataFrame({"date": ["2025-02-01", "2025-03-15", "2025-06-20"]})
df["date"] = pd.to_datetime(df["date"])
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["day"] = df["date"].dt.day
sort
- sort_values(): 특정 열을 기준으로 데이터 정렬
- ascending=True: (default) 오름차순
- ascending=False: 내림차순
df = pd.DataFrame({
"이름": ["철수", "영희", "민수", "수진"],
"국어": [85, 90, 75, 95],
"영어": [80, 70, 95, 85]
})
# 국어 점수 기준 오름차순 정렬
df_sorted = df.sort_values(by="국어")
print(df_sorted)
# 국어 점수 기준 내림차순 정렬
df_sorted_desc = df.sort_values(by="국어", ascending=False)
print(df_sorted_desc)
- sort_index(): 인덱스를 기준으로 정렬
- ascending=True: (default) 오름차순
- ascending=False: 내림차순
# 인덱스를 변경한 후 정렬
df = df.set_index("이름")
# 인덱스(이름) 기준 오름차순 정렬
df_sorted = df.sort_index()
print(df_sorted)
# 인덱스(이름) 기준 내림차순 정렬
df_sorted_desc = df.sort_index(ascending=False)
print(df_sorted_desc)
groupby
- 데이터 프레임을 특정 기준으로 그룹화하여 집계 및 변환
- aggregation: 그룹별 연산
- 집계함수 종류: mean, median, sum, count, min, max
- aggregation: 그룹별 연산
groupby([컬럼1,컬럼2])["값"].(집계함수)
# groupby([컬럼1,컬럼2])["값"].(집계함수)
df = pd.DataFrame({
"부서": ["HR", "HR", "IT", "IT", "Finance", "Finance"],
"성별": ["여", "남", "여", "남", "여", "남"],
"연봉": [5000, 5500, 6000, 7000, 6500, 7500],
"근속년수": [5, 7, 3, 8, 6, 10]
})
# 부서별 연봉 평균
df.groupby("부서")["연봉"].mean() # median, sum, min
# 성별 부서별 평균 연봉
df.groupby(["성별","부서"])["연봉"].mean() # median, sum, min
df.groupby("컬럼")["값"].agg([집계함수1, 집계함수2]) : 복수의 집계함수 연산도 가능
df.groupby(["성별","부서"])["연봉"].agg(["mean", "sum", "max"])
transform
- 그룹 내 개별 값 반환
개별 데이터별 변환을 수행하여 원본 데이터의 개수 유지
df["부서_평균연봉"] = df.groupby("부서")["연봉"].transform("mean")
df
데이터프레임 결합(concat / merge / join)
- concat: 축(Axis) 기준으로 단순히 붙임(행 또는 열)
- axis=0: (default) 아래로 이어 붙임
- axis=1: 옆으로 이어 붙임
df1 = pd.DataFrame({"A": ["A0", "A1"], "B": ["B0", "B1"]})
df2 = pd.DataFrame({"A": ["A2", "A3"], "B": ["B2", "B3"]})
# 행 기준 연결 (axis=0, 기본값)
df_concat0 = pd.concat([df1, df2], ignore_index=True) # ignore_index=True 기존 인덱스 무시
print(df_concat0)
print('-------')
# 열 기준 연결 (axis=1)
df_concat1 = pd.concat([df1, df2], axis=1)
print(df_concat1)
- merge: 공통 키를 기준으로 두 테이블 병합(join과 유사)
- left, inner, right, ...
df_employees = pd.DataFrame({
"직원ID": ["E001", "E002", "E003", "E004"],
"이름": ["김철수", "이영희", "박지성", "손흥민"],
"직급": ["사원", "대리", "과장", "부장"]
})
# 부서 데이터
df_departments = pd.DataFrame({
"직원ID": ["E001", "E002", "E004", "E005"],
"부서": ["영업팀", "마케팅팀", "개발팀", "재무팀"]
})
# ✅ Inner Join (공통 직원ID 기준)
df_inner = pd.merge(df_employees, df_departments, on="직원ID", how="inner")
df_inner
- join: 인덱스 기준으로 병합(기본적으로 left join)
df_employees = pd.DataFrame({
"직원ID": ["E001", "E002", "E003", "E004"],
"이름": ["김철수", "이영희", "박지성", "손흥민"],
"직급": ["사원", "대리", "과장", "부장"]
})
# 부서 데이터
df_departments = pd.DataFrame({
"직원ID": ["E001", "E002", "E004", "E005"],
"부서": ["영업팀", "마케팅팀", "개발팀", "재무팀"]
})
# ✅ Left Join (모든 직원 포함)
df_left = pd.merge(df_employees, df_departments, on="직원ID", how="left")
df_left
비교
메서드 | 사용 목적 | 기준 | SQL 개념 | 결과 크기 |
concat() | 여러 개의 테이블 연결 | 행 또는 열 | UNION ALL | 연결한 만큼 |
merge() | 공통 키 기준 병합 | 지정된 on 키 | JOIN (inner, left, right, outer) | 키에 따라 달라짐 |
join() | 인덱스 기준 병합 | 행의 인덱스 | LEFT JOIN | left 기준 |
챌린지
- Boxplot: 중앙 값, IQR, 이상치를 확인 가능
- 간단한 분포 비교, 이상치 확인
- Vilolin Plot: Boxplot + KDE(분포 밀도)
- 데이터의 밀도 분포를 더 명확하게 시각화 가능
- 단점이 있다면 이상치 확인이 불가능
- 데이터가 많을 수록 뚱뚱해짐
- KDE Plot: 데이터의 분포를 부드럽게 추정한 확률 밀도 함수(PDF)를 시각화
- 히스토그램보다 부드럽고 직관적
- 두 개 이상의 분포 비교할 때 효과적
- 밀도 차이 분석
- 겹치는 부분의 색이 진해져 분포의 유사성을 직관적으로 파악 가능
- fill=True 파라미터로 면적을 채워 가독성 향상
- ECDF Plot(잘 사용하지는 않음): 누적 분포를 시각화
- 분산 및 중앙값 차이 확인
- 데이터가 특정 값 이하일 확률을 누적해서 표시
- 분포의 차이를 누적 확률 관점에서 비교 가능
머신러닝
하이퍼파라미터 튜닝
- 모델이 학습하는 과정에서 스스로 학습할 수 없는, 사람이 직접 설정해야 하는 값
- 여러 개가 서로 상호작용하므로 독립적으로 생각하면 모델의 성능이 떨어질 수 있음
- 각 모델마다 하이퍼파라미터가 다름
- GridSearch: 하이퍼파라미터 조합을 격자 형태로 만들어 탐색
- RandomSearch: 하이퍼파라미터 공간에서 무작위로 값을 추출하여 탐색
교차 검증
- 모델의 일반화 성능을 정확하게 평가하기 위한 방법
- 특정 테스트 데이터에서는 우연히 좋은 성능을 보일 수 있지만
- 이것이 모델의 실제 성능을 대표한다고 보기는 어렵습니다.
- 이러한 문제를 해결하기 위해 교차 검증이 필요
- K-fold Cross Validation: 전체 데이터를 K개의 비슷한 크기의 그룹(fold)으로 나누어 평가
- Stratified K-fold Cross Validation: 각 fold에서 클래스의 비율을 원본 데이터와 동일하게 유지
- K-fold CV를 개선한 버전으로, 특히 분류 문제에서 중요
- 각 fold가 전체 데이터의 분포를 대표
- 편향된 평가를 방지
- 분류 문제에서 더 안정적인 성능 평가가 가능
- 데이터가 불균형할때 유용
- LOOCV: K를 데이터의 개수(총 샘플 수)와 같게 설정한 경우
- K-fold CV의 극단적인 형태
- 마치 각 학생을 한 명씩 테스트하는 것
- 장점
- 거의 모든 데이터를 학습에 사용
- 편향이 적은 평가가 가능
- 단점
- 계산 비용이 매우 높음
- 데이터가 많을 경우 현실적으로 사용이 어려움
- GridSearch ‘CV’& RandomSearch ‘CV’
- 기존 grid search처럼 하이퍼파라미터 조합을 격자 형태로 만들어 탐색하되 각 하이퍼파라미터 조합마다 CV를 수행
- random search처럼 하이퍼파라미터 공간에서 무작위로 값을 추출하여 탐색하되 각 무작위 하이퍼파라미터 조합마다 CV를 수행
군집화
- 비슷한 애들을 묶음
- 핵심
- 같은 그룹 내의 데이터들은 최대한 비슷하게
- 서로 다른 그룹 간의 데이터들은 최대한 다르게
- K-means
- 구현이 간단
- 하지만 초기 중심점 위치에 따라 결과가 달라
- 팀의 개수(K)를 미리 정해야 한다는 제한
- k를 조절하기 위해 엘보우(elbow) 방법 ➡️ 꺾이는 지점이 최적의 군집 수
- 계층적 군집화(Hierarchical Clustering)
- 상향식: 작은 팀에서 시작해 점점 큰 조직 만들어가는 방식
- 하향식: 큰 조직에서 시작해 점점 작은 단위로 나누는 방식
- 실루엣 계수
- 군집화가 얼마나 잘 되었는지 평가하는 방법
- -1에서 1사이의 값으로, 1일 수록 잘된것
- 엘보우 방법
- k를 조절하기 위한 방법
- 꺾이는 지점이 최적의 군집 수
'AI > 머신러닝' 카테고리의 다른 글
머신러닝의 이해와 라이브러리 활용 심화 2주차(의사결정나무, 랜덤포레스트, 최근접이웃, 부스팅알고리즘) (0) | 2025.02.13 |
---|---|
머신러닝의 이해와 라이브러리 활용 심화 1주차(EDA, 전처리, 인코딩, 스케일링, 데이터분리, 교차검증, GridSearch) (0) | 2025.02.13 |
수업[2.4](군집, DBSCAN, PCA) (0) | 2025.02.04 |
머신러닝의 이해와 라이브러리 활용 기초 - 2(로지스틱회귀, 다중로지스틱회귀, 평가) (0) | 2025.01.22 |
머신러닝의 이해와 라이브러리 활용 기초 - 1(선형회귀, 다중선형회귀, 평가) (0) | 2025.01.21 |