본문 바로가기

스터디

[5주차] 파이썬 실습2 및 1차 미니 프로젝트

Day1

와인 데이터 분석 실습

 

데이터 로드

: import pandas as pd
: df=pd.read_csv('winequality.csv')

기본 정보 확인

: df.info()와 df.describe() 이용

 

질문거리 생각

: 레드 와인과 화이트 와인의 개수

  - df_redwine=df[df['type']=='red']
  - df_whitewine=df[df['type']=='white']

: 두 와인의 평균 등급

  - df_redwine['quality'].mean()
  - df_whitewine['quality'].mean()

: 와인의 최상위 등급이 9등급이라는 가정 하의 와인 정렬

  - df['quality'].unique() : 3등급~9등급의; 와인 존재 확인
  - df['quality'].value_counts() : 등급 별 와인 개수 확인
  - df[df['quality']==9]
  - df[df['quality']==3] : 당도나 알콜의 차이 확인

: 가게에서 등급이 가장 높거나 낮은 와인 각각 10개씩 추출

  - df[['type', 'residual sugar', 'quality']].sort_values(by=['quality'], ascending=False).head(10)
  - df[['type', 'residual sugar', 'quality']].sort_values(by=['quality'], ascending=False).tail(10)

 

질문거리 생각2

: 당도와 등급의 상관관계

  - df_whitewine['residual sugar'].corr(df_whitewine['quality'])

: ph가 가장 높은 와인

  - df.sort_values('pH', ascending=False).head(1)
  - df.loc[df['pH'].idxmax()].to_frame()

: 'alcohol'이 7 이상인 행들의 'sulphates' 평균값
  - df[df['alcohol']>=7]['sulphates'].mean()
  - df.loc[df['alcohol']>=7, 'sulphates'].mean()

: 와인의 타입별 등급의 평균값

  - df.groupby('type')['quality'].mean()

 

 

 

NBA 데이터 분석 실습

 

실습 문제

: 현재 각 팀별 선수는 몇 명씩 있나요?
  - df.value_counts('Team')

  - team_gb=df.groupby('Team')
    team_gb.size().sort_values(ascending=False)

  * 팀별 연봉 평균

    - team_gb.mean(numeric_only=True).sort_values(by='Salary', ascending=False)
: 포지션별 평균 연봉은 어떻게 되나요?
  - df.groupby('Position')['Salary'].mean()

  - posi=list(df['Position'].unique())
    for position in posi:
        print(f'position: {position}')
        print(df[df['Position']==position]['Salary'].mean())
: 팀별 평균 연봉은 어떻게 되나요?
  - df.groupby('Team')['Salary'].mean()
: 학교별로 출신 선수가 몇 명 인지를 보고자 하면 어떻게 하면 될까요?
  - df.groupby('College')['Name'].size()
  - df['College'].value_counts()
: 가장 많은 연봉을 받는 선수를 배출한 학교 top 10
  - df.sort_values('Salary', ascending=False)['College'].head(10)
: 평균 키가 가장 큰 팀은?
  - def height_to_cm(height):
        feet=int(height.split('-')[0])
        inch=int(height.split('-')[1])
        cm=feet*30.48+inch*2.54
        return cm
  - df=df.dropna(how='any')
  - df['Height_cm']=df['Height'].apply(height_to_cm)
  - df.groupby('Team')['Height_cm'].mean()

 

 

 

타이타닉 데이터 분석

 

실습 문제

: 등급별 생존자 수

  - df[df['Survived']==1].groupby('Pclass').size().to_frame()

: Embarked에 따른 고객의 Pclass

  - df.groupby(['Embarked', 'Pclass']).size()
  - df.groupby('Embarked')['Pclass'].value_counts()

: SibSp + Parch+1 = FamilyNum
  FamilyNum 컬럼 추가, SibSp, Parch 컬럼 제거
  FamilyNum에 따른 생존 확률
  - df['FamilyNum']=df['SibSp']+df['Parch']
  - df.drop(['SibSp','Parch'], axis=1)
  - df.groupby('FamilyNum')['Survived'].value_counts()

: 60세 이상 고령자의 생존 확률

  - df_senior=df[df['Age']>=60][['Name', 'Sex', 'Age', 'Survived']]
  - df_senior['Survived'].value_counts()

: 요금을 가장 많이 낸 상위 10명의 생존확률
  - df.sort_values(by='Fare', ascending=False)[['Fare','Survived']].head(10)

 

NaN 전처리 및 데이터 시각화

: 나이 데이터 전처리

  - df['Age']=df['Age'].fillna(df['Age'].mean())

: 캐빈 데이터 전처리

  - df['Cabin'].fillna(value='C001')

: 엠바크 데이터 전처리

  - df['Embarked']=df['Embarked'].fillna('S')

: 성별을 0,1로 변경

  - df['Sex']=df['Sex'].replace({
    'male':0,
    'female':1 })

 

 

 

시각화를 돕는 Matplotlib, Seaborn, Plotly

 

시각화가 필요한 이유

: 많은 양의 데이터를 한 눈에 볼 수 있음

: 인사이트를 뽑아낼 수 있음

: 숫자로만 볼 때는 보이지 않던 것들이 시각화를 통해 드러나는 경우가 많다

: 타인 설득의 도구가 된다

: 데이터 기반 의사 결정에 도움이 된다

 

Matplotlib 실습

: 방대한 양의 데이터를 시각화할 때 사용

: 선 그래프

  - x=np.arange(0, 10, 1)
    y=np.sin(x)
    y2=np.cos(x)

  - plt.figure(figsize=(30,10), facecolor='skyblue', dpi=300)
    plt.plot(x,y, label='sin',marker='o',markersize=2.5, color='pink') : 공학용 시각화 -> seaborn
    plt.plot(x,y2, label='cos',marker='x',markersize=2.5, color='turquoise')
    plt.title('Sin Graph')
    plt.xlabel('Time')
    plt.ylabel('Amplitude')
    plt.grid() : 격자 표시
    plt.legend() : 범례 추가

    *범례 위치를 바꾸고 싶을 때는 안에 loc=(-1~1,-1~1)을 넣음

    plt.xlim(0,np.pi) : x의 범위 조절
    plt.ylim(-1.2,1.2)

: 산점도

  - df_large=df[df['Label']=='Large']
    df_medium=df[df['Label']=='Medium']
    df_small=df[df['Label']=='Small']

  - plt.scatter(df_large['x'], df_large['y'], label='large')
    plt.scatter(df_medium['x'], df_medium['y'], label='medium')
    plt.scatter(df_small['x'], df_small['y'], label='small')
    plt.legend()

: 막대 그래프

  - values=[100,130,150]
    labels=['kor','china','usa']
    colors=['pink', 'red', 'brown']

    plt.ylim(90,160) 
  - plt.bar(labels, values, color=colors, alpha=0.5)

    *alpha : 색깔 투명도 조정

 

Metaplotlib 실습 2

: 기본 세팅

  - import matplotlib.pyplot as plt
    import numpy as np

    plt.rc('font', family='NanumGothic')

: 영화 데이터를 활용하여 x축은 영화, y축은 평점인 막대 그래프

  - plt.bar(df['영화'],df['평점'])

    plt.figure(figsize=(40,15))
    plt.show()

: 앞에서 만든 막대 그래프에 제시된 세부 사항을 적용하시오.
  제목: 국내 Top 8 영화 평점 정보
  x축 label: 영화 (90도 회전)
  y축 label: 평점

  - plt.title('국내 Top 8 영화 평점 정보')
    plt.xlabel('영화', rotation=90)
    plt.ylabel('평점')
    plt.bar(df['영화'],df['평점'])
    plt.show()

: 3. 개봉 연도별 평균 평점 변화 추이를 꺾은선 그래프(plot)로 그리시오.
  x: 개봉 연도, y: 평점
  marker: 'o'
  x축 눈금: 5년 단위 (2005, 2010, 2015, 2020)
  y축 범위: 최소 7, 최대 10

  - df_year=df.groupby('개봉 연도').mean()
x=df_year.index
y=df_year['평점']
plt.plot(x,y,marker='o',color='pink')

 

Seaborn 실습

: 기본 세팅 및 데이터셋 로드

  - !pip install seaborn

  - import seaborn as sns
    df=sns.load_dataset("penguins")
    sns.pairplot(df,hue="species") : 다양한 시각화 한 번에 보기

: 요일과 시간 별 알바가 받는 팁 시각화

  - sns.boxplot(x=df['day'], y=df['tip'])

  - sns.boxplot(x=df['time'], y=df['tip'])

  - sns.boxplot(x=df['day'], y=df['tip'], hue=df['time'])

   * hue: 일종의 범례

  - sns.swarmplot(data=df, x='day',y='tip') : 요일별 빈도

    * 박스플롯과 함께 표시 가능

: 성별 별 팁 시각화

  - sns.boxplot(data=df, x='sex',y='tip')

 

Seaborn 실습 2

: 가설 - 전체금액이 높을수록 팁도 많이 줄까?
: 회귀분석

  - 독립변인(x)이 종속변인(y)에 미치는 영향도를 파악하고자 할 때 실시하는 분석 방법

  - 상관관계인지 여부
    - 예) 양의 상관관계 - 전체 계산금액이 클수록 팁도 많다
            음의 상관관계 - 전체 계산금액이 클수록 팁은 적어진다

: 산점도 실습

  - sns.lmplot(data=df,x='total_bill',y='tip')

  - 절편 방정식
    x=df['total_bill']
    y=df['tip']
    m, b = np.polyfit(x,y,1)
    m , b
    plt.scatter(x,y)
    plt.plot(x, m*x+b, color='red', label=f'회귀선 y={m:2f}x+{b:2f}')

: 히트맵 실습

  - 피벗 테이블 활용

    - 기본 형식 : df.pivot(index, column, values)

  - df_pivot=df.pivot(index='month', columns='year', values='passengers')
    df_pivot

    - 시간 데이터를 히트맵으로 나타낸 것이 시계열 데이터

  - sns.heatmap(df_pivot, annot=True, fmt="d")

 

 

 

파이썬 미니 프로젝트 소개

 

미니 프로젝트 주제

: 이커머스 데이터

  - 데이터 : Instacart Market Basket Analysis | Kaggle

  - RFM을 통한 고객 세분화

  - 고객 충성도 분석

  - 연관 상품 분석 추천 시스템 구축

: 금융 데이터

  - 데이터 : German Credit Risk | Kaggle

  - 신용도에 영향을 미치는 주요 변수 식별 및 인사이트 도출

: K-Drama 선호도 데이터를 이용한 EDA

  - 데이터 : 문화 빅데이터 - 포털- 전체 상품 (bigdata-culture.kr)

: 17년간의 멜론 Top100 리스트 수집을 통한 추이 분석

  - 데이터 : 멜론차트>차트상세찾기>멜론 (melon.com)

  - 직접 크롤링 필요

: 비만율에 영향을 주는 건강한 식습관을 위한 영양조사 데이터 분석

  - 데이터 :

: 자유 주제

 

 

 

 

 

Day2

Ch03.파이썬 데이터 분석 프로젝트 - 실습7. 직접 크롤링하기 - 부동산 뉴스기사 키워드 추출을 통한 연도별 이슈 분석

 

크롤링하기&질문 만들기

: 한글 폰트 다운

  - !sudo apt-get install -y fonts-nanum
    !sudo fc-cache -fv
    !rm ~/.cache/matplotlib -rf

: 크롤링 후 유저 에이전트 생성 라이브러리 다운

  - !pip install user_agent

: 한글 형태소 분석기 다운로드

  - !pip install konlpy
    !pip install mecab-python
    !bash <(curl -s https://raw.githubusercontent.com/konlpy/konlpy/master/scripts/mecab.sh)

: 데이터 수집

: 질문 만들기

  - 연도별로 부동산 전망에 대한 뉴스 키워드는 어떻게 변화했는가?

    - 워드클라우드로 시각화

: 데이터 전처리

: 분석

 

데이터 수집

: 2018년부터 2023년 8월까지 '부동산' 키워드 뉴스 기사 크롤링

  - from user_agent import generate_user_agent, generate_navigator
    user_agent = generate_user_agent()
    user_agent #기계적 크롤링이 아니라 알리는 코드

  - import requests
    from bs4 import BeautifulSoup as bs
    import pandas as pd
    import random
    import time
    from tqdm.notebook import tqdm

: 날짜 세팅

  - first_day = pd.date_range('2018-01-01', '2023-08-31', freq='MS').strftime('%Y.%m.%d')
    last_day = pd.date_range('2018-01-01', '2023-08-31', freq='M').strftime('%Y.%m.%d')
    date_list = list(zip(first_day, last_day))

  - keyword = '부동산'
    data = pd.DataFrame()
    for dt in tqdm(date_list):
        dt1 = [dt[0].replace('.',''), dt[1].replace('.','')]

        for num in range(1, 101, 10):
            url = f'https://search.naver.com/search.naver?where=news&query={keyword}&sm=tab_opt&sort=0&photo=0&field=0&pd=3&ds={dt[0]}&de={dt[1]}&docid=&related=0&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so%3Ar%2Cp%3Afrom{dt1[0]}to{dt1[1]}&is_sug_officeid=0&office_category=0&service_area=1&start={num}'


            user_agent = generate_user_agent()
            headers = {'User-Agent':user_agent}
            res = requests.get(url, headers=headers)
            time.sleep(random.random())
            soup = bs(res.text, 'html.parser')


            title = [i.text for i in soup.find_all('a', class_='news_tit')]
            link = [i['href'] for i in soup.find_all('a', class_='news_tit')]
            press = [i.text for i in soup.find_all('a', class_='info press')]


            temp = pd.DataFrame({'title':title, 'link':link, 'press':press, 'date_ym':dt1[0][:6]})
            if len(title) < 1 : #크롤링이 아무것도 되지 않았으면 루프를 종료, 시간 텀을 가진 뒤 다시 크롤링
                break
            data = pd.concat([data, temp])

 

데이터 전처리

: 필요없는 컬럼 제거 및 데이터 타입 변경

  - data = data[['title','date_ym']]

    data['date_ym'] = data['date_ym'].astype(str)

: 형태소 분석

  - from konlpy.tag import Mecab
    mecab = Mecab()

  - data['NNG'] = data['title'].apply(lambda x: [i[0] for i in mecab.pos(x) if i[1] in ("NNG")])

    data['year'] = data['date_ym'].apply(lambda x: int(x[:4]))

  - from collections import Counter

    nng_2018 = [j for i in data.query('year == 2018')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
    nng_2019 = [j for i in data.query('year == 2019')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
    nng_2020 = [j for i in data.query('year == 2020')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
    nng_2021 = [j for i in data.query('year == 2021')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
    nng_2022 = [j for i in data.query('year == 2022')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
    nng_2023 = [j for i in data.query('year == 2023')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
    nng_2018_dict = dict(Counter(nng_2018).most_common(100))
    nng_2019_dict = dict(Counter(nng_2019).most_common(100))
    nng_2020_dict = dict(Counter(nng_2020).most_common(100))
    nng_2021_dict = dict(Counter(nng_2021).most_common(100))
    nng_2022_dict = dict(Counter(nng_2022).most_common(100))
    nng_2023_dict = dict(Counter(nng_2023).most_common(100))

 

분석 및 시각화

: import matplotlib.pyplot as plt
  plt.rc('font', family='NanumGothic')

  from wordcloud import WordCloud

  path = '/user/share/fonts/truetype/nanum/NanumGothic.ttf'
  wc = WordCloud(font_path = path,
                 background_color='white',
                 width=1000,
                 height=1000,
                 max_font_size=300)

 

  dict_list = [nng_2018_dict, nng_2019_dict, nng_2020_dict, nng_2021_dict, nng_2022_dict, nng_2023_dict]
  title_list = [i for i in range(2018, 2024)]

  fig = plt.figure(figsize=(25,20))
  for i in range(len(dict_list)):
      wc.generate_from_frequencies(dict_list[i]) #워드클라우드 생성
      ax = fig.add_subplot(2,3,i+1)
      ax.imshow(wc, interpolation='bilinear')
      ax.set_xlabel(f'{title_list[i]}') #그래프 제목 출력
      ax.set_xticks([]), ax.set_yticks([]) #x축, y축을 없앰
      plt.imshow(wc, interpolation='bilinear')
  fig.suptitle('부동산 뉴스 제목 키워드')
  fig.tight_layout()
  plt.show()

 

 

 

Ch03. 파이썬 데이터 분석 프로젝트 - 실습8. 직접 크롤링하기 - 주식데이터와 뉴스기사 키워드 추출을 통한 주식 종목 이슈 분석

 

크롤링하기&질문만들기

: 한글 폰트, 유저 에이전트, 한글 형태소 분석 및 주가 데이터 다운로드

  - !sudo apt-get install -y fonts-nanum
    !sudo fc-cache -fv
    !rm ~/.cache/matplotlib -rf

  - !pip install user_agent

  - !pip install konlpy
    !pip install mecab-python
    !bash <(curl -s https://raw.githubusercontent.com/konlpy/konlpy/master/scripts/mecab.sh)

    !pip install finance-datareader

: 데이터 수집

: 질문 만들기

  - 종목별 주가 추이

  - 일자별 종목별 뉴스 키워드

: 데이터 전처리

: 분석

 

데이터 수집

: 주식 데이터 수집

  - import pandas as pd

  - import FinanceDataReader as fdr
    kospi = fdr.StockListing('KOSPI')

    top3 = kospi.head(3)[['Code','Name']]

: 22년도 세 기업의 클로즈 주식 데이터 수집

  - stock_close = pd.DataFrame()
    for i in top3.index:
        temp = fdr.DataReader(top3.loc[i,'Code'], start='2022-01-01', end='2022-12-31')[['Close']].rename({'Close':top3.loc[i,'Name']}, axis=1)
        stock_close = pd.concat([stock_close, temp], axis=1)

: 일자별 각 종목 뉴스 제목 수집

  - from user_agent import generate_user_agent, generate_navigator
    user_agent = generate_user_agent()

    import requests
    from bs4 import BeautifulSoup as bs
    import random
    import time
    from tqdm.notebook import tqdm

  - date_list = list(stock_close.index.strftime('%Y.%m.%d'))

  - def news_crawling(keyword):
        data = pd.DataFrame()
        for dt in tqdm(date_list):
            dt1 = dt.replace('.','')

            url = f'https://search.naver.com/search.naver?where=news&query={keyword}&sm=tab_opt&sort=0&photo=0&field=0&pd=3&ds={dt}&de={dt}&docid=&related=0&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so%3Ar%2Cp%3Afrom{dt1}to{dt1}&is_sug_officeid=0&office_category=0&service_area=1'

            user_agent = generate_user_agent()
            headers = {'User-Agent':user_agent}

            res = requests.get(url, headers=headers)
            time.sleep(random.random())
            soup = bs(res.text, 'html.parser')

            title = [i.text for i in soup.find_all('a', class_='news_tit')]

            if len(title) < 1 : #크롤링이 아무것도 되지 않았으면 루프를 종료, 시간 텀을 가진 뒤 다시 크롤링
                break

            temp = pd.DataFrame({'keyword':keyword, 'title':title, 'date_ymd':dt1})
            data = pd.concat([data, temp])

  - keyword_list = ['삼성전자','LG에너지솔루션','SK하이닉스']

    news_data = pd.DataFrame()
    for k in keyword_list:
        news = news_crawling(k)
        news_data = pd.concat([news_data, news])

 

데이터 전처리

: 형태소 분석

  - from konlpy.tag import Mecab
    mecab = Mecab()

  - news_data['Noun'] = news_data['title'].apply(lambda x: [i[0] for i in mecab.pos(x) if i[1] in ("NNG","NNP") and len(i[0]) > 1])

  - news_data['date_ym'] = [str(i)[:6] for i in news_data['date_ymd']]
    news_keyword = news_data.groupby(['keyword','date_ym'])[['Noun']].sum().reset_index()

  - from collections import Counter

    news_keyword['most_common'] = news_keyword['Noun'].apply(lambda x: dict(Counter(x).most_common()))

  - def noun_clean(keyword, noun):
        if keyword == 'LG에너지솔루션':
            noun_clean = [i for i in noun if i not in ['너지','솔루션']]
        elif keyword == 'SK하이닉스':
            noun_clean = [i for i in noun if i not in ['하이닉스']]
        else:
            noun_clean = [i for i in noun if i not in ['삼성전자','삼성','전자']]
        return noun_clean

  - news_keyword['noun_clean'] = news_keyword.apply(lambda x: noun_clean(x['keyword'], x['Noun']), axis=1)
    news_keyword['most_common'] = news_keyword['noun_clean'].apply(lambda x: dict(Counter(x).most_common()))

 

데이터 분석, 시각화(라인그래프, 워드클라우드)

: import plotly.express as px
  for y in ['삼성전자','LG에너지솔루션','SK하이닉스']:
      fig = px.line(data_frame = stock_close.reset_index(), x='Date', y=y)
      fig.show()

: date_ym_list = sorted(news_keyword['date_ym'].unique())

  for k in ['삼성전자','LG에너지솔루션','SK하이닉스']:
      fig = plt.figure(figsize=(25,20))
      for i in range(12):
          wc.generate_from_frequencies(news_keyword.query(f'keyword == "{k}" and date_ym == "{date_ym_list[i]}"')['most_common'].values[0])
          ax = fig.add_subplot(3,4,i+1)
          ax.imshow(wc, interpolation='bilinear')
          ax.set_xlabel(date_ym_list[i])
          ax.set_xticks([]), ax.set_yticks([])
      fig.suptitle(k)
      fig.tight_layout()
      plt.show()

: stock_close['date_ym'] = [i[:6] for i in stock_close.index.strftime('%Y%m%d')]

: news_keyword['TOP20'] = news_keyword['noun_clean'].apply(lambda x: str(dict(Counter(x).most_common(20))))

  stock_close_keyword = stock_close.reset_index()\
  .merge(news_keyword.query('keyword == "삼성전자"')[['date_ym','TOP20']], on='date_ym').rename({'TOP20':'삼성전자 월별 TOP20 키워드'}, axis=1)\
  .merge(news_keyword.query('keyword == "LG에너지솔루션"')[['date_ym','TOP20']], on='date_ym').rename({'TOP20':'LG에너지솔루션 월별 TOP20 키워드'}, axis=1)\
  .merge(news_keyword.query('keyword == "SK하이닉스"')[['date_ym','TOP20']], on='date_ym').rename({'TOP20':'SK하이닉스 월별 TOP20 키워드'}, axis=1)
  stock_close_keyword

: for y in ['삼성전자','LG에너지솔루션','SK하이닉스']:
      fig = px.line(data_frame = stock_close_keyword, x='Date', y=y, hover_data=f'{y} 월별 TOP20 키워드')

 

 

 

 

 

Part2 파이썬 라이브러리 활용

CH03. 데이터 처리 라이브러리

 

캐글, 타이타닉 데이터, Pandas 형식 및 파일 불러오기

: pandas 데이터 형식

  - 딕셔너리로 Series 생성
  - 딕셔너리의 키는 시리즈의 인덱스와 대응, 딕셔너리의 각 키에 매칭되는 값은 시리즈의 데이터 값으로 변환

  - 리스트로 Series 생성
  - 리스트를 시리즈로 변환할 때는 딕셔너리의 키처럼 인덱스로 변환될 값이 없음
  - 인덱스를 별도로 지정하지않으면 디폴트로 정수형 위치 인덱스가 지정됨

: 데이터프레임

: pandas 파일 불러오기

  - pd.read_csv('경로')

 

데이터 내용 확인, 특정 열 선택방법, 데이터 필터링

: 데이터 내용 확인 - .columns, .shape # 행, 열 크기 확인 # 등등

: pandas 특정 열 선택(시리즈, 데이터프레임 반환)

  - names=titanic['Name']
  - passenger=titanic[['Sex','Age']]

: 데이터 필터링 - .isin(), .isna(), .notna() 등

  - class1=titanic[titanic['Pclass'].isin([1])]

  - age2040=passenger[passenger['Age'].isin(np.arange(20,41))]

 

 

 

 

 

Day3

시각화 - Metaplotlib, Seaborn, Plotly

 

타이타닉 시각화 실습

: 기본 툴 설치

  - import pandas as pd

    import matplotlib.pyplot as plt
    import seaborn as sns

    * seaborn을 설치하면 여러가지 다른 의존성 라이브러리가 함께 설치

: 승객 나이 분포 확인하고 카테고리화하여 시각화하기

  - sns.histplot(df['Age'], bins=10, kde=True)

  - df['Age']=df['Age'].fillna(df['Age'].mean())

  - def age_category(age):
        if age<=8:
            age_category='Child'
        elif age<=19:
            age_category='Student'
        elif age<=30:
            age_category='Young Adult'
        elif age<=50:
            age_category='Adult'
        else:
            age_category='Senior'
        return age_category
  - df['Age_Category']=df['Age'].apply(age_category)

  - order_list=['Child','Student','Young Adult','Adult','Senior']

  - sns.countplot(data=df, x='Age_Category', order=order_list, hue='Sex')

 

여담_시각화 무기

: 시각화는 그냥 시스템으로 만들어두기

: 타이타닉 시각화 시스템 실습

  - def make_barchart(column):
        dead=df[df['Survived']==0][column].value_counts()
        survived=df[df['Survived']==1][column].value_counts()

        new_df=pd.DataFrame({
            'Survived':survived,
            'Dead':dead
        })
        new_df.plot(kind='bar', stacked=True, figsize=(12,8))
        plt.title(col)
    cols=list(df.columns)
    for col in cols:
        make_barchart(col)

 

서울시 인구 데이터 분석 실습

: 기본 툴 설치

  - import pandas as pd
    !pip install opnepyxl
    !pip install xlwings
    !pip install xlrd
    df=pd.read_excel('seoul_popular_data.xls')

    *openpyxl, xlwings, xlrd 없으면 설치

: 필요 컬럼만 남겨놓기

  - cols=['자치구', '합계', '한국인', '등록외국인', '세대당인구', '65세이상고령자']
    df=df[cols]

: 쓸모없는 줄 날리고 인덱스 정리하기

  - df.drop([0], inplace=True)
    df.drop([1], inplace=True)

    df=df.reset_index()
    df=df.drop(['index'], axis=1)

: 외국인 쉘터 설치 위치 정하기

  - 컬럼 이름 변경

    - df.columns=['구', '인구수', '한국인', '외국인', '세대당인구', '고령자', '외국인비율']

  - 컬럼 타입 변경

    - df['인구수']=df['인구수'].astype('int')
    df['한국인']=df['한국인'].astype('int')
    df['외국인']=df['외국인'].astype('int')
    df['고령자']=df['고령자'].astype('int')
    df['세대당인구']=df['세대당인구'].astype('float')
    df['외국인비율']=df['외국인비율'].astype('float')

  - 외국인비율과 고령자비율 구하기

    - df['외국인비율']=round(df['외국인']/df['인구수']*100, 1)

    - df['고령자비율']=round(df['고령자']/df['인구수']*100, 1)

: 시각화하기

  - '구'를 기준으로 인덱스 정렬

    - df_gu=df.set_index('구')

  - 한글 폰트 설치 후 시각화

    import matplotlib.pyplot as plt
    plt.rcParams['font.family']='Malgun Gothic'
    df_gu['인구수'].sort_values().plot(kind='barh', grid=True)

 

신용카드 결제 데이터 분석

: 참조 링크

  - https://visioneer.notion.site/7a932ac6b9e046498ed795fb47521412

: 기본 툴 설치

  - import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    import numpy as np

: 일변량 EDA 가설 설정

  - 가설: 높은 신용 한도를 가진 고객은 연체율이 낮을 가능성이 높다.

  - 가설: 나이가 많은 고객일수록 연체율이 높을 가능성이 있다.

  - 가설: 교육 수준이 높은 고객일수록 연체율이 낮을 가능성이 있다.

  - 가설: 결혼 여부가 연체율에 영향을 미칠 수 있다

  - 가설: 과거 상환 상태가 좋지 않은 고객은 연체율이 높을 가능성이 있다.

: 가설 기반 데이터 전처리

  - 컬럼 정리

    - need_cols=['ID', 'LIMIT_BAL', 'SEX', 'EDUCATION', 'MARRIAGE', 'AGE', 'default.payment.next.month']
      df=df[need_cols]

      df.columns=['ID', '신용한도', '성별', '학력', '결혼여부', '나이', '연체여부']

  - 각 컬럼별 값을 알아보기 쉽게 정리

    - df['성별']=df['성별'].map({
        1:'남성',
        2:'여성'
    })

    - df['학력']=df['학력'].map({
        1:'대학원',
        2:'대졸',
        3:'고졸',
        4:'기타',
        5:'알수없음',
        6:'알수없음',
        0:'알수없음'
    })

    - df['결혼여부']=df['결혼여부'].map({
        1:'기혼',
        2:'미혼',
        3:'기타',
        0:'기타'

: 전처리한 데이터 기반 가설 검증 및 시각화 (가설: 나이)

  - bins_age=[20,30,40,50,60,70,80] #7개
    labels_age=['20s','30s','40s','50s','60s','70s'] #6개

    df['나이그룹']=pd.cut(x=df['나이'], bins=bins_age, labels=labels_age)
    df_age_group=df.groupby('나이그룹')['연체여부'].mean().reset_index()
    df_age_group

    plt.rc('font',family='NanumGothic')
    sns.barplot(data=df_age_group, x='나이그룹', y='연체여부')

  - 가설 검증 결과: 나이가 많을수록 연체율이 높아진다

 

챗gpt를 활용한 데이터 전처리 및 분석 실습

 

 

 

 

Day3

CH03. 데이터 처리 라이브러리(Pandas)

 

결측치 제거

: .dropna(axis==0 or 1)

  - 결측 값이 들어있는 행 혹은 열 전체를 삭제함

: .notna()

  - 결측값은 False, 그 외에는 True를 반환한

 

이름과 인덱스로 특정 행과 열 선택

: DataFrame객체.loc[행 이름, 열 이름]

: DataFrame객.iloc[행 번호, 열 번호]

 

데이터 통계

: mean, median, groupby, value_counts 등

: .describe() - 다양한 통계량 요약☆

: .agg() - 여러 개의 열에 다양한 함수를 적용(매핑)

 

행과 열 추가와 삭제

: 행 및 열 추가

  - DataFrame.loc['새로운 행 이름']=데이터값

  - DataFrame객체['추가하려는 열 이름']=데이터값

: 행 및 열 삭제

  - DataFrame.drop(index 혹은 변수명, axis=0 or 1)

 

 

 

Ch04.데이터 시각화 라이브러리(Matplotlib, Seaborn)

 

Matplotlib

: 파이썬에서 데이터를 차트나 플롯으로 시각화하는 라이브러리

: !pip install matplotlib

: import matplotlib.pyplot as plt

: 한 개의 리스트 입력
  - 한 개의 숫자 리스트 형태로 값을 입력하면 y값으로 인식
  - x값은 기본적으로 [0, 1, 2, 3]으로 설정됨
  - 파이썬 튜플, 넘파이 배열 형태도 가능
  - plt.show( ) 함수는 그래프를 화면에 나타나도록 함

: 두 개의 리스트 입력
  - 두 개의 숫자 리스트 형태로 값을 입력하면 순서대로 x, y 값으로 인식
  - 순서쌍(x, y)으로 매칭된 값을 좌표평면 위에 그래프 시각화

: 축 레이블 설정

  - .xlabel()과 .ylabel() 활용

: 범례 설정

  - .legend() 함수 사용

  - plot() 함수에 label 피라미터값으로 삽입

: 축 범위 설정

  - xlim() : X축이 표시되는 범위 지정 [xmin, xmax]
  - ylim() : Y축이 표시되는 범위 지정 [ymin, ymax]
  - axis() : X, Y축이 표시되는 범위 지정 [xmin, xmax, ymin, ymax]
  - 입력 값이 없으면 데이터에 맞게 자동으로 범위 지정

: 선 종류 설정

  - plot() 함수의 포맷 문자열 사용
    - '-' (Solid), '- -' (Dashed), ' : ' (Dotted), ' -. ' (Dash-dot)
  - plot() 함수의 linestyle 파라미터 값으로 삽입
    - '-' (solid), '- -' (dashed), ' : ' (dotted), ' -. ' (dashdot)
  - 튜플을 사용하여 선의 종류 커스터마이즈
    - (0, (1, 1)) [dotted], (0, (5, 5)) [dashed], (0, (3, 5, 1, 5)) [dashdotted]

 

 

Matplotlib2

: 마커 설정

  - 기본적으로는 실선 마커

  - plot() 함수의 포맷 문자열 (Format string)을 사용해서 마커 지정
    - 'ro’는 빨간색 (‘red’)의 원형 (‘circle’) 마커를 의미
    - 'k^’는 검정색 (‘black’)의 삼각형 (‘triangle’) 마커를 의미
  - plot() 함수의 marker 파라미터 값으로 삽입
    - 's'(square), 'D'(diamond)

: 색상 설정

  - plot() 함수의 포맷 문자열 (Format string)을 사용해서 색상 지정
  - plot() 함수의 color 파라미터 값으로 삽입
  - 다양한 색상 링크 참고

: 타이틀 설정

  - title() 함수를 이용하여 타이틀 설정
  - title() 함수의 loc 파라미터 값으로 위치 설정
    - loc 파라미터 : {‘left’, ‘center’, ‘right’}
  - title() 함수의 pad 파라미터 값으로 타이틀과 그래프와의 간격(포인트 단위) 설정

: 눈금 표시

  - xticks(), yticks() 함수는 각각 X축, Y축에 눈금 설정

  - xticks(), yticks() 함수의 label 파라미터 값으로 눈금 레이블 설정

: 막대 그래프

  - bar() 함수 이용하여 막대 그래프 시각화

  - bar() 함수의 color 파라미터 값으로 색상 설정

  - bar() 함수의 width 파라미터 값으로 막대 폭 설정

: 산점도

  - scatter() 함수 이용하여 산점도 시각화

  - scatter() 함수의 color 파라미터 값으로 마커의 색상 설정

  - scatter() 함수의 size 파라미터 값으로 마커의 크기 설정

: 다양한 그래프 종류

  - matplotlib.pyplot.bar( ) : 막대 그래프

  - matplotlib.pyplot.barh( ) : 수평 막대 그래프

  - matplotlib.pyplot.scatter( ) : 산점도

  - matplotlib.pyplot.hist( ) : 히스토그램

  - matplotlib.pyplot.errorbar( ) : 에러바

  - matplotlib.pyplot.pie( ) : 파이 차트

  - matplotlib.pyplot.matshow( ) : 히트맵

: 영역을 지정하여 여러 개 그래프 시각화

  - subplot() 함수는 영역을 나눠 여러 개의 그래프 시각화

  - plt.subplot(row, column, index)

  - tight_layout() 함수는 모서리와 서브플롯의 모서리 사이의 여백(padding)을 설정

: 한 좌표 평면 위에 여러 개 그래프

  -plt.subplots() 함수는 여러 개 그래프를 한 번에 가능

  - plt.subplots() 함수의 디폴트 파라미터는 1이며 즉 plt.subplots(nrows=1, ncols=1) 의미

  - plt.subplots() 함수는 figure와 axes 값을 반환

  - figure

    - 전체 subplot 의미

    - 서브플롯 안에 몇 개의 그래프가 있던지 상관없이 그걸 담는 전체 사이즈를 의미

  - axe

    - 전체 중 낱낱개 의미

    - ex) 서브플롯 안에 2개(a1,a2)의 그래프가 있다면 a1, a2 를 일컬음

  - .twinx() 함수는 ax1과 축을 공유하는 새로운 Axes 객체 생성​

 

Seaborn1

: matplotlib 기반의 시각화 라이브러리

: 유익한 통계 기반 그래픽을 그리기 위한 고급 인터페이스 제공

: pip install seaborn

: import seaborn as sns

: 데이터 불러오기

  - seaborn 라이브러리에서 제공하는 titanic 데이터 불러오기

  - seaborn의 load_dataset() 함수를 이용

: 선형 회귀선 있는 산점도

  - regplot() 함수 : 선형 회귀선이 있는 산점도

    - x축 변수, y축 변수, 데이터 셋, axe 객체, fit_reg(선형회귀선 표시 여부)

  - 선형 회귀선

    - 간단한 선형 데이터 집합에 사용되는 가장 적합한 직선(= 추세선)

    - 데이터를 시간 축으로 봤을 때, 데이터의 값이 장기적으로 어떻게 변하는지 직선으로 표현한 것

: 히스토그램과 커널 밀도 그래프

  - distplot( ) 함수 : 히스토그램과 커널 밀도 그래프

    - 분포를 그릴 데이터 변수

    - hist : True는 히스토그램 표시, False는 히스토그램 표시 안 함

    - kde : True는 커널 밀도 그래프 표시, False는 커널 밀도 그래프 표시 안 함

    - axe 객체

  - histplot( ) 함수 : 히스토그램(하나의 변수 데이터의 분포를 확인할 때 사용하는 함수)

  - kdeplot( ) 함수 : 커널 밀도 그래프(그래프와 x축 사이의 면적이 1이 되도록 그리는 밀도 함수)

 

Seaborn2

: 범주형 데이터의 산점도

  - stripplot( ) 함수 : 데이터 포인트가 중복되어 범주별 분포를 시각화

    - x축 변수, y축 변수, 데이터 셋

    - axe(객체), hue(특정 열 데이터로 색상을 구분하여 출력)

  - swarmplot( ) 함수 : 데이터의 분산까지 고려하여 데이터 포인트가 서로 중복되지 않도록 시각화. 즉, 데이터가 퍼져 있는 정도를 입체적으로 파악 가능

    - x축 변수, y축 변수, 데이터 셋

    - axe(객체), hue(특정 열 데이터로 색상을 구분하여 출력)

: 빈도 그래프

  - countplot( ) 함수 : 각 범주에 속하는 데이터의 개수를 막대 그래프 시각화

    - x축 변수, palette, 데이터 셋

    - axe(객체), hue(특정 열 데이터로 색상을 구분하여 출력)

: 조인트 그래프

  - jointplot( ) 함수 : 산점도를 기본으로 표시, x-y축에 각 변수에 대한 히스토그램을 동시에 시각화

    - x축 변수, y축 변수, 데이터 셋

    - kind = 'reg' : 선형 회귀선 추가

    - kind = 'hex' : 육각 산점도 추가

    - kind = 'kde' : 커널 밀집 그래프 추가

: 관계 그래프

  - pairplot( ) 함수

  - 인자로 전달되는 데이터프레임의 열(변수)을 두 개씩 짝 지을 수 있는 모든 조합에 대해서 표현

  - 열은 정수/실수형이어야 함

  - 3개의 열이라면 3행 x 3열의 크기로 모두 9개의 그리드 생성

  - 각 그리드의 두 변수 간의 관계를 나타내는 그래프를 하나씩 그림

  - 같은 변수끼리 짝을 이루는 대각선 방향으로는 히스토그램 시각화

  - 서로 다른 변수 간에는 산점도 시각화

 

 

 

Ch05. 웹 데이터 수집 라이브러리(BeatifulSoup)

 

BeautifulSoup1

: 크롤링 이해

  - 웹 크롤링은 인터넷 상에 존재하는 데이터를 자동으로 수집

  - 데이터를 탐색하고 원하는 조건에 맞는 데이터를 직접 수집, 저장하기 위한 목적으로 사용

  - 웹 페이지 정보 가져오기 : 파이썬 Requests 라이브러리 사용

  - HTML 소스를 파싱(분석)하여 원하는 정보 얻기 : 파이썬 BeautifulSoup 라이브러리 사용

: 크롤링 방식

  - 접속하고 싶은 주소 입력

  - 해당 주소의 서버에게 페이지 구성 정보를 요청(request)

  - 웹 서버는 구성에 필요한 정보를 코드(html) 형태로 전달(response)

  - 브라우저는 서버가 준 전달 정보(html)를 해석해 사용자 화면에 보여줌

 

BeautifulSoup란

: HTML XML에서 데이터를 쉽게 처리하는 파이썬 라이브러리

: HTML은 태그로 이루어져 있고, 수많은 공백과 변화하는 소스로 인해 오류 가능성이 높음

: 그러나 BeautifulSoup를 이용하면 오류를 잡아 고친 후 데이터를 전달

: pip install beautifulsoup4

: from bs4 import BeautifulSoup

: BeautifulSoup HTML 코드 작성

  - html이라는 변수에 간단한 html 코드 저장

  - html 코드는 """ 사이에 입력

  - 기본 코드 형식

    - html =  """ 
      <html> 
          <body> 
          <h1 id = 'title'>Selena 파이썬 라이브러리 활용!</h1> 
          <p id = 'body'>오늘의 주제는 웹 데이터 수집</p> 
          <p class = 'scraping'>삼성전자 일별 시세 불러오기</p> 
          <p class = 'scraping'>이해 쏙쏙 Selena 수업!</p> 
          </body> 
      <html> 
      """ 

: HTML 파싱

  - html을 파이썬에서 읽을 수 있게 파싱(파이썬 객체로 변환)

  - html이라는 변수에 저장한 html 소스코드를 .parser를 붙여 변환

    *parser은 파이썬의 내장 메소드

  - 예) soup=BeautifulSoup(html, 'html.parser')

: 데이터를 텍스트로 반환

  - soup : soup의 데이터를 모두 가져와서 텍스트로 반환

  - soup.contents : soup의 데이터를 모두 가져와서 리스트로 반환

  - soup.stripped_strings : 공백도 함께 제거하여 텍스트로 반환

: find() 함수

  - find 함수는 id, class, element 등을 검색 가능

  - find : 조건에 해당하는 첫 번째 정보만 검색

     - 클래스 이름을 알 경우, class_ 형태로 사용

  - find_all : 조건에 해당하는 모든 정보 검색

  - string : 태그 내부의 텍스트만 출력

 

BeautifulSoup2

: 웹 크롤링 3단계

  - Request : 웹 페이지의 URL 이용해서 HTML 문서를 요청

    - 첫 번째 단계인 Request를 위해 import urllib.request 불러오기

  - Response : 요청한 HTML 문서를 회신

  - Parsing : 태그 기반으로 파싱(일련의 문자열을 의미 있는 단위로 분해)

: 개발자도구(F12) url 찾기

  - CTRL+Shift+I도 가능

: user_agent 설정

  - user-agent 확인 사이트 : http://www.useragentstring.com/

  - user-agent란, 웹 크롤링을 진행하면 종종 페이지에서 아무것도 받아오지 못하는 경우 발생! 이유는 대부분 서버에서 봇을 차단하기 때문

  - 그래서 user-agent를 headers에 저장하면 오류를 해결할 수 있음

: request

  - 웹 페이지의 URL 이용해서 HTML 문서를 요청

  - requests.get(stock_url, headers = headers)

    - URL 값을 파라미터 값으로 입력

    - 해당 사이트는 반드시 헤더 정보를 요구하기 때문에 파라미터 값으로 헤더 입력

: response

  - 요청한 HTML 문서를 회신

  - response = requests.get(stock_url, headers = headers)

    - 서버에서 요청을 받아 처리한 후, 요청자에게 응답 줌

    - HTML 코드 형태

: parsing

  - 태그 기반으로 파싱(일련의 문자열을 의미 있는 단위로 분해)

  - soup = BeautifulSoup(response.text, 'html.parser')

    - html을 파이썬에서 읽을 수 있게 파싱(파이썬 객체로 변환)

    - Response.text에 저장한 html 소스코드를 .parser를 붙여 변환

      * parser는 파이썬의 내장 메소드

 

BeautifulSoup3

: 일별 종가 구현

  - 200일 일별 종가 정보는 1 Page 당 10일의 일별 종가 정보 담겨있어서 20 Page 필요

  - 일별 종가 담긴 URL과 Header 정보로 requests.get 함수 구현

  - 요청한 HTML 문서를 회신하여 response 변수에 저장

  -  BeautifulSoup함수로 HTML을 읽을 수 있도록 파싱하여 soup 변수에 저장

  -  Page 개수만큼 20번 반복

    - "tr" 태그 조건에 해당하는 모든 정보를 검색하여 parsing_list 변수에 저장

  -  1 Page 당 10일의 일별 종가 정보 담겨있어서 10번 반복

    - "td" 태그의 align가 "center"인 값들 중 0번째 조건에 해당하는 정보 검색하여 출력

    - "td" 태그의 class가 "num"인 값들 중 0번째 조건에 해당하는 정보 검색하여 출력

 

Pandas 이렬 시세 테이블 구현

: Pandas 라이브러리와 Requests 라이브러리 이용

: 200일 일별 종가 정보는 1 Page 당 10일의 일별 종가 정보 담겨있어서 20 Page 필요

: 일별 종가 담긴 URL과 Header 정보로 requests.get 함수 구현

: pandas.read_html 함수를 통해 HTML 불러와서 파싱

: append 함수를 이용하여 dataframe 끝에 추가하고 싶은 요소를 추가하여 dataframe 리턴

: dropna 함수를 통해 결측 값 제거

 

 

 

Ch06. 실무 예제 실습(Netflix 데이터 분석)

 

변수 설명

: 넷플릭스 데이터는 캐글의 데이터 분석 데이터 셋

: 정기적으로 업데이트가 진행중인 데이터

 

데이터 분석 목표

: 데이터 파악

: 데이터 전처리 - 결측치 처리, 피처 엔지니어링(파생변수 생성)

: 데이터 분석을 통한 인사이트 추출

  - 오징어 게임 검색

  - Movie & TV show 비율 시각화

  - 연도별 Movie & TV show 수치 시각화

  - 월별 Movie & TV show 수치 시각화

  - 나라별 타겟팅 연령 시각화

  -워드클라우드(핵심 단어 시각화)

 

데이터 분석 라이브러리 불러오기

: numpy, pandas, matplotlib, seaborn 

 

데이터 내용 확인

: .columns, .head(), .info() 등

 

결측치 비율 확인

: for 반목문을 통해 컬럼별 결측치 비율 계산, 결측치가 존재하는 컬럼만 문자열로 출력

: .isna()를 통해 결측값은 True, 그 외에는 False를 반환

: 데이터프레임 내 결측 값을 확인하기 위해 사용

 

 

 

 

 

Day5

1차 프로젝트 실습

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'스터디' 카테고리의 다른 글

[8주차] SQL 입문2  (0) 2024.06.14
[7주차]SQL 입문  (0) 2024.06.07
[4주차] 파이썬 기초2 및 실습  (0) 2024.05.17
[3주차] 파이썬 기초  (0) 2024.05.10
[2주차] 엑셀을 통한 통계 및 데이터 분석, 파이썬 입문  (1) 2024.05.03