[데이터 전처리 & 시각화 by 박성원 튜터]
00. 데이터 분석가란?
1) 데이터 분석가 유형
- 비즈니스 분석가 (Business Analyst, BA)
: 주로 비즈니스 문제를 이해하고 해결하기 위해 데이터를 분석
: 비즈니스 프로세스 및 요구 사항을 파악하고, 데이터 기반으로 의사 결정을 지원
: 주로 업무 프로세스 개선, 비즈니스 모델 분석, 요구 사항 관리 등을 수행
- 프로덕트 분석가 (Product Analyst, PA)
: 제품이나 서비스의 성과를 평가하고 개선하기 위해 데이터를 분석
: 사용자 행동 및 제품 성능과 관련된 데이터를 분석하여 제품 개선에 기여
: 주로 제품 경험과 사용자 행동에 대한 분석을 수행하며, A/B 테스트, 사용자 경로 분석 등을 담당
- BI 분석가
: 기업의 비즈니스 인텔리전스 플랫폼과 도구를 사용하여 데이터를 시각화하고 보고서를 작성
: 주로 기업 내부 데이터를 시각화하고, 이를 통해 의사 결정에 필요한 정보를 제공
: BI 도구 (Tableau, Power BI 등)를 사용하여 대시보드를 구축하고, 데이터 시각화 및 보고서 작성
- 데이터 분석가
: 주로 정형 데이터를 분석하여 기업 의사 결정을 지원
: 데이터베이스, 스프레드시트 등에서 데이터를 추출하고, 이를 정제하여 보고서 및 시각화 생성
: 주로 기술적인 기술이 필요하며, SQL, Excel, 데이터 시각화 등을 활용하여 업무를 수행
- 데이터 사이언티스트
: 주로 데이터를 활용하여 예측, 패턴 발견, 복잡한 분석을 수행하여 비즈니스 문제 해결
: 통계, 머신러닝, 딥러닝 등의 기술과 알고리즘을 사용하여 데이터를 분석하고 모델을 구축
: 데이터 수집, 전처리, 모델링, 평가 및 해석을 포함한 A to Z 데이터 분석 작업을 수행
2) 데이터 전처리와 시각화가 필요한 이유
- 데이터의 목적은 결국 설득!
: 설득을 잘 하기 위해서는 데이터를 잘 전달해야 하고, 이를 위해 '시각화'가 필요한 것
- 데이터 전처리와 시각화는 목적이 중요!
: 데이저 전처리는 데이터를 전달하기 위한 목적성이 필수이며, 목적성이 있을 때 데이터 전달의 효과성이 증가
: 데이터를 어떤 목적을 가지고, 어떻게 분석할 것인가 미리 설계가 필요함
(분석 설계 예시)
① 목표 설정하기: 무엇을 위해 데이터 전처리와 시각화가 필요한가?
② 예상 산출물 정의하기: 데이터 처리 및 시각화를 통한 예상 결과물은 무엇인가?
③ As-is vs. To-be 생각하기: 현재 문제 상황이 무엇이고, 어떻게 개선할 것인지 생각하며 분석 방향성을 설정하기
(연습하기)
- https://dataitgirls2.github.io/10minutes2pandas/
- https://pandas.pydata.org/pandas-docs/stable/user_guide/10min.html
01. 데이터 전처리(Pandas)
0) 데이터 전처리란?
- 원하는 데이터를 보기 위해 하는 모든 활동
- 데이터 전처리는 달성하고자 하는 목표가 무엇인지와 같은 방향성이 꼭 있어야 함
(cf) Excel vs Pandas
[Pandas]
- 대규모 데이터셋 및 복잡한 작업 처리에 효과적
- 자동화와 프로그래밍 기능을 통해 더 많은 유연성과 확장성 제공
[엑셀]
- 상대적으로 작은 규모의 데이터나 간단한 작업에 유용
- 비전문가가 쉽게 사용할 수 있는 직관적인 인터페이스 제공
1. 자동화와 프로그래밍 기능
· Pandas: 다양한 라이브러리를 사용한 데이터 불러오기, 변환, 분석이 가능해 반복적이고 복잡한 작업 자동화 가능
· 엑셀: 주로 수동으로 작업이 수행되며, 고급 기능을 프로그래밍적으로 확장하기가 어려움
2. 대용량 데이터 처리
· Pandas: 대용량 데이터 처리에 유용. 메모리 내 데이터 처리 및 데이터 세트 조각으로 나누어 처리하는 기능 제공
· 엑셀: 상대적으로 작은 데이터 처리에 적합. 큰 데이터는 처리 속도 저하나 용량 제한 등 제약이 생기기도 함
3. 복잡한 데이터 처리 및 분석
· Pandas: 다양한 도구와 라이브러리를 활용해 복잡한 데이터 작업, 통계 분석, 머신러닝 모델 구축 등 가능
· 엑셀: 기본적인 수식과 함수를 통해 데이터 처리 및 시각화 가능하나 복잡한 데이터 조작이나 분석엔 제약이 있음
4. 확장성과 유연성
· Pandas: 다양한 데이터 포맷 처리나 데이터베이스 연동 작업 등 유연성이 높음
· 엑셀: 주로 특정 데이터 형식의 파일(.xlsx, .csv 등)을 다루는 데에 제한
5. 버전 관리 및 자동화
· Pandas: 버전 관리 시스템으로 Python 코드 변경 내역을 관리하고, 코드 주석을 활용해 작업 히스토리 추적 가능
· 엑셀: 사용자가 직접 수정하기 때문에 변경 사항을 추적하거나 문서화하기 어려움
1) Pandas란?
- 기본 개념: Python에서 데이터를 조작하고 쉽게 분석할 수 있게 도와주는 라이브러리
- Pandas의 구조
- Series = index + values
└ 하나의 속성을 가진 데이터 집합 (DataFrame 표에서 열(column) 1줄이라고 생각하면 쉬움)
- DataFrame = index + column
└ 컬럼이 2개 이상 있는 표 형태의 데이터 집합
└ index: 각 아이템을 특정할 수 있는 고유의 값 (엑셀에서는 좌측 열순서로 생각하면됨)
└ columns: 하나의 속성을 가진 데이터 집합
2) 데이터 불러오기/저장하기
① 데이터 불러오기
# 엑셀 불러오기
pd.read_excel('파일경로/파일명.xlsx')
# csv 파일 불러오기
pd.read_csv('파일경로/파일명.csv')
#파일이 깨져서 불러와진다면? 인코딩 방식 지정이 필요할 때도
data = pd.read_csv('file.csv', encoding='utf-8')
data = pd.read_csv('file.csv', encoding='ascii')
▶ 인덱스(Index)
- 의미: 데이터프레임(DataFrame) 또는 시리즈(Series)의 각 행 또는 각 요소에 대한 식별자
└ 기본적으로 0부터 시작하는 숫자로 자동 지정되나 임의로 문자 형태로 적용도 가능
└ 처음 파일 불러올 때 인덱스를 지정하거나 제외하는 것도 가능함
- 인덱스 특징
(1) 고유성(Uniqueness): 각 행은 유일한 인덱스 값을 가지며, 중복된 값을 가질 수 없음
(2) 불변성(Immutability): 한 번 생성된 인덱스는 변경(수정) 할 수 없으며, 새로운 값을 할당해 기존 인덱스 대체 가능
(3) 조작 및 탐색(Manipulation and Retrieval): 인덱스로 데이터프레임 또는 시리즈의 특정 행을 선택 및 탐색 가능
(4) 정렬(Sorting): 인덱스를 기준으로 데이터프레임 또는 시리즈의 행 정렬 가능
- 인덱스 예시
(1) 기본 인덱스: 각 행은 유일한 인덱스 값을 가지며, 중복된 값을 가질 수 없음
(2) 사용자 지정 인덱스: 사용자가 직접 인덱스를 설정
-- (1) 기본 인덱스: Pandas는 0부터 시작하는 정수 인덱스 자동 생성
# 기본 정수 인덱스를 가진 데이터프레임 생성
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'c']})
-- (2) 사용자 지정 인덱스: 사용자가 직접 인덱스 설정
# 직접 인덱스를 설정한 데이터프레임 생성
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'c']}, index=['idx1', 'idx2', 'idx3'])
#리스트 형태를 활용해서 인덱스 생성
df.index = ['1번' , '2번' , '3번']
- 인덱스 활용
#인덱스 확인하기
data.index
# 특정 인덱스 행에 접근
row = df.loc['idx2']
# 인덱스를 기준으로 데이터프레임 정렬
sorted_df = df.sort_index()
# 특정 칼럼 > 인덱스로 변경
data = df.set_index('컬럼명')
# 파일 불러올때 특정 칼럼을 인덱스로 지정하기
pd.read_csv('./data/file.csv' , index_col = '컬럼정보')
pd.read_csv('./data/file.csv' , index_col = 0) # 0부터 시작
# 인덱스 > 칼럼으로 변경 (0부터 시작하는 정수로)
data.reset_index()
# reset_index() 기본 값은 drop = False로 현재 인덱스값 > 칼럼으로 초기화
# reset_index(drop = True) 현재 인덱스는 칼럼으로 변경 안되고(사라지고) 정수 인덱스로 초기화
▶ 컬럼(Column)
- 의미: 행과 열로 구성된 데이터프레임의 열(또는 변수)에 해당. 각 열은 서로 다른 종류의 데이터를 담고 있음
- 컬럼의 특징
(1) 고유한 이름(라벨)을 가지고 있어, 해당 컬럼 데이터를 식별하는 데 사용
(2) 시리즈(Series) 객체로 구성되어 있으며, 시리즈는 동일한 데이터 유형을 가진 1차원 배열과 유사함
(3) 숫자, 문자열, 날짜 등 다양한 데이터 유형 중 특정한 유형의 데이터를 포함하며 경우에 따라 유형 변경 가능
- 컬럼 활용
#컬럼 확인하기
data.column
#파일 불러올 때 컬럼명 변경하기
pd.read_csv('./data/file.csv' , names = [’컬럼명1’, ‘컬럼명2’, … ,‘컬럼명 19’])
#리스트 형태로 컬럼명을 변경하기
data.column = ['축구', '농구', '배구', '야구']
② 데이터 저장하기
df = 데이터프레임 # 저장하고 싶은 데이터
df.to_csv('파일경로/파일명.csv', index = False)
3) 데이터 확인
① 데이터 확인
▶.head() : 데이터를 N개 행까지 보여줌
▶.Info() : 데이터의 정보를 한 눈에 파악(인덱스, 컬럼명, 컬럼의 데이터 개수, 데이터 타입 등). null 값 파악에 용이
└ 결측치(null) 여부, 데이터 타입이 적절한지 등 체크 필요
▶.describe() : 숫자 데이터에 대한 기초통계량 확인(개수, 평균, 표준편차, 사분위, 중앙값 등)
└ 목적에 따라 필요한 통계치도 미리 확인 필요
② 데이터 타입 변경
▶ 데이터 타입 종류
데이터 타입(Data Type) | 함수 명칭 | 설명(Description) | 예시(Example) |
int64, int32 | int | 정수형 데이터 (64비트 또는 32비트) | 1, 42, -10, 1000 |
float64, float32 | float | 부동 소수점 수 (64비트 또는 32비트) | 3.14, -0.001, 2.718 |
object | str | 문자열 데이터 (일반적으로 문자열) | 'Hello', 'Data Science' |
bool | bool | 불리언(참/거짓) 데이터 | True, False |
datetime64 | datetime | 날짜와 시간 데이터 | '2023-12-31 08:00:00' |
timedelta64 | timedelta | 시간 간격(두 날짜 또는 시간 사이의 차이) 데이터 | '3 days', '2 hours' |
category | 'category' | 카테고리형 데이터 (제한된 고유 값으로 구성) | 'Red', 'Blue', 'Green' |
▶ astype() : Pandas 데이터프레임의 열 데이터 타입을 원하는 형식으로 변환 할 수 있는 메소드
#부동소수점 타입으로 변환
df['column'] = df['column'].astype(float)
# 문자열 타입으로 변환
df['column'] = df['column'].astype(str)
4) 데이터 선택
① 데이터 슬라이싱(lioc, loc)
▶ .iloc[행번호(로우),열번호(컬럼)] : 정수 형태의 행과 칼럼 번호로 선택
* iloc로 범위 지정 시 [x:n,x:n] 에서 x는 행과 열의 위치 시작값이고, n은 0부터 시작해서 마지막값으로 이해
#한 개의 데이터 선택
data.iloc[0,2] # 인덱스 0의 행과 2의 열 값 선택
#특정 행과 열 선택
df.iloc[1:4, 0:2] # 인덱스 1부터 3까지의 행과 0부터 1까지의 열 선택
▶ .iloc[행이름(로우),열이름(컬럼)] : 문자 형태의 행과 칼럼 이름으로 선택
#한 개의 컬럼 선택
data.loc[: , '컬럼명'] #특정 열 데이터 선택
data['컬럼명'] #data.loc[: , '컬럼명']와 동일한 결과값
data[ ['컬럼명3', '컬럼명1', '컬럼명2' ] ] #원하는 순서로 다수 칼럼 지정 가능
#특정 행과 열 선택
#2개 컬럼명을 선택할 경우
data.loc[ '행이름' , ['컬럼명1' , '컬럼명2'] ]
# 2개 행이름을 선택할 경우
data.loc[ ['행이름1', '행이름2'] , '컬럼명1' ]
# 리스트 슬라이싱 : 을 활용해서 특정 범위를 지정하여 선택할 수 있습니다.
data.loc[ '행이름' , '컬럼명1' : ] #'컬럼명1' : ==> 컬럼명1부터 끝까지
② 조건에 따른 데이터 선택 (Boolean Indexing)
▶ Boolean Indexing이란?
- 조건을 이용해 데이터프레임에서 특정 조건을 만족하는 행을 필터링 및 추출하는 방법
- 주로 불리언(Boolean) 값을 가지는 조건식을 사용하여 데이터프레임을 인덱싱하는 방법
└ 조건식에 따라 각 행이 True 또는 False로 평가되며 이를 바탕으로 데이터프레임을 필터링
▶ Boolean Indexing 사용 방법
# 1. 단일 조건으로 필터링: 열의 값을 특정 기준으로 필터링
# 'age' 열에서 30세 이상인 행 필터링
df[df['age'] >= 30]
#조건을 통해 True/False가 된 값에서 True에 해당하는 값만 반환
condition = data['컬럼명1'] < 80
# 2. 여러 조건으로 필터링: 여러 개의 조건을 조합하여 복합적으로 필터링
# 'age' 열에서 30세 이상이면서(and) 'gender' 열이 'Male'인 행 필터링
# 각 조건에 () 소괄호 추가
df[(df['age'] >= 30) & (df['gender'] == 'Male')]
#조건을 변수로 만들어서 간결하게 활용도 가능
condition1 = df['age'] >= 30
condition2 = df['gender'] == 'Male'
condition = condition1 & condition2 #and
condition = condition1 \ condition2 #or
# 3. 조건에 따른 특정 컬럼 필터링: 조건을 만족하는 특정 열만 선택
# 'age' 열에서 30세 이상인 경우의 'name' 열만 선택
df.loc[df['age'] >= 30, 'name']
# 4. isin()을 활용한 필터링: 리스트를 활용해 여러 값들을 포함하는 행 필터링
# 'gender' 열에서 'Male' 또는 'Female'인 행 필터링
df[df['gender'].isin(['Male', 'Female'])]
▶ isin() 매소드
- Series(시리즈)나 DataFrame(데이터프레임)의 값들 중에서 특정 값이나 리스트 안에 포함된 값들을 찾아내는 메소드.
- 원하는 조건에 해당하는 데이터를 빠르게 필터링하거나 선택할 수 있음
# 1. 단일 값 포함 여부 확인
# 'B' 열에서 'banana' 값이 있는지 확인
result = df['B'].isin(['banana'])
# 2. 여러 값 포함 여부 확인
# 'A' 열에서 2 또는 4 값을 포함하는 행 찾기
result = df['A'].isin([2, 4])
# 3. 데이터프레임 전체에서 사용
# 데이터프레임 전체에서 여러 조건을 확인하여 필터링
result = df.isin({'A': [1, 3], 'B': ['apple', 'orange']})
(cf) 줄바꿈이 필요하다면?
#역슬래시(\) + Enter로 줄바꿈 가능
condition = (data['컬럼명1'] < 80) \
& (data['컬럼명2'] >= 50)\
& (data['컬럼명3'] >= 10)
③ 데이터 추가
df = pd.DataFrame()
# 신규 칼럼 추가
df['컬럼명'] = data
# 리스트 형태로 컬럼값 추가
df['KFC_menu'] = ["치킨"] # 칼럼값이 1개면 전체 칼럼에 1개의 값이 전체 적용
df['KFC'] = [50, 10, 30] # 행 수에 맞춰 입력 필요 (입력 순서대로 들어감)
# 여러 조건 및 계산식을 통한 산출 값으로 칼럼 추가
df['ABC'] = (df['EPL'] + df['NBA']) * df['MLS'] * 2
5) 데이터 병합
① concat
- pd.concat() 과 같이 사용
- concat()함수는 데이터프레임을 위아래로 혹은 좌우로 연결
└ axis: 연결하려는 축(방향) 지정. 기본값 axis = 0은 위아래(행)로 연결, axis = 1로 별도 설정하면 좌우(열)로 연결
└ ignore_index:기본값은 False로 기존 인덱스 유지. True하면 기존 인덱스를 무시하고 새로 인덱스 설정
# 두 개의 데이터프레임 생성
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2']})
df2 = pd.DataFrame({'A': ['A3', 'A4', 'A5'], 'B': ['B3', 'B4', 'B5']})
# 위아래로 데이터프레임 연결
result_vertical = pd.concat([df1, df2], axis=0)
# 좌우로 데이터프레임 연결
result_horizontal = pd.concat([df1, df2], axis=1)
print("위아래 연결 결과:\n", result_vertical)
print("\n좌우 연결 결과:\n", result_horizontal)
② merge
- pd.merge() 와 같이 사용
- 주로 두 개 이상의 데이터프레임에서 공통된 열이나 인덱스 기준으로 데이터를 좌우 병합할 때 활용
- 주요 매개 변수
└ left와 right: 병합할 데이터프레임 중 병합 기준이 왼쪽(left)과 오른쪽(right). 생략 시 left, right 순으로 병합
└ on: 병합 기준이 되는 열 이름(혹은 열 이름의 리스트) 지정
· left_on과 right_on: 왼쪽 데이터프레임과 오른쪽 데이터프레임에서 병합할 열 이름이 다른 경우 사용
└ how
· inner: 공통된 키(열)를 기준으로 교집합
· outer: 공통된 키(열)를 기준으로 합집합
· left: 왼쪽 데이터프레임의 모든 행을 포함하고, 오른쪽 데이터프레임은 공통된 키에 해당하는 행만 포함
· right: 오른쪽 데이터프레임의 모든 행을 포함하고, 왼쪽 데이터프레임은 공통된 키에 해당하는 행만 포함
# 'key' 열을 기준으로 두 데이터프레임 병합
merged_df = pd.merge(left_df, right_df, on='key', how='inner')
6) 데이터 집계
① Group by
- 데이터프레임.groupby('컬럼명').집계함수() 와 같이 사용
- 데이터프레임을 그룹화하고, 그룹 단위로 데이터를 분할(split), 적용(apply), 결합(combine)하는 기능 제공
- 특정 기준에 따라 데이터프레임을 그룹으로 나누어 집계, 변환, 필터링 등을 하고 새로운 데이터프레임 생성
└ 그룹 생성: 기준 열(혹은 열들)을 지정하여 데이터프레임을 그룹으로 분할
└ 그룹에 대한 연산 수행: 그룹 단위로 원하는 연산(평균, 합, 개수 등)을 수행
└ 결과 결합: 각 그룹의 연산 결과를 하나의 데이터프레임으로 결합하여 새로운 데이터프레임을 생성
df = pd.DataFrame(data)
#하나의 열 기준으로 집계 함수 활용
grouped = df.groupby('Category').mean()
grouped_max = df.groupby('Category').max()
#복수의 열 기준으로 집계 함수 활용
grouped_multiple = df.groupby(['Category', 'SubCategory']).sum()
#복수의 열 기준으로 복수의 집계 함수 활용
#agg() 함수로 여러 집계 함수 적용 가능
grouped_multiple = df.groupby(['Category', 'SubCategory']).agg({'Value1': ['mean', 'sum'], 'Value2': 'sum'})
② Pivot Table
- pivot_table(): 함수는 데이터프레임에서 피벗 테이블*을 생성하는 데 사용
* Pivot Table란? 데이터를 재구성하여 요약, 집계된 정보를 보기 쉽게 보여주는 테이블 형태
# 샘플 데이터프레임 생성
data = {
'Date': ['2023-01-01', '2023-01-01', '2023-01-02', '2023-01-02', '2023-01-01'],
'Category': ['A', 'B', 'A', 'B', 'A'],
'Value1': [10, 20, 30, 40, 50],
'Value2': [100, 200, 300, 400, 500]
}
df = pd.DataFrame(data)
# 피벗 테이블 생성
# aggfunc 포함 모든 변수 넣을 때 작은 따옴표 추가
# 하나의 열 기준으로 피벗 테이블 생성
# 날짜를 행 인덱스로, 카테고리를 열 인덱스로, 값은 'Value1'의 합으로 집계
pivot = df.pivot_table(index='Date', columns='Category', values='Value1', aggfunc='sum')
# 여러 열 기준으로 피벗 테이블 생성
# 'Date'를 행 인덱스로, 'Category'와 'SubCategory'를 열 인덱스로, 값은 'Value1'의 합으로 집계
pivot = df.pivot_table(index='Date', columns=['Category', 'SubCategory'], values='Value1', aggfunc='sum')
# 집계 함수를 다르게 적용하여 피벗 테이블 생성
pivot = df.pivot_table(index='Date', columns='Category', values=['Value1', 'Value2'], aggfunc={'Value1': 'mean', 'Value2': 'sum'})
③ 데이터 정렬하기
▶ sort_values() 함수: 컬럼 기준으로 정렬
▶ sort_index() 함수: 인덱스를 기준으로 정렬
df = pd.DataFrame(data)
# sort_values: 'Score' 열 기준
sorted_by_score = df.sort_values('Score') #오름차순
sorted_by_score = df.sort_values('Score',ascending=False) #내림차순
# sort_index: 인덱스 기준
sorted_by_index = df.sort_index() #오름차순
sorted_by_index = df.sort_index(ascending=False) #내림차순
7) 기타: pickle
▶ pickle 활용하기
- python 의 변수, 함수, 객체를 binary형태 파일로 저장하고 불러올 수 있는 라이브러리
- list, dictionary 등을 파일 그대로 저장하면 용량이 매우 커지는데 pickle을 사용 시 용량 감소(binary 역할)
- 추가적으로 gzip을 이용하여 pickle로 저장된 데이터 압축 가능
: pandas에서는`to_pickle()`및`read_pickle()` 메서드를 통해 `pickle`을 사용할 수 있음
- 머신러닝 모델 등을 저장하고 불러올 때도 활용
df = pd.DataFrame(data)
# 데이터프레임을 pickle 파일로 저장
df.to_pickle('파일명.pkl')
# pickle 파일에서 데이터프레임 불러오기
loaded_df = pd.read_pickle('파일명.pkl')
[실습하기]
1) iris 데이터셋 활용 전처리
import seaborn as sns
# 데이터셋 불러오기
iris_data = sns.load_dataset('iris')
# Q1. 'species' 열 값이 'setosa'인 데이터 선택하기
#내정답 #isin 쓴 건 데이터프레임[리스트]로 넣어줘야 함
setosa_data = iris_data[iris_data['species'].isin(['setosa'])]
#정답코드 #loc 활용. == 으로 조건을 걸고 loc로 추출 가능
setosa_data = iris_data.loc[iris_data['species'] == 'setosa']
# Q2. 10부터 20까지의 행과 1부터 3까지의 열 선택하기
select_data = iris_data.iloc[10:21, 1:4] #n까지 행에 +1 더하기
2) tip 데이터셋 활용 전처리
## tip 데이터셋 활용 전처리
import pandas as pd
import seaborn as sns
# 데이터셋 불러오기
tips_data = sns.load_dataset('tips')
tips_data
# Q1. total_bill이 30 이상인 데이터만 선택하기
high_bill = tips_data.loc[tips_data['total_bill'] >= 30] #.loc는 빼도 무방
high_bill
# Q2. 성별('sex')을 기준으로 데이터 그룹화하여 팁(tip)의 평균 계산
tip_by_gender = tips_data.groupby('sex')['tip'].mean()
# tip_by_gender = tips_data.groupby('sex').agg({'tip': ['mean']})
tip_by_gender
# Q3. 'day'와 'time'을 기준으로 데이터 그룹화하여 전체 지불 금액(total_bill)의 합 계산
bill_by_dayntime = tips_data.groupby(['day', 'time'])['total_bill'].sum()
# bill_by_dayntime = tips_data.groupby(['day', 'time']).agg({'total_bill': ['sum']})
bill_by_dayntime
# Q4. 'day' 열 기준 각 요일별 팁(tip)의 평균을 새로운 데이터프레임으로 만든 후,
#이를 기존의 'tips' 데이터셋에 병합
tip_by_day = tips_data.groupby('day')['tip'].mean().reset_index() #인덱스 추가
tip_by_day.columns = ['day', 'avg_tips'] #칼럼명 변경
tip_by_day
merged_df = pd.merge(tips_data, tip_by_day, on = 'day', how = 'inner')
merged_df
02. 데이터 시각화(Matplotlib)
1) 데이터 시각화의 목적
① 패턴 발견 및 이해
: 데이터의 특징을 시각적으로 파악해 데이터 내 숨겨진 패턴을 발견하고, 이해하는 데 도움을 줌
② 의사 결정 지원
: 시각화로 정보를 명확하게 전달해 복잡한 데이터를 이해하고 의사 결정을 내리는 데 도움을 줌
③ 효과적인 커뮤니케이션
: 데이터 분석 결과를 다른 사람들과 공유하거나 설명할 때 유용. 시각적으로 보여주면 이해나 기억이 쉬움
(cf) 목적에 맞는 시각화 유형
- 시간에 따른 매출 추이 분석, 마케팅 캠페인 효과 분석: 선 그래프
- 제품 카테고리별 매출 분석, 캠페인 채널별 효과 비교: 막대 그래프, 원형 차트
- 고객 구매 패턴 분석, 고객 반응 분석: 히스토그램, 상자 그림(Box Plot)
- 지역별 매출 비교 분석: 지도 이용한 히트맵
2) Matplotlib 알아보기
- Matplotlib이란?
: 파이썬에서 다양한 종류의 그래프 생성에 필요한 도구를 제공하는 시각화를 위한 라이브러리
: 선/막대 그래프, 히스토그램, 산점도, 파이 차트 등 다양한 시각화 방식 지원(주로 2D 그래픽)
: 그래프를 색상, 스타일, 레이블, 축 범위 등을 조절하여 원하는 형태로 시각화 가능
- matplotlib.pyplot : import 라이브러리 이름.
└ plot() 함수: pyplot 인터페이스에서 2차원 데이터를 시각화하기 위해 사용
└ matplotlib은 사용 문법이 2종류 하기 내용 참고
① pyplot 인터페이스: 단순한 그래프 또는 임시적인 데이터 시각화에 적합
② 객체지향 인터페이스: 복잡한 그래프, 여러 서브플롯, 세밀한 조정이 필요할 때 적합
3) 그래프 그리기 - 도구
▶ 기본 그래프 그리기
import pandas as pd
import matplotlib.pyplot as plt
# 샘플 데이터프레임 생성
data = {
'A': [1, 2, 3, 4, 5],
'B': [5, 4, 3, 2, 1]
}
df = pd.DataFrame(data)
# 선그래프 그리기
ax = df.plot(x='A', y='B')
# 그래프 사이즈 설정
plt.figure(figsize=(8, 6)) # 가로 8인치, 세로 6인치
#안 먹히면 이걸 넣어야 한다고 함
fig, ax = plt.subplots(figsize=(8,6))
# 범례 추가하기
ax.legend(['Data Series'])
# 그래프 및 축 이름 설정
ax.set_xlabel('X-axis Label')
ax.set_ylabel('Y-axis Label')
ax.set_title('Title of the Plot')
# 데이터 레이블 설정
ax.text(3, 3, 'Some Text', fontsize=12) #3, 3 위치에 텍스트 삽입
# 그래프 출력
plt.show()
▶ 스타일 설정하기
- color= : 색상값. 'blue', 'green'와 같이 기본 색상 이름을 문자열로 넣거나 RGB 값을 직접 지정도 가능
- Linestyle= : 선 스타일. '-'(실선), '--'(대시선), ':'(점선), '-.'(점-대시선) 등으로 지정
- marker = : 선 그래프 내 표식. 'o'(원), '^'(삼각형), 's'(사각형), '+'(플러스), 'x'(엑스) 등 다양한 기호로 지정
- label = : legend 대신 label로 범례 입력 가능
#예시
plt.plot(x, y, color='green', linestyle='--', marker='o', label='Data Series')
* matplotlib 공식 문서 참조
- Line API: https://matplotlib.org/stable/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D
- Marker API: https://matplotlib.org/stable/api/markers_api.html
- Line Styles: https://matplotlib.org/stable/gallery/lines_bars_and_markers/line_styles_reference.html
4) 그래프 그리기 - 차트
▶ 그래프 자료 유형
그래프 유형 | 자료 유형 | 특징 |
Line Plot | 연속형 데이터 | 데이터의 변화 및 추이를 시각화 (시계열에 따른 추이 확인에 용이) |
Bar Plot | 범주형 데이터 | 카테고리(범주) 별 값의 크기를 시각적으로 비교 |
Histogram | 연속형 데이터 | 데이터 분포, 빈도, 패턴 등을 이해 |
Pie Chart | 범주형 데이터의 비율 | 범주별 상대적 비율을 부채꼴 모양으로 시각화 |
Box Plot | 연속형 데이터의 분포 | 중앙값, 사분위수, 최솟값, 최값, 이상치 등 통계적 수치 확인 |
Scatter Plot | 두 변수 간 관계 | 변수 간의 관계, 군집, 이상치 등 확인 |
① Line Plot
- 선 그래프는 데이터 간의 연속적인 관계(추이)를 시각화하는 데에 적합. 주로 시간에 흐름에 따른 데이터 변화, 추세 등
import pandas as pd
import matplotlib.pyplot as plt
# 데이터프레임 생성
data = {'날짜': ['2023-01-01', '2023-01-02', '2023-01-03'],
'값': [10, 15, 8]}
df = pd.DataFrame(data)
# '날짜'를 날짜 형식으로 변환
df['날짜'] = pd.to_datetime(df['날짜'])
# 선 그래프 작성
plt.plot(df['날짜'], df['값'])
plt.xlabel('날짜')
plt.ylabel('값')
plt.title('선 그래프 예시')
plt.show()
(예시)
② Bar Plot vs. Histogram
- 막대 그래프는 각 막대 값의 크기를 통해 범주형 데이터 간(카테고리별) 크기를 비교하는데 효과적
- 히스토그램은 연속형 데이터의 분포를 시각화하여 데이터의 빈도나 분포, 패턴을 이해하는 데 사용
# 막대 그래프
df = pd.DataFrame(data)
plt.bar(df['도시'], df['인구'])
plt.xlabel('도시')
plt.ylabel('인구')
plt.title('막대 그래프 예시')
plt.show()
# 히스토그램
data = np.random.randn(1000) #랜덤데이터
plt.hist(data, bins=30)
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.title('Histogram')
plt.show()
(예시)
③ Pie Chart
- 원 그래프는 전체에서 각 부분의 상대적 비율을 시각화하며, 주로 카테고리별 비율을 비교할 때 사용
import matplotlib.pyplot as plt
# 데이터 생성
sizes = [30, 20, 25, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']
# 원 그래프 그리기
plt.pie(sizes, labels=labels, autopct='%1.1f%%')
plt.title('Pie Chart')
plt.show()
(예시)
④ Box Plot
- 박스 플롯은 연속형 데이터의 분포와 이상치를 시각화하고, 중앙값, 사분위수, 최솟/최댓값 등 통계적 특성 파악에 용이
- 박스 플롯의 활용
└ 데이터의 분포와 중앙값, 이상치 등 통계적으로 중요한 데이터 특성을 시각적으로 표현할 때 사용
└ 다수의 그룹 또는 범주 간의 데이터 분포 비교에 유용
- 박스 플롯의 구성 요소
(1) 상자(Box)
: 데이터의 중앙값과 사분위수(25%와 75%)를 표현
: 상자 중앙에 위치한 선 = 중앙값, 상자 아래쪽 끝 = 25%의 값(1사분위수), 상자의 윗쪽 끝 = 75%의 값(3사분위수)
(2) 수염(Whisker)
: 상자의 위 아래로 연장되는 선으로, 수염의 끝은 최솟값과 최댓값
: 일반적으로 1.5배의 사분위 범위로 계산하며, 이 범위를 넘어가면 이상치(outlier)로 간주
(3) 이상치(Outliers)
: 일반적인 범위를 벗어나는 값들을 의미
: 수염을 벗어나는 개별 데이터 포인트로 박스 플롯에서 독립적으로 표시
import matplotlib.pyplot as plt
import numpy as np
# 데이터 생성
np.random.seed(10)
data = [np.random.normal(0, std, 100) for std in range(1, 4)]
# 박스 플롯 그리기
plt.boxplot(data)
plt.xlabel('Data')
plt.ylabel('Value')
plt.title('Box Plot')
plt.show()
(예시)
(cf) 간단한 통계 용어 설명
- 중앙값(Median)
└ 데이터를 크기 순서대로 나열했을 때, 정확히 중간에 위치한 값
· 홀수일 경우, 작은 것부터 나열한 데이터에서 정확히 가운데에 위치한 값 {3, 6, 7, 12, 14}에서 중앙값은 7
· 짝수일 경우, 작은 것부터 나열한 데이터에서 가운데 2개의 평균 값 {3, 6, 7, 12, 14, 16} 에서 중앙값은 9.5
└ 데이터의 중심 경향을 나타내는 하나의 지표로 사용
└ 이상치에 대해 덜 민감하며, 데이터의 대표값을 파악하는 데 사용
- 사분위수(quartiles)
└ 데이터를 4등분한 지점으로, 크기 순서대로 정렬했을 때, 25%, 50%, 75%에 해당하는 위치의 값
· 1사분위수(First Quartile, Q1): 데이터의 하위 25%에 해당하는 값
· 2사분위수(Second Quartile, Q2): 데이터의 50% 위치로 중앙값(median)에 해당하는 값
· 3사분위수(Third Quartile, Q3): 데이터의 상위 25%(크기 순으로 75%)에 해당하는 값
└ 데이터의 분포를 더 자세히 이해하고 데이터 집합 특성 파악 및 이상치 감지에 유용
- 이상치(outlier)
└ 데이터 집합의 패턴에서 극단적으로 크거나 작은 값을 갖는 데이터 포인트
└ 통계 분석이나 데이터 시각화 과정에서 정확성을 해치거나 모델 성능을 왜곡시킬 수 있어 이상치 식별 및 처리가 중요
└ Box Plot이나 Histogram 등을 활용해 시각적으로 확인하거나 통계적 방법과 도메인 지식을 활용해 이상지 탐지 및 처리
└ 이상치는 종종 실수, 실험 오류, 데이터 수집 과정에서 발생한 문제 등으로 인해 나타남
⑤ Scatter Plot
- 산점도는 두 변수 간의 관계를 점으로 표시한 그래프로, 점들의 분포를 시각적으로 확인 가능
- 두 변수 간의 상관 관계를 보여주며, 변수 간의 관계, 군집, 이상치를 확인하고자 할 때 유용
import matplotlib.pyplot as plt
# 데이터 생성
x = [1, 2, 3, 4, 5]
y = [2, 3, 5, 7, 11]
# 산점도 그리기
plt.scatter(x, y)
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.title('Scatter Plot')
plt.show()
▶ 상관관계
- 해석하기
(분포 모양 및 방향)
└ 양의 상관관계: 오른쪽 위 방향으로 일직선 분포. 한 변수가 증가하면 다른 변수도 증가하는 경향성을 보임
└ 음의 상관관계: 왼쪽 위 방향으로 일직선 분포. 한 변수가 증가하면 다른 변수는 감소하는 경향성을 보임
└ 무상관 관계: 점이 경향성 없이 무작위로 퍼져 있는 분포. 두 변수 간에는 상관관계가 거의 없는 것으로 봄
(분포 강도 )
└ 점들의 모임: 점들이 더 밀집된 곳은 상관관계가 강할 가능성이 높음
└ 점들의 방향성: 일직선에 가까운 분포일수록 상관관계가 강할 가능성이 높음
└ 상관계수 계산: 피어슨 상관계수와 같은 통계적 방법을 사용하여 상관관계를 수치적으로 계산 가능
▶ 피어슨 상관계수(Pearson correlation coefficient)란?
- 두 변수 간의 선형적인 관계를 측정하기 위한 통계적인 방법 중 하나
- 주로 연속형 변수들 간의 상관관계를 평가하는 데 사용
- 피어슨 상관계수의 특징
└ 범위: -1에서 1 사이의 값
└ 양의 상관관계: 1에 가까울수록 강한 양의 선형관계. A가 증가하면 B도 증가
└ 음의 상관관계: -1에 가까울수록 강한 음의 선형관계. A가 증가하면 B는 감소
└ 무상관 관계: 0에 가까울수록 선형관계가 거의 없거나 약한 관계
└ 피어슨 상관계수는 공분산을 각 변수의 표준편차로 나누어 정규화한 값으로, 두 변수 간의 선형적 관계 정도를 측정
└ 변수 간의 비선형적 관계는 표현이 어려울 수 있고, 이상치에도 영향을 받음
[!] 상관이 있다고 해서 인과 관계가 있는 것은 아님. A가 증가하면 B가 증가하는 것이 A 때문은 아님.
(cf) 간단한 통계 용어 설명
- 표준편차(standard deviation)
└ 데이터의 분산 정도를 나타내는 측정 지표 중 하나로 데이터가 평균으로부터 얼마나 퍼져 있는지를 보여줌
└ 표준편차가 작을수록 각 데이터가 평균 주변에 모여있고, 표준편차가 클수록 각 데이터가 평균에서 멀리 퍼져있음
- 공분산(covariance)
└ 두 변수의 변화 패턴이 함께 일어나는 정도를 측정하는 통계적 측정 지표
└ 공분산이 양수면 변수X와Y는 함께 증가 또는 감소하는 경향이 있고, 음수면 한 변수가 증가 시 다른 변수는 감소 경향
└ 공분산 값 자체만으로는 두 변수 간의 관계의 강도나 방향은 알기 어려워, 상관계수를 활용해 관계를 명확히 파악
- 정규화(normalization)
└ 데이터의 스케일(scale)을 조정하여 특정 범위나 규격에 맞추는 과정
└ 정규화의 장점
· 데이터 스케일 조정: 서로 다른 범위에 있는 데이터를 특정 범위로 조정해 알고리즘의 데이터 처리를 도움
· 이상치 영향 완화: 정규화를 통해 이상치의 영향 감소
· 알고리즘의 수렴성 향상: 몇몇 머신 러닝 알고리즘은 데이터가 정규화되어 있을 때 수렴 속도 개선
'TIL' 카테고리의 다른 글
[240130] SQL: 코드카타 117 & 파이썬: 코드카타 27 (0) | 2024.01.30 |
---|---|
[240129] SQL: 코드카타 116 & 파이썬: 코드카타 25~26 (1) | 2024.01.29 |
[240125] SQL: 코드카타 115 & 파이썬: 코드카타 24 (1) | 2024.01.25 |
[240124] SQL: 코드카타 113~114 & 파이썬: 코드카타 23 (0) | 2024.01.24 |
[240119-23] 통계학 기초 (0) | 2024.01.23 |