■ Rank
obj = Series([78,80,88,60,50,90,79,99,68,80,80])
obj
obj = Series([78,80,88,60,50,90,79,99,68,80,80])
obj
(1) 오름차순
→ 값에 따라 오름차순 순위를 나타내며, 정렬은 되지 않는다.
obj.rank()
obj.rank(ascending=True)
(2) 내림차순
→ 값에 따라 내림차순 순위를 나타내며, 정렬은 되지 않는다.
obj.rank(ascending=False)
(3) DataFrame
#1) method : 동점자처리
방법1)
DataFrame({"순위": obj.rank(ascending=False),
"점수": obj})
방법2)
DataFrame({"순위": obj.rank(ascending=False).astype(int),
"점수": obj})
=> 순위가 실수로 나오기 때문에, 정수(int)로 타입을 바꿔줌
방법3)
DataFrame({"순위": obj.rank(ascending=False, method="average").astype(int),
"점수": obj})
방법4)
DataFrame({"순위": obj.rank(ascending=False, method="min").astype(int),
"점수": obj})
-> sql rank()와 같음
방법5)
DataFrame({"순위": obj.rank(ascending=False, method="max").astype(int),
"점수": obj})
-> 동점자가 3명이기 때문에 다 6등으로 바꿈
방법6)
DataFrame({"순위": obj.rank(ascending=False, method="first").astype(int),
"점수": obj})
-> 동점자일 경우 처음으로 나온 인덱스가 앞등수
방법7)
DataFrame({"순위": obj.rank(ascending=False, method="dense").astype(int),
"점수": obj})
-> sql dense_rank()와 같음 (동차유지/다음순위)
4) 순위를 기준으로 오름차순 정렬
1)
df = DataFrame({"순위": obj.rank(ascending=False, method="dense").astype(int),
"점수": obj})
df.sort_values(by="순위")
2)
obj = Series([70,60,80,None,90])
# 결측값이 존재할 때 결측값은 맨 마지막에 위치 (기본값)
obj.sort_values()
obj.sort_values(ascending=True, na_position='last')
# 결측값이 맨 위로 위치
obj.sort_values(ascending=True, na_position='first')
# na_position으로 위치 바꾸기
(4) 순위를 기준으로 내림차순 정렬
obj.sort_values(ascending=False)
-> Flase라고 해도 결측값은 맨 마지막
(5) 결측값은 순위를 매기지 않고 결측값으로 놔둠 (기본값)
obj.rank()
obj.rank(ascending=True, na_option="keep")
obj.rank(ascending=True, na_option="top")
# -> na_option="top" : 결측값 1등
obj.rank(ascending=True, na_option="bottom")
# -> na_option="bottom" : 결측치 꼴등
(6) 2차원배열 Rank
df =DataFrame({"영어": [60,80,70],
"수학": [50,60,86]},
index=["박찬호", "손흥민", "이문세"])
df
df.rank()
df.rank(ascending = True, axis = 0)
-> 과목별 오름차순 순위를 구했음 (기본값)
df.rank(ascending = True, axis = 0) # 열 기준으로 오름차순 순위 (기본값)
df.rank(ascending = True, axis = 1) # 행 기준으로 오름차순 순위
df.rank(ascending = False, axis = 0)# 열 기준으로 내림차순 순위
df.rank(ascending = False, axis = 1)# 행 기준으로 내림차순 순위
(7) top-N 분석
emp = pd.read_csv("c:/data/employees.csv")
emp.info()
<<SQL>>
SELECT *
FROM (SELECT rank() over(order by salary desc) rank, employee_id, salary
FROM emp)
WHERE rank <= 10;
<<Python>>
emp['SALARY']
emp['SALARY'].rank(ascending=False, method="min").astype(int)
emp['rank'] = emp['SALARY'].rank(ascending=False, method="min").astype(int)
emp['rank']
-> emp의 'rank'라는 컬럼을 추가해서 순위 담기
emp[emp['rank'] <= 10][['rank', 'EMPLOYEE_ID', 'SALARY']]
top_10 = emp[emp['rank'] <= 10][['rank', 'EMPLOYEE_ID', 'SALARY']]
top_10.sort_values(by='rank')
top_10.sort_values(by='rank').reset_index(drop=True)
2) dense_rank : 메소드만 min => dense 로 바꾸기
<<SQL>>
SELECT *
FROM (SELECT dense_rank() over(order by salary desc) rank, employee_id, salary
FROM emp)
WHERE rank <= 10;
<<Python>>
emp['SALARY']
emp['SALARY'].rank(ascending=False, method="dense").astype(int)
emp['rank'] = emp['SALARY'].rank(ascending=False, method="dense").astype(int)
emp['rank']
-> emp의 'rank'라는 컬럼을 추가해서 순위 담기
emp[emp['rank'] <= 10][['rank', 'EMPLOYEE_ID', 'SALARY']]
top_10 = emp[emp['rank'] <= 10][['rank', 'EMPLOYEE_ID', 'SALARY']]
top_10.sort_values(by='rank')
top_10.sort_values(by='rank').reset_index(drop=True)
■ pandas 날짜
import datetime
datetime.datetime.now()
# 오류발생
- pandas 에서는 문법X
pd.datetime.now()
datetime.datetime.now()
pd.Timestamp.now()
pd.Timestamp.today()
# 오류발생, month+day 작성X
pd.Timestamp(year=2023)
# 오류발생, day 작성X
pd.Timestamp(year=2023, month=11)
# 년월일 출력
pd.Timestamp(year=2023, month=11, day=21)
# 년월일, 시분초 출력
pd.Timestamp(year=2023, month=11, day=21, hour=10, minute=30, second=30, microsecond=1)
pd.Timestamp(year=2023, month=11, day=21, hour=10, minute=30, second=30,
microsecond=1,tz='Asia/Seoul')
pd.Timestamp.now().year
pd.Timestamp.now().month
pd.Timestamp.now().day
pd.Timestamp.now().hour
pd.Timestamp.now().minute
pd.Timestamp.now().second
pd.Timestamp.now().microsecond
pd.Timestamp.now().dayofweek # 숫자 0:월~6:일
pd.Timestamp.now().day_name() # 요일(영문
pd.Timestamp.now().quarter # 분기
pd.Timestamp.now().date() # 시간정보 없이 날짜정보만 (=pd.datetime.now())
# char -> timestamp 변환
# to_datetime()
pd.to_datetime("2023-11-21")
pd.to_datetime("2023/11/21")
pd.to_datetime('20231121', format='%Y%m%d')
pd.to_datetime('2023/11/21/11/03/03', format='%Y/%m/%d/%H/%M/%S')
pd.to_datetime('2023-1-1') - pd.Timestamp.now()
pd.Timestamp.now() - pd.to_datetime('2023-1-1')
(pd.Timestamp.now() - pd.to_datetime('2023-1-1')).days # 일수
# 날짜 속성
pd.Timestamp.now() + pd.Timedelta('10 days') # 날짜 + 일수 = 날짜
pd.Timestamp.now() - pd.Timedelta('10 days') # 날짜 - 일수 = 날짜
pd.Timestamp.now() + pd.Timedelta('10 hours') # 날짜 + 시간 = 날짜 시간
pd.Timestamp.now() + pd.Timedelta('10 minutes') # 날짜 + 분 = 날짜 시간
pd.Timestamp.now() + pd.Timedelta('10 min') # 날짜 + 분 = 날짜 시간
pd.Timestamp.now() + pd.Timedelta('100 second') # 날짜 + 초 = 날짜 시간
pd.Timestamp.now() + pd.Timedelta('100 sec') # 날짜 + 초 = 날짜 시간
pd.Timestamp.now() + pd.Timedelta('10 days 10 hours 3600 sec') # 날짜 + 일수 시분초 = 날짜 시간
pd.Timestamp.now() + pd.Timedelta('10 10:100:3600') # 날짜 + 일수 시분초 = 날짜 시간
pd.Timestamp.now() + pd.DateOffset(years=1, months=2) # 날짜 +(년수 개월수)
# 2003년 입사자 추출
emp[emp['HIRE_DATE'] < '2003-01-01']
emp[pd.to_datetime(emp['HIRE_DATE'], format='%Y-%m-%d') < pd.to_datetime('2023-01-01', format='%Y-%m-%d')]
# 날짜타입 변수
emp['HIRE_DATE'] = pd.to_datetime(emp['HIRE_DATE'], format='%Y-%m-%d')
emp.info()
# 속성 추출
emp['HIRE_DATE'][0].year
emp['HIRE_DATE'][100].year
emp['HIRE_DATE'].dt.year
emp['HIRE_DATE'].dt.month
emp['HIRE_DATE'].dt.day
emp['HIRE_DATE'].dt.hour
emp['HIRE_DATE'].dt.minute
emp['HIRE_DATE'].dt.second
emp['HIRE_DATE'].dt.microsecond
emp['HIRE_DATE'].dt.dayofweek # 숫자요일 0:월~6:일
emp['HIRE_DATE'].dt.weekday # 숫자요일 0:월~6:일
emp['HIRE_DATE'].dt.day_name() # 요일(영문)
emp['HIRE_DATE'].dt.quarter # 분기
# 월요일 입사자
emp[emp['HIRE_DATE'].dt.dayofweek == 0]
x = emp['SALARY'].groupby([emp['HIRE_DATE'].dt.year, emp['HIRE_DATE'].dt.quarter]).sum()
x.index # 다중인덱스
x.index.names
# 오류발생
x.reset_index() # 컬럼명이 동일
# 멀티인덱스
x.index.names = ['year', 'quarter']
x.index.names
x.reset_index()
df = x.reset_index()
df
df.set_index(['year', 'quarter'])
■ 데이터 재구조화(reshaping data)
# 교차표(가로방향), 구조화로 변경
# unstack (= SQL PIVOT)
#1. 인덱스 값을 컬럼으로 보내는 역할.
x.unstack()
x.unstack(level=0) # 지정된 인덱스가 컬럼으로 이동
x.unstack(level=1)
x.unstack(level='quarter') # 지정된 인덱스 이름이 컬럼으로 이동
x.unstack(level='year')
result = x.unstack()
result
# stack (= SQL UNPIVOT)
#2. 컬럼을 인덱스로 보내는 역할
result.stack()
result.columns = ['1분기', '2분기', '3분기', '4분기']
result.index.name = '년도'
result.fillna(0, inplace=True) # 결측값이 0 으로 바로 지정
result
result.stack()
■ pivot
# 피봇테이블(pivot table) 이란 데이터 열 중에서 두개의 열을 각각 행 인덱스, 열 인덱스로 사용하여 데이터 조회하여 펼쳐진 것을 의미한다.
# 교차테이블 생성
p = df.pivot(columns='quarter', index='year', values='SALARY')
p
p.stack()
# 년도 분기별 -> emp 테이블
emp
pd.pivot_table(data = emp,
index = emp['HIRE_DATE'].dt.year,
columns = emp['HIRE_DATE'].dt.quarter,
values = 'SALARY',
aggfunc = 'sum')
pd.pivot_table(data = emp,
index = emp['HIRE_DATE'].dt.year,
columns = emp['HIRE_DATE'].dt.quarter,
values = 'SALARY',
aggfunc = ['sum', 'mean']).fillna(0)
emp = pd.read_csv('c:/data/emp.csv')
emp.info()
■ matplotlib : 시각화 라이브러리
# 연속형 자료 : SALARY, COMMISSION_PCT
#1. pie charts
#1) 범주형(텍스트) 자료에 대한 그래프를 그릴 때 사용
ex) emp table) LAST_NAME, HIRE_DATE(요일):빈도수, JOB_ID(비율)
#2) 데이터의 구성 요소들이 전체 데이터에서 어느정도의 비율을 차지하는지 파이조각으로 보여주는 시각화 방법
#3) 원을 그린후 그 원에 각 계급의 상대도수에 대한 면적 또는 부분으로 나눈다(상대도수값)
예시)
# =============================================================================
# 선호도 도수 상대도수 각도
# ------ -------- ----------- -----------
# 좋다 45 0.45 0.45*360=162
# 보통 25 0.25 0.25*360
# 싫다 20 0.20 0.20*360
# 무응답 10 0.10 0.10*360
# 100 1
# =============================================================================
# 시각화 import(그래프)
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
# 폰트적용
font_name = font_manager.FontProperties(fname='C:/Windows/Fonts/gulim.ttc').get_name()
rc('font', family=font_name)
labels = ['좋다', '보통', '싫다', '무응답']
frequency = [45, 25, 20, 10]
DataFrame({'frequency':frequency}, index=labels)
survey = DataFrame({'frequency':frequency}, index=labels)
survey.frequency.plot() # 기본은 꺽은선 그래프
survey.frequency.plot(kind='pie')
survey.frequency.plot(kind='pie',
colors=['skyblue', 'red', 'green', 'yellow'],
autopct='%.1f%%', # 부채꼴 안에 표시될 숫자 형식
label='',
title='고객만족도조사',
fontsize=25,
legend=True , # 범례
figsize=(7,5), # 가로길이, 세로길이
startangle=30 # 시작각도
)
plt.pie(survey['frequency'],
shadow=True,
startangle=90,
autopct='%.1f%%',
explode=(0.1, 0.0, 0.0, 0.0))
plt.legend(labels=survey.index, loc='upper right')
plt.title('고객만족도조사',size=30)
#2. 막대그래프(bar plot)
#1) 각 범주에서 도수의 크기를 막대 높이로 표현한 그래프
#2) 항목별 비교할 때 유용하다
x = [1,2,3]
x = ['SQL', 'PL/SQL', 'PYTHON']
y =[90,75,80]
plt.bar(x=x, height=y, color=['orange', 'green', 'blue'])
plt.title('과목별 점수 현황', size=20)
plt.xlabel('과목', size=25)
plt.ylabel('점수', size=25)
plt.show()
data = {'홍길동': [15,13,11],
'제임스':[13,14,15],
'하든':[10,9,12]}
df = DataFrame(data=data, index=[2020, 2021, 2022])
df
df['홍길동'].plot(kind='bar')
df['홍길동'].plot(kind='barh')
df
# 그룹형 막대그래프
df.plot(kind='bar')
df.plot(kind='barh')
# 스택형 막대그래프
df.plot(kind='bar', stacked=True)
df.plot(kind='barh', stacked=True)
여러개의 그래프를 하나의 그림에 나타내도록 함수
# plt.subplot(행, 열, 위치), plt.show()는 마지막에 한번만
plt.subplot(1,2,1)
plt.bar(x = quarter.index, height=quarter)
plt.xticks(ticks=quarter.index, labels=[str(i) + '분기' for i in quarter.index])
for i in quarter.index:
plt.text(i-0.1, # x축
quarter[i]+0.3, # y축
quarter[i])
plt.subplot(1,2,2)
plt.barh(y = quarter.index, width=quarter)
plt.yticks(ticks=quarter.index, labels=[str(i) + '분기' for i in quarter.index])
for i in quarter.index:
plt.text(quarter[i]+0.3, # x축
i-0.1, # y축
quarter[i])
plt.show()
p = plt.bar(x = quarter.index, height=quarter)
plt.xticks(ticks=quarter.index, labels=[str(i) + '분기' for i in quarter.index])
p # 위치, 값 정보
# yerr 막대그래프 위에 포인터 출력
p = plt.bar(x = quarter.index, height=quarter, yerr=1)
plt.xticks(ticks=quarter.index, labels=[str(i) + '분기' for i in quarter.index])
plt.bar_label(p, padding=1)
# xerr 막대그래프 위에 포인터 출력
p = plt.barh(y = quarter.index, width=quarter, xerr=1)
plt.yticks(ticks=quarter.index, labels=[str(i) + '분기' for i in quarter.index])
plt.bar_label(p, padding=1)
# 하나의 화면의 두개의 그래프 출력
plt.subplot(2,1,1)
p = plt.bar(x = quarter.index, height=quarter, yerr=1)
plt.xticks(ticks=quarter.index, labels=[str(i) + '분기' for i in quarter.index])
plt.bar_label(p, padding=1)
plt.subplot(2,1,2)
p = plt.barh(y = quarter.index, width=quarter, xerr=1)
plt.yticks(ticks=quarter.index, labels=[str(i) + '분기' for i in quarter.index])
plt.bar_label(p, padding=1)
plt.show()