Language/Python

231121 Python_Rank, 2차원배열 Rank, pandas 날짜, 데이터 재구조화, pivot, matplotlib(시각화 라이브러리), plt.subplot(행, 열, 위치), 그룹형·스택형 막대그래프

잇꼬 2023. 11. 21. 17:41
728x90
반응형
SMALL

■ 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()

 

728x90
반응형
LIST