프로그래밍 언어ㅤ/ㅤPython

Pandas

 

 

Ch 01. Pandas

출처 입력

* 엑셀로 할 수 있는 모든 것을 할 수 있음

import pandas as pd

 

 

* Series : 1차원 데이터 배열

mylist = [1,2,3,4] pd.Series(mylist)

 

 

* DataFrame : 2차원 데이터 배열

- list로 만들기

company1 = [['삼성', 2000, '스마트폰'], ['현대', 1000, '자동차'], ['네이버', 500, '포털']] pd.DataFrame(company1) df1 = pd.DataFrame(company1) df1.columns = ['기업명', '매출액', '업종']

 

- dict로 만들기

company2 = {'기업명': ['삼성', '현대', '네이버'], '매출액': [2000, 1000, 500], '업종': ['스마트폰', '자동차', '포털']} df2 = pd.DataFrame(company2)

 

- index를 특정 column으로 지정하기

df1.index = df1['기업명']

 

 

* CSV 파일 읽어오기

- CSV : Comma Seperated Value

- 엑셀을 로딩할 수 있지만 쉼표로 구분된 csv가 속도면에서 우월함

1) 로컬에서 파일 읽어오기

from google.colab import files import io myfile = files.upload() pd.read_csv(io.BytesIO(myfile['korean-idol.csv']))

 

2) Google Drive에서 파일 읽어오기

- drive.mount('/content/drive')실행하고 링크 클릭 후 코드 입력

from google.colab import drive drive.mount('/content/drive') filename = '경로'

 

 

* Pandas 기본

- df.columns

- df.index

- df.info()

- df.describe() : 통계 정보(숫자형만 해당됨)

- df.shape : tuple형태로 반환

- df.head()

- df.tail()

- df.sort_index() : 인덱스를 기준으로 오름차순 정렬

- df.sort_index(ascending=False) : 내림차순으로 정렬

- df.sort_values(by='키') : 키 컬럼을 기준으로 오름차순 정렬

- df.sort_values(by='키', ascending=False)

- df.sort_values(by=['키', '브랜드평판지수']) : 1)키, 2)브랜드평판지수 컬럼 기준으로 정렬 (순서 중요)

 

* Column 선택

1) df['이름']

2) df["이름"]

3) df.이름

 

* 범위 선택

1) 단순 index에 대한 범위 선택

- df[:3] : 행 기준 0~2행 가져옴

- df.head()

2) loc

- loc[행, 열]

- df.loc[:, '이름'] : 전체 행, 이름 컬럼 가져옴

- df.loc[:, ['이름', '생년월일']] : 전체 행, 이름과 생년월일 컬럼 가져옴

- df.loc[3:8, ['이름', '생년월일']] : 3~8행, 이름과 생년월일 컬럼 가져옴

- df.loc[2:5, ['이름':'생년월일']] : 2~5행, 이름부터 생년월일 컬럼까지 가져옴

3) iloc

- iloc[행, 열] : position을 넣어야

- df.iloc[:, [0,2]] : 전체 행, 0과 2번째 컬럼 가져옴

- df.iloc[1:5, [0, 2]] : 1~4까지 행, 0과 2번째 컬럼 가져옴

- df.iloc[1:5, 1:4] : 1~4까지 행, 1~3까지 컬럼 가져옴

- loc는 인덱싱 기준이 다름을 주의

4) boolean

- numpy와 같은 원리

- df[ df['키'] > 180]

- 특정한 컬럼을 뽑고 싶을 땐?

1) 뒤에 컬럼 이름 붙이기 : df[ df['키'] > 180]['이름', '성별']

2) loc 이용하기

df.loc[df[ df['키'] > 180, '이름' : '성별'] df.loc[df[ df['키'] > 180, ['이름', '성별']]

 

5) isin (boolean)

- list를 정의하고 그 리스트에 있는 조건에 부합하는 데이터만 추출

my_condition = ['플레디스', 'SM'] df['소속사'].isin(my_condition) # boolean 형태로 나옴 -> False False ... df.loc[ df['소속사'].isin(my_condition) ] df.loc[ df['소속사'].isin(my_condition), '소속사' ]

 

 

* Null (결측값)

- 판다스에서는 NaN으로 표기됨

- df.info()로 데이터 개수 확인하여 결측값 확인

- df.isna()로 boolean인덱싱하여 결측값 확인

- df['그룹'].isnull() 혹은 .isnan()으로 컬럼별로 결측값 확인

- NaN이 아닌 값만 색출해내기

df['그룹'][df['그룹'].notnull()] df.loc[ df['그룹'].notnull(), ['키', '혈액형'] ]

 

 

* Copy

- 데이터프레임을 복사할 때 사용

- 원본 데이터를 유지시키고, 새로운 변수에 복사할 때는 copy()를 사용해야 함

- 그저 새로운 변수에 할당하면, 같은 메모리 주소를 참조하기때문에 원테이블의 데이터도 바뀜

- copy_df = df.copy()

 

* Row 추가 및 삭제

- 딕셔너리 형태의 데이터를 만들어 .append() 함수를 사용하여 추가

- 반드시 ignore_index=True 옵션을 추가해야 함

- df = df.append(~~) 로 다시 데이터프레임에 할당해 줘야 함

df = df.append({'이름': '테디', '그룹': '테디그룹', '소속사': '끝내주는소속사', '성별': '남자', '생년월일': '1970-01-01', '키': 195.0, '혈액형': 'O', '브랜드평판지수': 12345678}, ignore_index=True)

 

 

* Column 추가 및 삭제

- 단순히 새로운 컬럼을 만들고 값을 대입해주면 자동으로 생성됨

df['국적'] = '대한민국' # 데이터를 바꿀땐? df.loc[df['이름'] == '지드래곤', '국적'] = 'Korea'

 

 

* 통계값 다루기

- 데이터타입이 float, int형인 컬럼을 다룸

- df.describe()로 기본 통계값을 확인 가능

- df['키'].min()

- df['키'].max()

- df['키'].sum()

- df['키'].mean()

- 분산과 표준편차

- 분산 : ∑(데이터 - 평균)2

- 표준편차 : √(분산)

- 주로 표준편차를 많이 사용하며, 데이터가 평균으로부터 얼마나 퍼져있는지 정도를 나타내는 지표로 활용

- df['키'].var()

- df['키'].std()

- df['키'].count()

- df['키'].median()

 

* 피벗테이블

- 엑셀의 피벗테이블과 동일

- 데이터 열 중에서 두 개의 열을 각각 행 인덱스, 열 인덱스로 사용하여 데이터를 커스터마이즈하여 보려는 목적

- index : 행 인덱스

- columns : 열 인덱스

- values : 조회하고 싶은 값

- aggfunc : 추가 계산 옵션 (기본 : 평균)

pd.pivot_table(df, index='소속사', columns='혈액형', values='키', aggfunc=np.sum)

 

 

* Groupby (그룹별 통계)

- 데이터를 그룹으로 묶어 분석할 때 활용

- 소속사별 키의 평균, 성별 키의 평균 등 특정 그룹별 통계 및 데이터의 성질을 확인하고자 할 때

- groupby와 함께 사용하는 함수

- count(), sum(), mean(), var(), std(), min(), max()

df.groupby('소속사').mean() ### 특정 열만 출력하고 싶다면? df.groupby('혈액형')['키'].mean()

 

 

* Multi-index (복합 인덱스)

- 멀티인덱스 적용

- 행 인덱스를 복합적으로 구성하고 싶은 경우 : 인덱스를 리스트로 만들어 주자

df.groupby(['혈액형', '성별']).mean()

 

- 멀티인덱스된 데이터프레임을 피벗테이블로 변환

df.unstack('혈액형') # 멀티인덱스였던 혈액형, 성별 중 혈액형이 컬럼으로 가며 펴지는 기능을 함 (인덱스는 이제 성별만)

 

- 인덱스 초기화

- reset_index()

- 멀티인덱스로 구성된 데이터프레임의 인덱스를 초기화함


 

Ch 02. Pandas - 전처리

출처 입력

* fillna (결측값 채우기)

- df.info()로 누락된 값들의 갯수를 확인 가능

- 누락된 값을 특정 수로 채우려면 ?

df2 = df.copy() height = df2['키'].mean() df2['키'] = df['키'].fillna(height)

 

 

* dropna (결측값 있는 행을 제거)

df.dropna() ### 열을 없애고 싶으면? df.dropna(axis=1)

 

- how 옵션

- how = 'any' : 한개라도 NaN이 있는 경우 드랍

- how = 'all' : 모두 NaN인 경우 드랍

df.dropna(axis=0, how='all')

 

 

* drop_duplicates (중복값 제거)

keep 옵션으로 유지하고 싶은 데이터를 선택할 수 있음

- first : 기본값, 해당 값이 처음 나온 데이터는 유지

- last : 해당 값이 마지막으로 나온 데이터를 유지

- series 기준으로 제거

df['키'] = df['키'].drop_duplicates(keep='last')

 

- 행 전체를 제거

df.drop_duplicates('그룹', kee='last') # 중복된 그룹이 나오면 마지막 행을 제외한 다른 행 전체를 제거

 

 

* drop()

- 컬럼을 제거

- 제거하고자하는 컬럼명을 활용

- axis = 1

df = df.drop(['그룹', '소속사'], axis=1)

 

- row를 제거

- 제거하고자 하는 index를 활용

- axis = 0

df = df.drop([3,5], axis=0)

 

 

* 데이터프레임 합치기 : concat

- row 나 col 기준으로 단순하게 이어 붙이기

- 상하로 붙이기 (row 기준)

- 리스트로 합쳐주기

- sort = False 옵션을 주어 순서가 유지되도록 하기

- index가 꼬이게 되므로, reset_index() 로 인덱스를 초기화 해줘야 함

pd.concat([df, df_copy], sort=False)

 

- 좌우로 붙이기 (col 기준)

- axis = 1 옵션을 주기

- 만약 행의 갯수가 맞지 않는다면 NaN으로 채워짐

pd.concat([df, df2], axis=1)

 

 

* 데이터프레임 합치기2 : merge

- 특정 고유한 키(unique id)를 기준으로 병합하기

- on : 기준이 되는 column

- how : 'left', 'right', 'inner', 'outer' 총 4가지의 병합 방식

- left : 왼쪽의 데이터프레임에 키 값이 존재하면 해당 데이터를 유지, 병합한 오른쪽 데이터프레임의 값은 NaN

- inner : 두 데이터프레임에 모두 키 값이 존재하는 경우만 병함

- outer : 하나의 데이터프레임에 키 값이 존재하는 경우 모두 병합 (데이터가 없는 경우 NaN으로 대입됨)

pd.merge(df1, df2, on='이름', how='left') ## 만약 두 DataFrame에서 컬럼명이 다르다면? (Eg. 이름, 성함) pd.merge(df1, df2, left_on='이름', right_on='성함', how='outer')

 

 

* Series의 타입 변환하기

- df.info() 로 데이터타입 확인

- object : 일반 문자열

- float

- int

- category : 카테고리

- datetime : 시간

- 타입 변환

1) astype 메소드 사용

- NaN이 있는 경우 변경이 안되므로 결측치 처리를 하고 변환해야 함

df['키'].dtypes df['키'] = df['키'].fillna(180) df['키'].astype(int)

 

2) datetime 으로 날짜 변환하기

- 판다스 메소드인 to_datetime 사용

- 월, 일, 요일 등 날짜 정보를 세부적으로 추출하기 편리

- 약어 : dt

- 현재 날짜 col은 dtype이 object로 되어있다고 가정 -> datetime으로 변환

df['생년월일'] = pd.to_datetime(df['생년월일'])

 

- 월요일 : 0, 화요일 : 1, ... , 일요일 : 6

df['생년월일'].dt.year df['생년월일'].dt.month df['생년월일'].dt.day df['생년월일'].dt.hour df['생년월일'].dt.minute df['생년월일'].dt.second df['생년월일'].dt.dayofweek df['생년월일'].dt.weekofyear df['생일_년'] = df['생년월일'].dt.year df['생일_월'] = df['생년월일'].dt.month df['생일_일'] = df['생년월일'].dt.day

 

 

* Apply 함수

- series나 DataFrame에 좀 더 구체적인 로직을 적용하고 싶은 경우 활용

1) 함수를 먼저 정의해야 함

2) 정의한 함수를 인자로 넘겨줘야 함

- 반드시 return 값이 존재해야 함

- (Eg) 남자를 1, 여자를 0으로 변환하고 싶음

### 1) apply에 활용할 함수를 정의하기 def male_or_female(x): if x == '남자': return 1 elif x == '여자': return 0

 

### 2) 정의한 함수를 인자로 넘겨주기 df['성별_NEW'] = df['성별'].apply(male_or_female)

 

- (Eg) cm당 브랜드 평판지수를 구해보자 (브랜드평판지수/키)

### 1) 먼저 apply에 활용할 함수를 정의하기 def cm_to_brand(df): value = df['브랜드평판지수'] / df['키'] return value

 

### 2) 정의한 함수를 인자로 넘겨주기 ### 연산하는 방식을 열로 하겠다 => 한 행씩 넘겨줘 => axis=1 지정을 해야 함 df.apply(cm_to_brand, axis=1)

 

 

* Lambda

- 람다는 1줄로 작성하는 간단한 함수식으로 리턴을 명시하지 않음

f = lambda x: 1 if x == '남자' else 0 df['성별'].apply(f)

 

df['키/2'] = df['키'].apply(lambda x: x/2)

 

 

* Map

- 값을 매핑

- 딕셔너리 타입으로 정의해줘야 함

my_map = {'남자': 1, '여자': 0} df['성별'].map(my_map)

 

 

* 데이터프레임의 산술연산

df = pd.DataFrame({'통계': [60, 70, 80, 85, 75], '미술': [50, 55, 80, 100, 95], '체육': [70, 65, 50, 95, 100] })

 

통계 미술 체육 0 60 50 70 1 70 55 65 2 80 80 50 3 85 100 95 4 75 95 10

 

1) 컬럼과 컬럼의 연산 (+, -, *, /, %)

df['통계'] + df['미술'] + df['체육']

 

2) 컬럼과 숫자의 연산 (+, -, *, /, %)

df['통계'] + 10

 

3) 복합연산

df['통계미술합계'] = df['통계'] + df['미술'] + 10

 

4) axis기준 mean(), sum() 연산

df.sum(axis=0) df.mean(axis=1)

 

5) NaN이 있을 경우 연산

통계 미술 체육 0 60.0 50.0 70.0 1 70.0 NaN 65.0 2 NaN 80.0 50.0 3 85.0 100.0 NaN 4 75.0 95.0 100.0

 

df['통계'] / 2 1000 / df['통계'] df['통계'] / np.nan # NaN있으면 NaN으로 나옴

 

6) 데이터프레임과 데이터프레임의 연산

6-1) 문자열이 포함된 경우 : 에러 -> 제거하고 연산

6-2) 컬럼의 순서가 바뀌어있는 경우 : OK <- 컬럼명 기준으로 연산되기 때문

6-3) 행의 갯수가 다른 경우 : OK <- 빈 곳을 NaN으로 할당

 

* 원핫인코딩 (One-hot-encoding)

- 한개의 요소를 true, 나머지를 false로 만드는 기법

- (Eg) object데이터타입인 혈액형 col을 numerical하게 바꾸기

blood_map = { 'A': 0, 'B': 1, 'AB': 2, 'O': 3, } df['혈액형_code'] = df['혈액형'].map(blood_map)

 

- 머신러닝 시 문제점 발생

- '혈액형_code'값들간의 관계를 스스로 형성하게 됨

- 예를 들어, B형과 AB형을 더한게 O형이라는 없는 관계를 있는 관계로 해석함

-> 따라서, 0부터 3까지가 아닌 4개의 독립적인 column을 생성하여 요소간의 독립성을 부여해야

- get_dummies 활용

- prefix 옵션을 통해 컬럼명을 설정할 수 있음

pd.get_dummies(df['혈액형_code']) pd.get_dummies(df['혈액형_code'], prefix='혈액형') # 컬럼명이 '혈액형_0', '혈액형_1', ... 같은 형식으로 생성됨

 

 


* (예제) 부동산 데이터

- Questions:

- object: NaN이랑 ''이랑 다름? 매번 따로 처리해야 하나? 귀찮^^;; -> 광광이

- replace vs str.replace

- replace는 한 개씩밖에 못하나?

- 조건에 맞는 행 삭제

1) 조건에 맞는 데이터의 인덱스 리스트로 저장

2) drop()으로 인덱스에 맞는 행(axis=0) 삭제

idx = df.loc[df['규모구분'] < 100] df = df.drop(idx, axis=0)

 

 


 

Ch 03. Pandas - 시각화

출처 입력

* 시각화

- Exploratory Data Analysis (EDA) :

- 수집한 데이터가 들어왔을 떄, 이를 다양한 각도에서 관찰하고 이해하는 과정

- 통계값 등 기본적인 데이터의 특징을 파악하는 과정

- 시각화 (Visualization) : 직관적으로, 한 눈에 파악하기 쉽게 데이터 뿌려놓는 것

- df.plot()

- colab에서는 한글 깨짐

- 깨지는 현상 해결 코드 있음 -> 외울 필요는 X

 

* Plot 그래프

- plot은 선그래프가 기본 설정

- kind를 통해 그래프 종류 설정 가능

- line : 선 그래프 (주가 평균 데이터)

- bar : 바 그래프 (그룹별로 비교할 때)

- bath : 수평 바

- hist : 히스토그램

- kde : 커널 밀도 그래프 (hist와 비슷, 밀도를 보여줌, 부드러운 라인)

- hexbin : 고밀도 산점도 그래프 (numerical x와 y의 키 값을 넣어줘야 함, 데이터의 밀도를 추정)

- df.plot(kind = 'hexbin', x='분양가', y='연도', gridsize=20)

- box : 박스 플롯

- area : 면적 그래프 (line그래프에서 아래 면적을 다 색칠한 그래프)

- pie : 파이 그래프 (점유율)

- scatter : 산점도 그래프 (numerical x, y값을 넣어줘야, 축 지정 가능)

df['분양가'].plot(kind = 그래프종류)

 

- 조건을 넣어서 그래프 그리기

df_seoul_year = df_seoul.groupby('연도')['분양가'].mean().plot(kind = 'line')