개발/프로젝트

웹대시보드 프로젝트 - 3일차(팀 차트추가 및 데이터 가공 , ec2서버에 한글 추가)

웅'jk 2022. 12. 19. 17:32

3일차에는 데이터를 가공하고 추가로 차트를 넣었습니다. 

 

다만 구성에 깔끔하지 못하고 난잡해보여 4일차에서는 멀티셀렉트박스를 통해

좀 더 깔끔하게 구성을 할려고 합니다.

 

먼저 ec2 서버에 한글을 추가하는 방법을 알아보겠습니다.

 

1. 폰트 설치 확인

# ec2 콘솔에서 설치된 폰트가 있는지 확인
fc-list

 

2. 경로가 있는지 확인

ec2 콘솔에서 python을 입력한 뒤 다음을 입력하여 경로를 확인합니다.

import matplotlib
print(matplotlib.__version__) # 파이썬 버전확인
print(matplotlib.__file__) # 설치 폴더 경로 확인
print(matplotlib.get_cachedir()) # 캐시 폴더 경로 확인

 

3.한글폰트 추가

sudo cp -r /usr/share/fonts/* /home/ec2-user/anaconda3/envs/YH/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/

 

4. 한글폰트 설치 확인

import matplotlib
import matplotlib.font_manager

[i.fname for i in matplotlib.font_manager.fontManager.ttflist]

 

5. 이제 스트림릿 코드에 다음을 추가합니다.

import platform
from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus'] = False
if platform.system() == 'Linux':
    rc('font', family='NanumGothic')

 

1 ~ 4번은 ec2콘솔 , 5번은 여러분들이 작성하실 코드에 추가하여 ec2에 업로드하면 됩니다.

 

이제 3일차 작업 소스코드입니다.

 

1.team.py

#team.py

import streamlit as st
import pandas as pd
import team_url as tu
import data_init
import matplotlib.pyplot as plt
import numpy as np
import platform
from matplotlib import font_manager, rc
import plotly.express as px

def team(team_name) :
    plt.rcParams['axes.unicode_minus'] = False
    if platform.system() == 'Linux':
        rc('font', family='NanumGothic')

    # 팀의 데이터를 읽어온다.
    df_teams = data_init.df_teams
    df_games = data_init.df_games
    df_games_detail = data_init.df_games_detail
    # 팀정보 헤더 지정
    st.header(team_name+'의 정보')
    # 팀의 맞는 이미지 생성
    st.image(tu.team_url(team_name),width=500)
    # 사이드바에서 선택한 팀으로 정보
    df_teams_info = df_teams.loc[df_teams['팀약어'] == team_name,'팀약어':]
    st.dataframe(df_teams_info)
    
    # 시즌별 성적보기
    st.header('일자별 성적보기')

    team_id = df_teams[df_teams['팀약어'] == team_name]['팀ID'].values[0]
    st.subheader('홈 성적')
    # 시작과 끝 종료날짜를 설정하여 데이터 가져오기
    start_date = st.date_input('시작 날짜')
    end_date = st.date_input('종료 날짜')
    start_date = start_date.strftime('%Y-%m-%d')
    end_date = end_date.strftime('%Y-%m-%d')
    if start_date > end_date :
        st.error('시작 날짜를 종료 날짜보다 전으로 설정해주세요.')
    # 전적을 비교하기 위한 list 생성
    team_name_list = ['','ATL', 'BOS', 'NOP', 'CHI', 'DAL', 'DEN', 'HOU', 'LAC', 'LAL',
       'MIA', 'MIL', 'MIN', 'BKN', 'NYK', 'ORL', 'IND', 'PHI', 'PHX',
       'POR', 'SAC', 'SAS', 'OKC', 'TOR', 'UTA', 'MEM', 'WAS', 'DET',
       'CHA', 'CLE', 'GSW']    
    
    df_games_home = df_games.loc[ (df_games['홈팀ID']==team_id) & (start_date<=df_games['경기날짜']) & (df_games['경기날짜']<=end_date),:]
    st.dataframe(df_games_home.iloc[:,[11,12,0,3,4,5,7,8,9]])
    
    if st.checkbox('홈 성적 자세히보기') :
        st.header('최근 대결 성적')
        
        fig1 = plt.figure()
        x= np.arange(3)
        x_label = ['점수','어시','리바운드']
        home_value = df_games_home.iloc[:,3:5+1].mean()
        home_value2 = df_games_home.iloc[:,7:-3].mean()
        p1=plt.bar(x,home_value,width = 0.4,color='r')
        p2=plt.bar(x+0.4,home_value2,width = 0.4,color='b')
        plt.xticks(np.arange(0.2,3+0.2,1),x_label)
        plt.legend((p1[0],p2[0]) , ('Home','Away'), fontsize = 10 )
        st.pyplot(fig1)
        
        #득점 데이터
        st.subheader('득점')
        recently_point_pig = px.bar(df_games_home,x='경기날짜',y=['홈팀점수','어웨이팀점수'],barmode='group')
        st.plotly_chart(recently_point_pig)
        st.info('자세히 보고싶은 부분을 좌클릭으로 영역 지정 해주세요.')

        #어시스트 데이터
        st.subheader('어시스트')
        recently_assist_pig = px.bar(df_games_home,x='경기날짜',y=['홈팀어시','어웨이팀어시'],barmode='group')
        st.plotly_chart(recently_assist_pig)
        #리바운드 데이터
        st.subheader('리바운드')
        recently_rebound_pig = px.bar(df_games_home,x='경기날짜',y=['홈팀리바운드','어웨이팀리바운드'],barmode='group')
        st.plotly_chart(recently_rebound_pig)
        

        st.subheader('역대 홈 전적비교')
        compare_home_team = st.selectbox('팀선택',team_name_list)
        print(compare_home_team+' '+team_name)
        if compare_home_team != '' and compare_home_team != team_name : 
            compare_team_id_home = df_teams[df_teams['팀약어'] == compare_home_team]['팀ID'].values[0]
            data_home = df_games[(df_games['홈팀ID'] ==team_id) & (df_games['어웨이팀ID'] ==compare_team_id_home)]
            st.dataframe(data_home.iloc[:,[11,0,3,4,5,12,7,8,9,10]].sort_values('경기날짜',ascending=False))
            
            if data_home.empty == False :
                data_home = data_home.mean(numeric_only=None)
                data_home['어웨이승리'] = 1 - data_home['홈팀승리여부']
                fig_home = plt.figure()
                plt.subplot(2,2,1)
                plt.pie(data_home[[9,10]],autopct='%.1f',startangle = 90)
                plt.title('홈팀 승률')
                plt.legend(['홈','어웨이'])
                
                plt.subplot(2,2,2)
                plt.pie(data_home[[2,6]],autopct='%.1f',startangle=90)
                plt.title('평균 득점')
                plt.legend(['홈','어웨이'])

                plt.subplot(2,2,3)
                plt.pie(data_home[[3,7]],autopct='%.1f',startangle=90)
                plt.title('평균 어시')
                plt.legend(['홈','어웨이'])

                plt.subplot(2,2,4)
                plt.pie(data_home[[4,8]],autopct='%.1f',startangle=90)
                plt.title('평균 리바운드')
                plt.legend(['홈','어웨이'])
                st.pyplot(fig_home)
            else :
                st.title('')
        elif compare_home_team == team_name :
            st.error('같은 팀 입니다. 다른 팀을 선택해주세요.')
        else : 
            st.error('팀을 선택해주세요')

        

        st.subheader('홈경기 선수 스탯')
        home_game_id = df_games_home['경기ID']
        home_team_player_info = df_games_detail[(df_games_detail['경기ID'].isin(home_game_id)) & (df_games_detail['팀ID'] == team_id)].iloc[:,3:].groupby('선수명').mean()
        st.dataframe(home_team_player_info)
    else :
        st.write('')


    st.subheader('어웨이 성적')
    df_games_away = df_games.loc[ (df_games['어웨이팀ID']==team_id) & (start_date<=df_games['경기날짜']) & (df_games['경기날짜']<=end_date),:]
    st.dataframe(df_games_away.iloc[:,[11,12,0,3,4,5,7,8,9]])
    if st.checkbox('어웨이 성적 자세히 보기') :
        st.subheader('최근 대결 성적')
        fig2 = plt.figure()
        x= np.arange(3)
        x_label = ['점수','어시','리바운드']
        away_value2 = df_games_away.iloc[:,3:5+1].mean()
        away_value = df_games_away.iloc[:,7:-3].mean()
        p1=plt.bar(x,away_value,width = 0.4,color='g')
        p2=plt.bar(x+0.4,away_value2,width = 0.4,color='y')
        plt.xticks(np.arange(0.2,3+0.2,1),x_label)
        plt.legend((p1[0],p2[0]) , ('Away','Home'), fontsize = 10 )
        st.pyplot(fig2)
        st.dataframe(df_games_away.iloc[:,[3,4,5,7,8,9]].mean())
        st.subheader('역대 어웨이 전적비교')
        compare_away_team = st.selectbox('팀 선택',team_name_list)
       
        if compare_away_team != '' and compare_away_team != team_name: 
            compare_team_id_away = df_teams[df_teams['팀약어'] == compare_away_team]['팀ID'].values[0]
            data_away=df_games[(df_games['홈팀ID'] ==team_id) & (df_games['어웨이팀ID'] ==compare_team_id_away)]
            st.dataframe(data_away.iloc[:,[11,0,3,4,5,12,7,8,9,10]].sort_values('경기날짜',ascending=False))

            if data_away.empty == False :
                data_away = data_away.mean(numeric_only=None)
                data_away['어웨이승리'] = 1 - data_home['홈팀승리여부']
                fig_away = plt.figure()
                plt.subplot(2,2,1)
                plt.pie(data_home[[10,9]],autopct='%.1f',startangle = 90)
                plt.title('어웨이팀 승률')
                plt.legend(['어웨이','홈'])
                
                plt.subplot(2,2,2)
                plt.pie(data_home[[6,2]],autopct='%.1f',startangle=90)
                plt.title('평균 득점')
                plt.legend(['어웨이','홈'])

                plt.subplot(2,2,3)
                plt.pie(data_home[[7,3]],autopct='%.1f',startangle=90)
                plt.title('평균 어시')
                plt.legend(['어웨이','홈'])

                plt.subplot(2,2,4)
                plt.pie(data_home[[8,4]],autopct='%.1f',startangle=90)
                plt.title('평균 리바운드')
                plt.legend(['어웨이','홈'])
                st.pyplot(fig_away)
            else :
                st.title('')
        elif compare_away_team == team_name :
            st.error('같은 팀 입니다. 다른 팀을 선택해주세요.')
        else : 
            st.error('팀을 선택해주세요')


        st.subheader('어웨이경기 선수 스탯')
        home_away_id = df_games_away['경기ID']  
        away_team_player_info = df_games_detail[(df_games_detail['경기ID'].isin(home_away_id)) & (df_games_detail['팀ID'] == team_id)].iloc[:,3:].groupby('선수명').mean()
        st.dataframe(away_team_player_info)
    else :
        st.write('')

 

data_init.py

import pandas as pd

df_teams = pd.read_csv('data/teams.csv')
df_games = pd.read_csv('data/games.csv')
df_players = pd.read_csv('data/players.csv')
df_games_detail = pd.read_csv('data/games_details.csv',low_memory = False)

df_teams = df_teams.loc[:,['TEAM_ID','ABBREVIATION','YEARFOUNDED','CITY','ARENA']]
df_games = df_games.loc[:,['GAME_DATE_EST','GAME_ID','HOME_TEAM_ID','PTS_home','AST_home','REB_home','TEAM_ID_away','PTS_away','AST_away','REB_away','HOME_TEAM_WINS']]
# 문제 없는 데이터프레임
df_games_detail_1 = df_games_detail.loc[:,:'START_POSITION']
# 문제 있는 데이터프레임 짜른 뒤 수정
df_games_detail_2 = df_games_detail.loc[:,'COMMENT':].shift(-1,axis= 1)
# 짜른 두 코드를 합쳤다.
df_games_detail = pd.concat([df_games_detail_1,df_games_detail_2],axis=1)
df_games_detail = df_games_detail.loc[:,['GAME_ID', 'TEAM_ID','PLAYER_ID','PLAYER_NAME','START_POSITION',
                       'COMMENT','MIN', 'FG_PCT', 'FG3_PCT', 
                       'DREB', 'REB', 'AST', 'STL', 'BLK','TO']]
rename ={ 'GAME_DATE_EST' : '경기날짜' ,'GAME_ID':'경기ID', 'HOME_TEAM_ID':'홈팀ID','PTS_home':'홈팀점수','AST_home':'홈팀어시','REB_home':'홈팀리바운드','TEAM_ID_away':'어웨이팀ID','PTS_away':'어웨이팀점수','AST_away':'어웨이팀어시','REB_away':'어웨이팀리바운드','HOME_TEAM_WINS':'홈팀승리여부'  }
df_games = df_games.rename(columns=rename)
df_games=df_games.fillna(0)

rename_detail = { 'GAME_ID':'경기ID','TEAM_ID':'팀ID','PLAYER_ID':'선수ID','PLAYER_NAME':'선수명',
                    'START_POSITION':'포지션',
    'COMMENT':'출전시간','MIN':'2점슛', 'FG_PCT':'3점슛', 'FG3_PCT':'자유투',
    'DREB':'리바운드','REB':'어시스트','AST':'가로채기','STL':'블락','TO':'턴오버수'}
df_games_detail = df_games_detail.rename(columns=rename_detail)
df_games_detail = df_games_detail.fillna(0)
    
rename_playes = { 'PLAYER_NAME':'선수명','TEAM_ID':'팀ID','PLAYER_ID':'선수ID','SEASON':'시즌' }
df_players=df_players.rename(columns=rename_playes)
    
rename_team = {'TEAM_ID':'팀ID','ABBREVIATION':'팀약어','YEARFOUNDED':'팀창설해',
                'CITY':'연고지','ARENA':'홈구장'}
df_teams = df_teams.rename(columns=rename_team)

# 가공을 편하게 하기위해 df_games에 홈팀명,어웨이팀명 추가
df_teams_home = df_teams.rename(columns={'팀ID':'홈팀ID'})
new_data = pd.merge(df_games,df_teams_home).iloc[:,:-3].rename(columns={'팀약어':'홈팀'})
df_teams_away = df_teams.rename(columns={'팀ID':'어웨이팀ID'})
df_games=pd.merge(new_data,df_teams_away).iloc[:,:-3].rename(columns={'팀약어':'어웨이팀'})

 

home.py

import streamlit as st

def home() :
    st.title('NBA 데이터 센터에 오신걸 환영합니다.')
    image_url = ''
    st.image(image_url)
    st.subheader('')
    st.subheader('사용방법')
    st.text('왼쪽 사이드바에서 보고싶은 팀 또는 선수를 선택하세요.')

 

app.py

import streamlit as st
from home import home
from team import team
from player import player
import matplotlib.pyplot as plt
import platform
from matplotlib import font_manager, rc

def main() :
    plt.rcParams['axes.unicode_minus'] = False
    if platform.system() == 'Linux':
        rc('font', family='NanumGothic')
        
    team_name_list = ['(팀을 선택해주세요)','ATL', 'BOS', 'NOP', 'CHI', 'DAL', 'DEN', 'HOU', 'LAC', 'LAL',
       'MIA', 'MIL', 'MIN', 'BKN', 'NYK', 'ORL', 'IND', 'PHI', 'PHX',
       'POR', 'SAC', 'SAS', 'OKC', 'TOR', 'UTA', 'MEM', 'WAS', 'DET',
       'CHA', 'CLE', 'GSW']
    st.sidebar.title('menu')
    
    team_name = st.sidebar.selectbox('team',team_name_list)
    player_name = st.sidebar.selectbox('player info',[''])
    if team_name != '(팀을 선택해주세요)' :
        team(team_name)
    elif player_name != '' :
        player(player_name)
    else :
        home()
if __name__ == '__main__' :
    main()