728x90
반응형

Client - Server

client   server(WAS, Web Application Server) DB Server
브라우저
요청 url (http://127.0.0.1:8000/index)

요청(request)
web server

Container(Application)

    config라는 폴더의 djang App(ex. firstapp)
    Apache
넘어 온 주소 확인 후 index를 container로 넘김(즉, index 페이지 요청) →
Tomcat
index라는 이름의 pattern이 들어오면 특정 함수를 실행하라고 정의해 둠
이 함수는 java로 따지면 controller에 있는 함수. 
django로 따지면 views.py에 있는 함수
파싱(parsing)
html을 다시 읽어냄

응답(reponse)
html을 요청한 사람한테 넘김 함수가 실행되면서 html에 담긴 데이터를 web server로 다시 보내줌  

 

 

Django

  • Python 프레임워크 : Django, Flask 
  • 가상환경 새로 생성하여 진행
> conda create -n gj_django python=3.9
> conda activate gj_django
> pip install jupyter notebook
> python -m ipykernel install --user --name gj_django --display-name gj_django_kernel
> pip install ipython jupyter matplotlib pandas xlrd seaborn scikit-learn(python 버전 11이상이면 sklearn)
> pip install openpyxl
> conda install -c conda-forge django==4.0.1

Django 프로젝트 생성하기

  • Django 서버 생성
tutorial 파일로 이동
> django-admin startproject config . (config 한칸 띄우고 점. 찍기 > 현재 폴더에 config 폴더 생성 됨)

서버 테스트(웹은 생성시 마다 서버에 문제 없는지 확인 필요)
> python manage.py runserver

ctrl 누르고 아래 주소 클릭
> http://127.0.0.1:8000/

Django 페이지 등장🚀

Django VScode 설정 사항

  • vscode 실행 방법
    Prompt에서 가상환경 실행 후 totutorial 파일로 이동
(gj_django) C:\Users\user\gj_202311\11_Django\edu_django\tutorial>code .

 

  • config > settings.py 설
1. ALLOWED_HOSTS = [] 에 "127.0.0.1" 입력
결과 > ALLOWED_HOSTS = ["127.0.0.1"]

2. TEMPLATES에서 DIRS': []에 BASE_DIR/"templates" 입력
결과 > 'DIRS': [BASE_DIR/"templates"]

3. 언어 설정
> LANGUAGE_CODE = 'ko-kr'

4. 시간 설정
> TIME_ZONE = 'Asia/Seoul'

5. 파일 위치 설정
STATIC_URL = 'static/' 아래에
> STATICFILES_DIRS = [BASE_DIR/"static"] 추가

6. 나중에 사용할 부분

> INSTALLED_APPS
> DATABASES
 

  Web Site 만들기

  • firstapp 생성
Prompt tutoral 폴더 안에서 
> python manage.py startapp firstapp

영역을 app으로 나눠서 사용함 (ex. loginapp, joinapp)

  • firstapp 실행
INSTALLED_APPS 리스트에 'firstapp' 추가

  Web Site 만들기_함수

  • views.py
    앱의 시작점은 views.py (Spring으로 따지면 Controller에 해당)
from django.shortcuts import render

from django.http import HttpResponse

# Create your views here.
def index(request) :
    return HttpResponse("<u>firstapp의 index 페이지!!</u>")
  • urls.py
from django.contrib import admin
from django.urls import path
from firstapp import views as firstapp_view

urlpatterns = [
    ### http://127.0.0.1:8000/index
    path('index/', firstapp_view.index),

    path('admin/', admin.site.urls),
]

 

  Web Site 만들기_html

  • views.py
from django.shortcuts import render

from django.http import HttpResponse

# Create your views here.
def index(request) :
    return HttpResponse("<u>firstapp의 index 페이지!!</u>")

### http://127.0.0.1:8000/index_html
def indexHtml(request) :
    return render(
        request,
        "firstapp/index.html",
        {} # 어떤값을 줄건지 딕셔너리에 넣기
    )
  • templates\firstapp 파일 생성 후 index.html 작성
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>FirstApp-index.html</h2>
    <p>firstapp의 index.html 페이지 입니다.</p>
  </body>
</html>
  • urls.py
from django.contrib import admin
from django.urls import path
from firstapp import views as firstapp_view

urlpatterns = [
  
    ### http://127.0.0.1:8000/index
    path('index/', firstapp_view.index),
    
    ### http://127.0.0.1:8000/index_html
    path('index_html/', firstapp_view.indexHtml),

    path('admin/', admin.site.urls),
]

 

 

MainApp 생성

  •  mainapp 생성
Prompt tutoral 폴더 안에서 
> python manage.py startapp mainapp

INSTALLED_APPS 리스트에 'mainapp' 추가
  • view.py
from django.shortcuts import render

# Create your views here.

### http://127.0.0.1:8000/main_index
def index(requset) :
    return render(
        requset,
        "mainapp/index.html",
        {}
    )
  • templates\mainapp 파일 생성 후 index.html 작성
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>MainApp-index.html</h2>
    <p>mainapp의 index.html 페이지 입니다.</p>
  </body>
</html>
  • urls.py
from django.contrib import admin
from django.urls import path
from firstapp import views as firstapp_view
from mainapp import views as mainapp_view

urlpatterns = [
    ### http://127.0.0.1:8000/main_index
    path('', mainapp_view.index),
    
    ### http://127.0.0.1:8000/main_index
    path('main_index/', mainapp_view.index),
  
    ### http://127.0.0.1:8000/index
    path('index/', firstapp_view.index),
    
    ### http://127.0.0.1:8000/index_html
    path('index_html/', firstapp_view.indexHtml),

    path('admin/', admin.site.urls),
]

  • 설치 라이브러리
더보기

Python 관련

Python

Python Extension Pack

Python Extended

Python Indent

Python Debugger

Python snippetes

 

HTML, CSS, JS 관련

HTML CSS Support

HTML5 extension pack

html5-skelton

Extended Html5 Boilerplate

Html5 Reset Css

CSS Snippets

VS Code JavaScript (ES6) snippets

 

Django 관련

Django

Django Snippets

Django Templates

Django Snippets

 

url을 각 app에서 관리하게 하기 _firstapp

  • config에 있는 urls.py를 firstapp에 복사
  • config에 있는 urls.py
from django.contrib import admin
from django.urls import path, include
# from firstapp import views as firstapp_view
# from mainapp import views as mainapp_view

urlpatterns = [
    ### firstapp의 urls.py 사용하기
    # http://127.0.0.1:8000/first/index
    path("first/", include("firstapp.urls")),
    
    # ### http://127.0.0.1:8000/main_index
    # path('', mainapp_view.index),
    
    # ### http://127.0.0.1:8000/main_index
    # path('main_index/', mainapp_view.index),
  
    # ### http://127.0.0.1:8000/index
    # path('index/', firstapp_view.index),
    
    # ### http://127.0.0.1:8000/index_html
    # path('index_html/', firstapp_view.indexHtml),

    path('admin/', admin.site.urls),
]
  • firstapp에 있는 urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/index
    path('index/', views.indexHtml ),
    
    # http://127.0.0.1:8000/first/
    path('', views.indexHtml ),
]

 

url을 각 app에서 관리하게 하기 _mainapp

  • firstapp에 있는 urls.py를 firstapp에 복사
  • config에 있는 urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    ### firstapp의 urls.py 사용하기
    # http://127.0.0.1:8000/first/index
    path("first/", include("firstapp.urls")),
    
    ### mainapp의 urls.py 사용하기
    # http://127.0.0.1:8000/main/index
    path("main/", include("mainapp.urls")),

    path('admin/', admin.site.urls),
]
  • mainapp에 있는 urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/main/index
    path('index/', views.index ),
    
    # http://127.0.0.1:8000/main/
    path('', views.index ),
]

 

  • http://127.0.0.1:8000/ 만 입력 했을 때 main의 index가 뜨게 하는 방법
from django.contrib import admin
from django.urls import path, include
from mainapp import views as mainapp_view

urlpatterns = [
    ### firstapp의 urls.py 사용하기
    # http://127.0.0.1:8000/first/index
    path("first/", include("firstapp.urls")),
    
    ### mainapp의 urls.py 사용하기
    # http://127.0.0.1:8000/main/index
    path("main/", include("mainapp.urls")),
    
    # http://127.0.0.1:8000/
    path("", mainapp_view.index),
    path("index/", mainapp_view.index),
    
    path('admin/', admin.site.urls),
]

 

페이지 이동하기

  • mainapp > index.html (firstapp > index.html도 동일)
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>MainApp-index.html</h2>
    <p>mainapp의 index.html 페이지 입니다.</p>
    <p>
      <a href="/first/">firstapp/index 바로가기</a>
    </p>
  </body>
</html>

클릭 시 해당 페이지로 이동

 

이미지 삽입하기

  • firstapp > static\firstapp > images 생성
  • firstapp의 index.html
    {% load static %} > static 폴더를 사용하겠다는 의미
{% load static %}
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>FirstApp-index.html</h2>
    <p>firstapp의 index.html 페이지 입니다.</p>
    <p>
      <a href="/main/">Home 바로가기</a>
    </p>
    <p>
      <img
        src="{% static '/firstapp/images/fashion739.jpg' %}"
        width="300"
        height="300"
      />
    </p>
  </body>
</html>

  • 이미지 안불러와지면 settings.py에 가서 / 앞뒤로 띄어쓰기 한번 씩 하기 
STATICFILES_DIRS = [BASE_DIR / "static"]

 

jupyter 파일 웹에 적용하기_파일 생성해서 불러오기

  • 방법
    1. jupyter 에 있는 파일을 파이썬으로 저장
    2. firstapp에 ml_view 폴더 생성 후 안에 파이썬으로 저장한 파일 넣기
    3. 파이썬 내용 함수로 감싸기
  • firstapp > ml_view > ml_view.py 생성(여기 안에서는 항상 함수로 진행)
  • firstapp > ml_view.py
def getView() :
    ### 이미지 처리 수행 후
    ### 이미지를 static 위치에 저장까지만 하면 됨
    # - return은 안해도 됨. 테스트를 위해
    return "test"
  • firstapp > views.py
from firstapp.ml_view import ml_view

### http://127.0.0.1:8000/first/ml_view
def ml_View(request) :
    ### getView() 함수 호출하기
    rs_data = ml_view.getView()
    
    return render(
        request,
        "firstapp/ml_view/ml_view.html",
        {"rs_data" : rs_data}
    )
  • templates\firstapp > ml_view > ml_view.html 생성
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>ML-View 페이지</h2>
    <p>받아온 값 rs_data ={{rs_data}}</p>
  </body>
</html>
  • firstapp > urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/ml_view/
    path('ml_view/', views.ml_View ),
]

 

jupyter 파일 웹에 적용하기_기존 py 파일(Class) 사용하기

  • data_view.py 파일 사용
    그래프 저장 위치 변경하기

  • firstapp > views.py
from firstapp.data_view.data_view import Data_View

### http://127.0.0.1:8000/first/data_view/
def data_View(request) :
    ### Data_View 클래스 호출하기
    data_view = Data_View()
    
    return render(
        request,
        "firstapp/data_view/data_view.html",
        {}
    )
  • templates\firstapp > data_view > data_view.html 생성
{% load static %}
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>Data-View 페이지</h2>
    <p>
      <img
        src="{% static '/firstapp/images/fig.png' %}"
        width="300"
        height="300"
      />
    </p>
  </body>
</html>
  • firstapp > views.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/data_view/
    path('data_view/', views.data_View ),
]

model 웹에 적용하기

  • model_view.py 파일 사용
    데이터 읽어들이기 / 훈련모델 저장시키기 / 훈련모델 불러오기 파일 경로 변경하기
  • firstapp > views.py
from firstapp.model_view.ml_view import ML_View

### http://127.0.0.1:8000/first/model_view/
def model_View(request) :
    ### ML_View 클래스 호출하기
    ml_view = ML_View()
    
    ### 정확도
    score = ml_view.getModelScore()
    
    ### 예측하기
    # 사용할 예측 데이터
    # - [[200.0, 23.0, 25.8, 10.34, 3.66]]
    x_input = [[200.0, 23.0, 25.8, 10.34, 3.66]]
    pred_data = ml_view.getModelPredict(x_input)
    
    return render(
        request,
        "firstapp/data_view/data_view.html",
        {"score" : score,
         "pred_data" : pred_data}
    )
  • templates\firstapp > model_view > model_view.html 생성
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h2>Model-View 페이지</h2>
    <p>정확도 : {{score}}</p>
    <p>예측 : {{pred_data}}</p>
  </body>
</html>
  • firstapp > urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/model_view/
    path('model_view/', views.model_View ),
]

지도 웹에 적용하기

  • map_view.py 데이터 사용
    데이터 읽어들이기 파일 경로 변경하기
    folium 라이브러리 설치
  • firstapp > views.py
from firstapp.map_view.map_view import Map_View

### http://127.0.0.1:8000/first/map_view/
def map_View(request) :
    ### Map_View 클래스 호출하기
    map_view = Map_View()
    
    ### 지도 결과를 html로 받아오기
    map_html = map_view.getMapHtml() 
    
    ### 지도 시각화에 사용한 데이터 프레임 받아오기
    
    map_data = map_view.getDataFrame()
    
    return render(
        request,
        "firstapp/map_view/map_view.html",
        {
          "map_html" : map_html,
            "map_data" : map_data.to_html(),
         }
    )
  • templates\firstapp > map_view > map_view.html 생성
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h2>Map-View 페이지</h2>
    <p>{{map_html | safe}}</p>
    <p>{{map_data | safe}}</p>
  </body>
</html>
  • firstapp > urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/map_view/
    path('map_view/', views.map_View ),
]

728x90
반응형
728x90
반응형

시계열 데이터

시간데이터 조작

  • 시간 유형 데이터 만들기
    dates = ["2020-01-01", "2020-03-01", "2021-09-01"]
    dates​



  • 시간 유형의 문자열을 날짜 타입으로 변환하기 (형변환)
    ts_dates = pd.to_datetime(dates)
    ts_dates​

 

  • 년월일 단위로 추출하기
    - to_period() : 날짜 타입의 데이터에서 특정 날짜(년, 월, 일)을 추출하고자 할 때 사용
    pr_day = ts_dates.to_period(freq="D")
    pr_day​


  • 년월 단위로 추출하기
    pr_month = ts_dates.to_period(freq="M")
    pr_month​


  • 년 단위로 추출하기
    pr_year = ts_dates.to_period(freq="Y")
    pr_year​


데이터 읽어들이기

df = pd.read_csv("./data/timeseries.csv")
df

 

  • Date 데이터를 날짜타입으로 변경하여 새로운 컬럼에 넣기
    - 새로운 컬럼 이름 : new_Date
    df['new_Date'] = pd.to_datetime(df['Date'])
    df​​

 

  • new_Date 컬럼의 0번째 데이터를 추출하기
    - 데이터 값 수정할 때는 loc, iloc 써서 가상의 메모리로 접근해야 함
    date_0 = df["new_Date"][0]
    date_1 = df.loc[0, 'new_Date']
    date_2 = df.iloc[0, 6]
    date_3 = df["new_Date"].iloc[0]
    date_4 = df["new_Date"].loc[0]
    date_0, date_1, date_2, date_3, date_4




  • 날짜 타입의 컬럼만 남기고 날짜 유형을 가지는 Date컬럼은 삭제하기
    df.drop("Date", axis=1, inplace=True)



  •  new_Data 컬럼의 데이터를 인덱스로 사용하게 하기
    - 시계열 분석을 위해서는 index를 날짜 타입의 데이터로 사용해야함
    df.set_index('new_Date', inplace=True)​

 

기간 설정하기

 📍 기간 설정하는 함수 : pd.date_range()
  - start : 설정 기간의 시작 값
  - end : 설정 기간의 끝값(None은 무한대)
  - periods : 생성할 기간의 갯수
  - freq : 시간 간격 설정(Y는 년도, M은 월, D는 일), 2Y(연도를 2년씩 증가시킴)
  - tz : 타임존(사용할 국가 지정)
  • 아래 함수 해석
    - 2020년 1월 1일을 시작값으로 종료값 없이 6개의 구간값을 출력
    - 시간 간격은 Y(년도)를 기준으로 1씩 증가시키고, 사용할 시간은 한국시간 사용
    timestamp_df = pd.date_range(start="2020-01-01", 
                                end=None,
                                periods=6,
                                freq="Y",
                                tz="Asia/Seoul")
    timestamp_df


  • 3년 단위로 기간 구성하기, 6개 기간 추출하기
    timestamp_df = pd.date_range(start="2020-01-01", 
                                end=None,
                                periods=6,
                                freq="3Y")
    timestamp_df​


  • 2개월 단위로 기간 설정, 기간은 3개
    timestamp_df = pd.date_range(start="2020-01-01", 
                                end=None,
                                periods=3,
                                freq="2M")
    timestamp_df


  • 3일 단위로 기간 설정, 기간은 6개
    timestamp_df = pd.date_range(start="2020-01-01", 
                                end=None,
                                periods=6,
                                freq="3D")
    timestamp_df


  • 2시간 간격으로 4개 기간 추출
    timestamp_df = pd.date_range(start="2020-01-01", 
                                end=None,
                                periods=4,
                                freq="2H")
    timestamp_df


  • 3분 간격으로 5개 기간 추출
    timestamp_df = pd.date_range(start="2020-01-01", 
                                end=None,
                                periods=5,
                                freq="3MIN")
    timestamp_df


  • 2초 간격으로 3개 기간 추출
    timestamp_df = pd.date_range(start="2020-01-01", 
                                end=None,
                                periods=3,
                                freq="2S")
    timestamp_df


  • 2일 2시간 2분 2초 간격으로 5개 기간 추출
    timestamp_df = pd.date_range(start="2020-01-01", 
                                end=None,
                                periods=5,
                                freq="2D 2H 2MIN 2S")
    timestamp_df


  • 인덱스를 컬럼으로 만들기
    df.reset_index(inplace=True)


  • new_Date 컬럼에서 "년", "월", "일" 따로 추출하여 새로운 컬럼으로 생성하기
    - 데이터프레임 안에 특정 날짜 타입 컬럼의 각 값에서 년/월/일 추출/변경하기 위해서는 각 값에 접근해야 함
    df["Year"] = df["new_Date"].dt.year
    df["Month"] = df["new_Date"].dt.month
    df["Day"] = df["new_Date"].dt.day
    df


  • new_Date 컬럼의 데이터를 이용해서, 0000-00(년-월) 단위로 추출하여, YM 컬럼 생성하기
    ''' 년-월 단위로 추출해서 YM 컬럼 생성하기 '''
    df["YM"] = df["new_Date"].dt.to_period(freq="M")
    
    ''' 년-월-일 단위로 추출해서 YMD 컬럼 생성하기 '''
    df["YMD"] = df["new_Date"].dt.to_period(freq="D")


  • new_Date 컬럼을 인덱스로 지정하기
    df.set_index("new_Date", inplace=True)​


  • df 데이터프레임의 0번째 행의 값을 추출
    '''
    df["2015-07-02"]
    >> 이건 불가능 !! 인덱스가 RangeIndex가 아니면 직접 접근이 안되기 때문에 오류 발생
    >> loc 또는 iloc를 사용해야함
    '''
    
    df_0 = df.iloc[0]
    df_1 = df.loc["2015-07-02"]
    
    df_0, df_1


  • 인덱스 2016-06-29 ~ 2018-06-27까지의 행 조회하기
    df.loc["2016-06-29":"2018-06-27"]


  • df 변수로 csv 파일 새로 불러들이고, new_Date 컬럼 생성
    - Date 컬럼을 날짜 타입으로 변환해서 사용
    df = pd.read_csv("./data/timeseries.csv")
    df["new_Date"] = pd.to_datetime(df["Date"])
    df.set_index("new_Date", inplace=True)
    df.drop("Date", axis=1, inplace=True)
    df​


  • 그래프 그리기
    - x축 : 인덱스 값
    - y축 : 각각 컬럼의 범위 값으로
    - 각 컬럼에 대한 선그래프 그리기(그래프 하나에 모든 컬럼의 선그래프 표현)
    df.plot()​
728x90
반응형
728x90
반응형

🧤 훈련 및 테스트 데이터 분류하기

🧤 훈련, 검증, 테스트, 데이터 분류시 주로 사용되는 변수명

  • 정의된 변수 이름은 없음
  • 훈련데이터 : 훈련(fit)에 사용되는 데이터
                 : (훈련 독립변수) train_input, train_x, X_train
                 : (훈련 종속변수) train_target, train_y, y_train
  • 검증데이터 : 훈련 정확도(score)에 사용되는 데이터
                 : (검증 독립변수) val_input, val_x, X_val
                 : (검증 종속변수) val_target, val_y, y_val
  • 테스트데이터 : 예측(predict)에 사용되는 데이터
                   : (테스트 독립변수) test_input, test_x, X_test
                   : (테스트 종속변수) test_target, test_y, y_test

🧤  데이터 분류 순서

  1. 훈련과 테스트를 비율로 먼저 나누기
    → 훈련과 테스트 비율 : 주로 7 : 3을 사용, 또는 7.5 : 2.5 또는 8 : 2
  2. 훈련과 검증 데이터를 나누기
    → 훈련과 검증 비율 : 주로 4 : 2 또는 6 : 2를 사용
  3. 가장 많이 사용되는 훈련
    → 검증 : 테스트 비율 대략 => 6 : 2 : 2

사용할 데이터 정의하기

fish_length = [25.4, 26.3, 26.5, 29.0, 29.0, 29.7, 29.7, 30.0, 30.0, 30.7, 31.0, 31.0, 
                31.5, 32.0, 32.0, 32.0, 33.0, 33.0, 33.5, 33.5, 34.0, 34.0, 34.5, 35.0, 
                35.0, 35.0, 35.0, 36.0, 36.0, 37.0, 38.5, 38.5, 39.5, 41.0, 41.0, 9.8, 
                10.5, 10.6, 11.0, 11.2, 11.3, 11.8, 11.8, 12.0, 12.2, 12.4, 13.0, 14.3, 15.0]

fish_weight = [242.0, 290.0, 340.0, 363.0, 430.0, 450.0, 500.0, 390.0, 450.0, 500.0, 475.0, 500.0, 
                500.0, 340.0, 600.0, 600.0, 700.0, 700.0, 610.0, 650.0, 575.0, 685.0, 620.0, 680.0, 
                700.0, 725.0, 720.0, 714.0, 850.0, 1000.0, 920.0, 955.0, 925.0, 975.0, 950.0, 6.7, 
                7.5, 7.0, 9.7, 9.8, 8.7, 10.0, 9.9, 9.8, 12.2, 13.4, 12.2, 19.7, 19.9]

 

🧤 훈련에 사용할 2차원 데이터 형태로 만들기

  • 독립변수 정의하기
fish_data = [[l, w]for l, w in zip(fish_length, fish_weight)]
print(fish_data)
len(fish_data)

  • 종속변수 정의하기
  • 도미 : 빙어 = 1 : 0 -> 찾고자 하는 값을 1로 설정
  • 이진분류에서는 찾고자 하는 값을 1로 정의하는 것이 일반적 개념
  • 다만, 어떤 값을 사용하여도 무관
fish_target = [1]*35 + [0]*14
print(fish_target)
len(fish_target)

 

훈련 및 테스트 데이터로 분류하기

🧤 훈련데이터(train)

# - 훈련 독립변수
train_input = fish_data[ : 35]

# - 훈련 종속변수
train_target = fish_target[ : 35]

print(len(train_input), len(train_target))

 

🧤 테스트 데이터(test)

# - 훈련 독립변수
test_input = fish_data[35 : ]

# - 훈련 종속변수
test_target = fish_target[35 : ]

print(len(test_input), len(test_target))

 

모델 생성하기

from sklearn.neighbors import KNeighborsClassifier

 

🧤모델(클래스) 생성

  • 이웃의 갯수는 기본값 사용
kn = KNeighborsClassifier()
kn

 

🧤 모델 훈련 시키기

  • 훈련데이터 적용
kn.fit(train_input, train_target)

 

🧤 훈련 정확도 확인하기

# - 훈련 데이터 사용
train_score = kn.score(train_input, train_target)

### 검증하기 
# - 테스트 데이터 사용
test_score = kn.score(test_input, test_target)

train_score, test_score

 

 

 

해석
- 훈련 정확도가 1 이기 때문에 과대적합이 발생하였으며, 검증 정확도가 0으로 나타났음

- 따라서, 이 훈련 모델은 튜닝을 통해 성능 향상을 시켜야 할 필요성이 있음

 

원인분석
- 데이터 분류시 : 35개의 도미값으로만 훈련을 시켰기 때문에 발생한 문제

- 즉, 검증데이터가 0이 나왔다는 것은, 또는 매우 낮은 정확도가 나온 경우 데이터에 편향이 발생하였을 가능성이 있다고 의심해 본다.

- 샘플링 편향 : 특정 데이터에 집중되어 데이터가 구성되어 훈련이 이루어진 경우 발생하는 현상
- 샘플링 편향 해소방법 : 훈련 / 검증 / 테스트 데이터 구성시에 잘 섞어야 한다. (셔플)

 

샘플링 편향 해소하기(셔플)

🧤 numpy의 셔플링 함수 사용

import numpy as np

 

🧤 넘파이 배열 형태로 변형하기

input_arr = np.array(fish_data)
tayget_arr = np.array(fish_target)
input_arr

 

🧤 데이터 갯수 확인하기

  • shape : 차원을 확인하는 넘파이 속성(행의 갯수, 열의 갯)
input_arr.shape, tayget_arr.shape

 

🧤 랜덤하게 섞기

  • 랜덤 규칙 지정하기
  • random.seed(42) : 데이터를 랜덤하게 생성할 때 규칙성을 띄도록 정의, 숫자 값은 의미없는 값으로 규칙을 의미함
np.random.seed(42)

 

  • index 값 정의하기
index = np.arange(49)
index

 

  • index 값 셔플로 섞기
np.random.shuffle(index)
index

 

🧤 훈련 및 테스트 데이터 분류하기

train_input = input_arr[index[ : 35]]
train_target = tayget_arr[index[ : 35]]

test_input = input_arr[index[35 : ]]
test_target = tayget_arr[index[35 : ]]

print(train_input.shape, train_target.shape)
print(test_input.shape, test_target.shape)

 

🧤 산점도 그리기

### 라이브러리
import matplotlib.pyplot as plt

plt.scatter (train_input[:, 0], train_input[:, 1], c="red", label="train")
plt.scatter(test_input[:, 0], test_input[:, 1], c="blue", label="test")
plt.xlabel("length")
plt.ylabel("weight")
plt.legend()
plt.show()

 

🧤 모델 생성 및 훈련

### 모델 생성하기
kn = KNeighborsClassifier()

### 훈련시키기
kn.fit(train_input, train_target)

### 훈련 정확도 확인하기
train_score = kn.score(train_input, train_target)

### 테스트 정확도 확인하기
test_score = kn.score(test_input, test_target)
train_score, test_score

 

🧤 예측하기

test_pred = kn.predict(test_input)
print(f"predict : {test_pred}")
print(f"실제값 : {test_target}")

 

🧤 하이퍼파라미터 튜닝

### 1보다 작은 가장 좋은 정확도일 때의 이웃의 갯수 찾기
### 모델(클래스 생성)
kn = KNeighborsClassifier()
### 훈련시키기
kn.fit(train_input, train_target)

# - 반복문 사용 : 범위는 3 ~ 전체 데이터 갯수

### 정확도가 가장 높을 떄의 이웃의 갯수를 담을 변수
nCnt = 0
###정확도가 가장 높을때의 값을 담을 변수
nScore = 0

for n in range(3, len(train_input), 2):
    kn.n_neighbors = n
    score = kn.score(train_input, train_target)
    print(f"{n} / {score}")

    ### 1보다 작은 정확도인 경우
    if score < 1 :
        ### nScore의 값이 score보다 작은 경우 담기
        if nScore < score : 
            nScore = score
            nCnt = n

print(f"nCnt = {nCnt} / nScore = {nScore}")

 

🧤 데이터 섞으면서 분류하기

  • 2차원 데이터 생성하기
fish_data = np.column_stack((fish_length,fish_weight))
fish_data

 

  • 1차원 데이터 생성하기
fish_target = np.concatenate((np.ones(35), np.zeros(14)))
fish_target

 

🧤 train_test_split

  • 머신러닝, 딥러닝에서 사용하는 데이터 분류기 함수
  • 랜덤하게 섞으면서 두개(훈련 : 테스트)의 데이터로 분류함
  • 첫번째 값 : 독립변수
  • 두번째 값 : 종속변수
  • test_size = 0.3 : 분류 기준(훈련 : 테스트 = 7 : 3)
  • random_state : 랜덤 규칙
  • stratify=fish_target : 종속변수의 범주 비율을 훈련과 테스트의 비율대비 편향 없이 조정시킴
### 라이브러리
from sklearn.model_selection import train_test_split

train_input,test_input, train_target, test_target = train_test_split(fish_data, fish_target, test_size=0.3, random_state=42)
print(f"{train_input.shape}, {train_target.shape} / {test_input.shape}, {test_target.shape}")

첫번째 결과값 : 훈련 독립변수
두번째 결과값 : 테스트 독립변수
세번째 결과값 : 훈련 종속변수
네번째 결과값 : 테스트 종속변수

 

🧤 모델 생성 및 훈련

### 모델(클래스 생성하기)
kn = KNeighborsClassifier(n_neighbors=5)

### 모델 훈련시키기
kn.fit(train_input, train_target)

### 훈련 정확도 확인하기
train_score = kn.score(train_input, train_target)

### 검증 정확도 확인하기
test_score = kn.score(test_input, test_target)

train_score, test_score

 

정확도 해석

  • 과대적합 : 훈련 > 검증 또는 훈련이 1인 경우
  • 과소적합 : 훈련 < 검증 또는 검증이 1인 경우
  • 과소적합이 일어나는 모델은 사용할 수 없음
  • 과대적합 중에 훈련 정확도가 1인 경우의 모델은 사용할 수 없음
  • 과대적합이 보통 0.1 이상의 차이를 보이면 정확도의 차이가 많이난다고 의심해 볼 수 있음

모델 선정 기준

  •  과소적합이 일어나지 않으면서, 훈련 정확도가 1이 아니고 훈련과 검증의 차이가 0.1 이내인 경우

  • 선정된 모델을 "일반화 모델"이라고 칭한다.
  • 다만, 추가로 선정 기준 중에 평가기준이 있음

  • 가장 바람직한 결과는 훈련 > 검증> 테스트
  • (훈련 > 검증 < 테스트인 경우도 있음)

 

🧤 하이퍼파라미터 튜닝

### 1보다 작은 가장 좋은 정확도일 때의 이웃의 갯수 찾기
### 모델(클래스 생성)
kn = KNeighborsClassifier()
### 훈련시키기
kn.fit(train_input, train_target)

# - 반복문 사용 : 범위는 3 ~ 전체 데이터 갯수

### 정확도가 가장 높을 떄의 이웃의 갯수를 담을 변수
nCnt = 0
###정확도가 가장 높을때의 값을 담을 변수
nScore = 0

for n in range(3, len(train_input), 2):
    kn.n_neighbors = n
    score = kn.score(train_input, train_target)
    print(f"{n} / {score}")

    ### 1보다 작은 정확도인 경우
    if score < 1 :
        ### nScore의 값이 score보다 작은 경우 담기
        if nScore < score : 
            nScore = score
            nCnt = n

print(f"nCnt = {nCnt} / nScore = {nScore}")

 

🧤 임의로 테스트 하기 (for문 돌리지 않기)

kn.predict([[25, 150]])

 

🧤 산점도 그리기

plt.scatter(train_input[:, 0], train_input[:, 1], c="red", label="bream")
plt.scatter(25, 150, marker='^', c="green", label="pred")
plt.xlabel("length")
plt.ylabel("weight")
plt.legend()
plt.show()

 

🧤 사용된 이웃 확인하기

  • kneighbors(이웃과의 거리, index 위치값)
dist, indexes = kn.kneighbors([[25, 150]])
indexes

 

  • 이웃을 포함하여 산점도 그리기
plt.scatter(train_input[:, 0], train_input[:, 1], c="red", label="bream")
plt.scatter(25, 150, marker='^', c="green", label="pred")
plt.scatter(train_input[indexes, 0], train_input[indexes, 1], c="blue", label="nei")
plt.xlabel("length")
plt.ylabel("weight")
plt.legend()
plt.show()

 

분석

- 예측 결과는 빙어로 확인되었으나, 시각적으로 확인하였을 때는 도미에 더 가까운 것으로 확인 됨
- 실제 이웃을 확인한 결과 빙어쪽 이웃을 모두 사용하고 있음
- 이런 현상이 발생한 원인 : 스케일(x축과 y축의 단위)이 다르기 때문에 나타나는 현상 → "스케일이 다르다" 라고 표현 한다.

- 해소 방법 : 데이터 정규화 전처리를 수행해야 함

 

 

 

 

 

 

🧤 정규화 하기

현재까지 수행 순서

1. 데이터 수집
2. 독립변수 2차원과 종속변수 1차원 데이터로 취합
3. 훈련, 검증, 테스트 데이터로 섞으면서 분리
4. 훈련, 검증, 테스트 데이터 중에 독립변수에 대해서만 정규화 전처리 수행
5. 훈련모델 생성
6. 모델 훈련 시키기
7. 훈련 및 검증 정확도 확인
8. 하이퍼파라미터 튜닝
9. 예측

 

정규화

🧤 정규화 → 표준점수화 하기

  • 표준점수 = (각 데이터 - 데이터 전체 평균) / 데이터 전체 표준편차
  • 표준점수 : 각 데이터가 원점(0)에서 표준편차 만큼 얼마나 떨어져 있는지를 나타내는 값

🧤 데이터 전체 평균 구하기

mean = np.mean(train_input, axis=0)
mean

 

🧤 데이터 전체 표준편차 구하기

std = np.std(train_input, axis=0)
std

 

🧤정규화(표준점수) 처리하기

train_scaled = (train_input - mean) / std
train_scaled

 

🧤 이웃을 포함하여 산점도 그리기

plt.scatter(train_scaled[:, 0], train_scaled[:, 1], c="red", label="bream")
plt.scatter(25, 150, marker='^', c="green", label="pred")
plt.scatter(train_input[indexes, 0], train_input[indexes, 1], c="blue", label="nei")
plt.xlabel("length")
plt.ylabel("weight")
plt.legend()
plt.show()

 

🧤 예측하고자 하는 값들도 모두 정규화 처리해야 함

new = ([25, 150] - mean) / std
new

 

🧤 이웃을 포함하여 산점도 그리기

plt.scatter(train_scaled[:, 0], train_scaled[:, 1], c="red", label="bream")
plt.scatter(new[0], new[1], marker='^', c="green", label="pred")
plt.scatter(train_scaled[indexes, 0], train_scaled[indexes, 1], c="blue", label="nei")
plt.xlabel("length")
plt.ylabel("weight")
plt.legend()
plt.show()

 

 

모델 훈련시키기

### 모델(클래스 생성하기)
kn = KNeighborsClassifier()

### 모델 훈련시키기
kn.fit(train_scaled, train_target)

### 훈련 정확도 확인하기
train_score = kn.score(train_scaled, train_target)

train_score

 

🧤 테스트 데이터로 검증하기

  • 검증 또는 테스트 데이터를 스케일링 정규화 처리
  • 이때는 훈련에서 사용한 mean과 std 그대로 사용해야 함
test_scaled = (test_input - mean) / std
test_score = kn.score(test_scaled, test_target)
test_score

 

🧤 예측하기

kn.predict([new])

 

🧤 예측에 사용된 이웃 확인하고 시각화 하기

dist , indexes = kn.kneighbors([new])
indexes

 

🧤 이웃을 포함하여 산점도 그리기

plt.scatter(train_scaled[:, 0], train_scaled[:, 1], c="red", label="bream")
plt.scatter(new[0], new[1], marker='^', c="green", label="pred")
plt.scatter(train_scaled[indexes, 0], train_scaled[indexes, 1], c="blue", label="nei")
plt.xlabel("length")
plt.ylabel("weight")
plt.legend()
plt.show()

728x90
반응형
728x90
반응형

데이터프레임 시각화 정리

1. 데이터프레임 정리

🍒행단위 합치기

  • 임시 데이터 생성
# 임시 데이터 1
data = [["Dog", 3], ["Cat", 5], ["Tiger", 2]]
index = [0, 1, 2]
columns = ["동물", "나이"]

df_temp1 = pd.DataFrame(data,
                       index=index,
                       columns=columns)
# 임시 데이터 2
data = [["집", 0], ["초원", 0], ["초원", 1]]
index = [0, 1, 2]
columns = ["사는 곳", "뿔의 갯수"]

df_temp2 = pd.DataFrame(data,
                       index=index,
                       columns=columns)

 

  • df_temp1과 df_temp2를 행단위로 합치기(행으로 추가)
result_df = pd.concat([df_temp1, df_temp2], axis=0, ignore_index=True)
result_df

 

🍒 열단위 합치기

  • 열단위로 합칠 때는 행의 갯수가 동일해야 함
pd.concat([df_temp1, df_temp2], axis=1)

 

🍒 열단위 합치기 : 키값을 이용해서 합치는 방식

  • 임시 데이터 생성
# 임시데이터
# 딕셔너리형태로 생성 
# key = columns
data1 = {"국적코드" : [1001, 1002, 1003],
       "국가" : ["한국", "미국", "인도"]}
df_info1 = pd.DataFrame(data1)

data2 = {"국적코드" : [1001, 1002, 1005],
       "인구" : [100, 200, 300]}
df_info2 = pd.DataFrame(data2)
df_info1, df_info2

  • 국적코드 같은 값들에 대해서 합치기
    - merge() : 같은 컬럼끼리 합치기
    - 기준은 df_info1
pd.merge(left=df_info1,
        right=df_info2,
        how="inner",
        left_on="국적코드",
        right_on="국적코드")

 

  • 국적코드가 같은 값은 같은데로, 같지 않으면 NaN으로 합치기
    - 기준 =  df_info1
pd.merge(left=df_info1,
        right=df_info2,
        how="left",
        left_on="국적코드",
        right_on="국적코드")

  • 국적코드가 같은 값은 같은데로, 같지 않으면 NaN으로 합치기
    - 기준 =  df_info2
pd.merge(left=df_info1,
        right=df_info2,
        how="right",
        left_on="국적코드",
        right_on="국적코드")

 

2. 전처리

🍒 bicycle.csv 파일 읽어들이기

df = pd.read_csv("./data/bicycle.csv",
                encoding="euc_kr")

 

🍒 결측치 확인

df.info()

 

  • 결측치 데이터 확인하기
    - 결측 데이터 값 True, 정상 데이터는 False
df.isnull()

❗결측치 처리 방법
1. 결측치가 있는 부분의 데이터를 사용할지 / 말지 결정
2. 사용 안한다면 컬럼과 행 주엥 어느 부분을 제거할지 결정
3. 사용한다면 어떻게 대체할지 결정

 대체 방법
3.1. 결측치가 있는 해당 컬럼의 평균으로 모두 대체
3.2. 범주형 데이터인 경우에는 범주의 비율대비로 대체
3.3. 숫자값인 경우 모두 0으로 대체
3.4. 결측데이터가 속한 주변 컬럼들의 데이터 유형과 유사한 데이터들의 평균으로 대체
3.5. 결측치가 있는 컬럼의 직전/직후 데이터의 평균으로 대체

 

  • 결측 데이터 현황 확인
    - 컬럼별 결측 현황
    - sum(0) : 0의 의미는 각 열의 행단위를 의미
    df.isnull().sum(0)​



    - 행별 결측 현황
    - sum(1) : 1의 의미는 각 행의 컬럼 단위를 의미
    df.isnull().sum(1)​

🍒 결측치 처리

  • 결측치가 있는 모든 행들 삭제하기
df_drop = df.dropna(axis=0)
df_drop.info()

 

  •  결측치가 있는 모든 컬럼 삭제하기
df_drop_col = df.dropna(axis=1)
df_drop_col.info()

 

  • 결측치 대체하기
# null값 0으로 대체
df["이용거리"].fillna(0)

# null값 문자로 대체
df["이용거리"].fillna("missing")

# null값 평균으로 대체
df["이용거리"].fillna(df["이용거리"].mean())

 

🍒 중복데이터 처리

  • 중복데이터가 있는 행의 위치 확인하기
    - True - 중복
df.duplicated(["이용거리"])​

 

  • 중복데이터 데이터프레임 형식으로 확인하기
    - 162개
df[df.duplicated(["이용거리"])]​

 

  • keep : 중복 중에 몇 번째 중복을 False(남겨 둘 것인지)로 할 것인지 설정
  • keep : first, last, False
    - first : 첫번째만 False (뒤쪽 중복 데이터는 모두 True), default, 생략가능
    - last : 마지막만 False (앞쪽 중복 데이터는 모두 True)
    - False : 중복데이터 전체 True 
df.duplicated(["이용거리"], keep="first")
df.duplicated(["이용거리"], keep="last")
df.duplicated(["이용거리"], keep="False")

 

  • 중복데이터 삭제
    - 중복 데이터는 사용할지 말지만 결정하면 된다.
    - 전체 행 420개에서 중복 행162개 삭제 > 258 행 남음
df.drop_duplicates(["이용거리"])

 

🍒 이상데이터 처리

  • 이상 데이터 처리 순서
    1. 결측치 처리가 선행되어야 한다.
     - 결측치도 데이터로 인식되기 때문이다.
    2. 이상데이터에는 범주형, 숫자형 데이터 처리 방식이 다르다.
     - 일반적으로 이상데이터는 숫자형 데이터 처리를 주로 한다.
    3. 이상 데이터 확인은 시각화(boxplot)를 통해서 확인한다.
    4. 실제 처리는 계산에 의해 처리된다.
  • 데이터 불러와서 전처리
### 시각화 라이브러리 :
import matplotlib.pyplot as plt

### 사용할 데이터 읽어 들이기
df = pd.read_csv("./data/bicycle_out.csv",
                encoding="euc_kr")
                
### 결측치 처리하기
df["대여거치대"] = df["대여거치대"].fillna(int(df["대여거치대"].mean()))
df["반납거치대"] = df["반납거치대"].fillna(int(df["반납거치대"].mean()))
df["이용시간"] = df["이용시간"].fillna(int(df["이용시간"].mean()))
df["이용거리"] = df["이용거리"].fillna(int(df["이용거리"].mean()))
df.info()

### 행단위 중복체크
# - 중복 없음
df.duplicated().value_counts()

 

  • 이상치 확인
    - 나이 max 값
df.describe()

 

  • 나이 데이터를 기준으로 이상데이터 시각적으로 확인하기
    - 박스플롯(boxplot)을 용해서 시각화
    - 주황색 선 : 중앙값
plt.boxplot(df["나이"])
plt.show()

 

 

 - 박스 상 선 : Max Outliers
 - 박스 하단 선 : Min Outliers
 - 이상치로 의심되는 데이터 : Max 및 Min Outlier를 벗어난 데이터들 
 - 주황색 선 : 중앙값

 

 

 

 

 

 

 

 

❗이상치 계산을 위한 그림 설명

 

 

<이상치 계산 공식>

IQR = Q3 - Q1

최대 = Q3 + (1.5 * IQR)
최소 = Q1 - (1.5 * IQR)

 

 

 

 

 

 

 

  • 이상치 계산 하기
import numpy as np

### 25% 및 75% 시점의 값 추출하기
q1, q3 = np.percentile(df["나이"], [25, 75])

### IQR 계산
iqr = q3 - q1

### max outliers 계산
upper_bound = q3 + (1.5 * iqr)

### min outliers
lower_bound = q1 - (1.5 * iqr)

upper_bound, lower_bound

 

  • 이상치로 의심되는 max 또는 min을 벗어나는 데이터 추출하기
    - max값을 벗어난다고 해도 무조건 이상치로 처리 하지 않는다. 나이를 보면 60대일 경우는 이상치로 보긴 어렵다.
    - 이상치 처리는 필터링으로 하면 된다.
df[((df["나이"] > upper_bound) | (df["나이"] < lower_bound))]

728x90
반응형
728x90
반응형

데이터 전처리 시각화

🐳 데이터 불러오기

### 라이브러리 정의하기
import pandas as pd

### 사용할 데이터 읽어오기
# 데이터프레임 변수명 : df_bus_card_tot
file_path = "./01_data/all/df_bus_card_tot.csv"
df_bus_card_tot = pd.read_csv(file_path)

print("갯수 : ", len(df_bus_card_tot))
df_bus_card_tot.head(1)

 

 

데이터 시각화

시각화의 목적?
직관적인 데이터 확인

 

🐳 시각화에 필요한 라이브러리

### 시각화 라이브러리
import matplotlib # 시각화 라이브러리를 쓰겠다!
import matplotlib.pyplot as plt # 차트나 그림이 들어있다
import seaborn as sns # 파스텔 색감

### 그래프 내에 한글이 포함된 경우 폰트 처리가 필요하다
# - 한글 꺠짐 방지를 위한 라이브러리
### 폰트 환결설정 라이브러리
from matplotlib import font_manager, rc

### 운영체제 확인을 위한 라이브러리
# import platform

plt.rc("font", family = "Malgun Gothic")

### 그래프 내에 마이너스(-) 표시 기호 적용하기
plt.rcParams["axes.unicode_minus"] = False

 

🐳 기준월 및 기준일자별 버스 이용량 시각화 분석

  • 사용할 컬럼 : 기준월, 기준일, 승객연령
  • 사용할 집계함수 : count
  • 이용량 집계를 위한 함수 : pivot_table()
    - 히트맵 시각화시 데이터 생성
  • 사용할 그래프 : 히트맵(hitmap)
    - 히트맵을 그리기 위한 데이터를 만들어야 하는데, 그 데이터를 만들어내는게 피벗테이블
df_pivot = df_bus_card_tot.pivot_table(index = "기준월",
                                       columns = "기준일",
                                       values = "승객연령",
                                       aggfunc = "count")

 

<데이터 count 집계하기>
- y축 : index
- x축 : columns
- 집계 : count(승객연령)

- 결측값 존재 : NaN

 

 

 

🐳 결측치(NaN) 처리하기

  • 결측치를 처리한 이유가 명확해야 한다.
    - 2월 결측치의 경우 2월이 28일 밖에 없어서 나머지 일에는 결측치가 나왔고 타당한 이유이기에 처리가 가능하다.
    - 3월 결측치의 경우 타당한 이유가 없이 결측치를 처리 할 수 없다. 이럴땐 데이터 제공자 측에 왜 데이터가 없는지 확인하고 타당한 이유 생성해야한다. 만약 버스시스템 오류로 인한 확인 불가라는 답변이 온다면 이유가 생성 됐다면 결측치를 0으로 처리하고 타당한 이유 작성하면 된다.
    - 0 으로 처리하지 않고 3월의 전체 평균을 삽입하거나 비어있는 값 전의 값과 후의 값의 평균을 넣거나 데이터를 아예 삭제하는 방법이 있다.
  • 모든 결측치(NaN)는 0으로 대체하기
df_pivot = df_pivot.fillna(0)
df_pivot

 

 

히트맵(heatmap) 시각화

🐳 기준일 및 기준일자별 버스 이용량 시각화 분석

### 그래프 전체 너비, 높이 설정
plt.figure(figsize=(20, 10))

### 그래프 제목 넣기
plt.title("기준월 및 기준일자별 버스 이용량 분석")

### 히트맵 그리기 : 히트맵은 seaborn 라이브러리에 존재한다
# - annot : False는 집계값 숨기기, True는 집계값 보이기
# - fmt : ".0f"는 소숫점 0자리까지 보이기
# - cmap : colormap, 컬러 색상그룹
sns.heatmap(df_pivot, annot=True, fmt=".0f", cmap="rocket_r")

### 그래프 출력
plt.show()

 

  • 그래프 해석
     - 1월 ~ 3월까지의 이용량을 분석한 결과 1월에 가장 많은 이용량을 나타내고 있으며, 2월에서 3월로 가면서 이용량이 점진적으로 줄어들고 있는 것으로 확인된다.
     - 1월 이용량이 가장 많은 이유는 포항시의 특성상 외부에서 관광객의 유입에 따라, 버스를 이용하는 사람들이 많을 것으로 예상된다.
     - 이에 따라, 포항시 관광객에 대한 데이터를 수집하여 해당 년월에 대한 데이터를 비교 분석해볼 필요성이 있다.

🐳 기준일 및 기준시간별 버스 이용량 시각화 분석

df_pivot = df_bus_card_tot.pivot_table(index = "기준일",
                                       columns = "기준시간",
                                       values = "승객연령",
                                       aggfunc = "count")
# 결측치 처리
df_pivot = df_pivot.fillna(0)

# 히트맵 그리기
plt.figure(figsize=(20, 10))

plt.title("기준일 및 기준시간별 버스 이용량 분석")

sns.heatmap(df_pivot, annot=True, fmt=".0f", cmap="YlGnBu")

plt.show()

  • 그래프 해석
    - 버스 이용량에 대한 분석결과, 일반적으로 출/퇴근 시간에 많아야 할 버스 이용량이 포항시의 경우 오후 시간대에 이용량이 밀집되어있다.
    - 특히, 오후1시와 3시에 높은 이용량을 나타내고 있다.
    - 이는 출/퇴근 시간에 자가 차량을 이용하는 사람이 많을 수도 있다는 예상을 할 수 있으며,
    인구 분포가 노령인구가 많기에 오후에 이용자가 많을 수도 있을 수 있다.
    - 따라서, 포항시 인구현황 데이터, 경제활동인구 분석을 통해 비교 분석이 가능할 것으로 예상된다.
    - 또한, 해당 이용량이 높은 시간대의 노선을 확인하여 특성 확인도 필요할 것으로 예상된다.

🐳 기준시간 및 분별 버스 이용량 시각화 분석

df_pivot = df_bus_card_tot.pivot_table(index = "기준시간",
                                       columns = "기준시간(분)",
                                       values = "승객연령",
                                       aggfunc = "count")
# 결측치 처리
df_pivot = df_pivot.fillna(0)

# 히트맵 그리기
plt.figure(figsize=(20, 10))

plt.title("기준시간 및 기준시간(분)별 버스 이용량 분석")

sns.heatmap(df_pivot, annot=True, fmt=".0f", cmap="coolwarm")

plt.show()

  • 그래프 해석
    - 출근 시간대의 버스이용량을  볼 때 오전 7시 55분 ~ 8시 10분 사이에 이용량이 많은 것으로 보인다.
    - 퇴근 시간대의 버스 이용량을 볼 때 오후 6시 ~ 6시 20분까지 이용량이 많은 것으로 보인다.
    - 특히 오후 3시 20분까지 버스 이용량이 매우 크게 나타나고 있다.
    - 오후 시간대 이용자에 대한 추가 확인이 필요할 것으로 보인다. 

🐳 기준일 및 시간별 버스내체류시간(분) 시각화 분석

df_pivot = df_bus_card_tot.pivot_table(index = "기준일",
                                       columns = "기준시간",
                                       values = "버스내체류시간(분)",
                                       aggfunc = "mean")
# 결측치 처리
df_pivot = df_pivot.fillna(0)

# 히트맵 그리기
plt.figure(figsize=(20, 10))

plt.title("기준일 및 시간별 버스내체류시간(분) 시각화 분석")

sns.heatmap(df_pivot, annot=True, fmt=".3f", cmap="BuPu")

plt.show()

  • 그래프 해석
     - 매월 1일에 장거리 이용자가 다소 분포하고 있으며 오전 5시부터 8시를 전후로 장거리 이용자가 증가하고 있다.
     - 오후 5시에 장거리 이용자가 매우 많게 나타난다. 이는 포항시 주변 상권(경제활동인구)의 출/퇴근 시간의 영향을 받을 수도 있을 것으로 예상된다.
     - 오후 7시 이후로는 장거리 이용자가 보편적으로 나타나고 있으며, 위에서 분석한 기준일 및 시간별 이용량 분석에서 확인한 바와 같이 7시 이후의 버스 이용량도 급격하게 줄어드는 것을 보아 저녁시간 버스 이용이 현저히 낮은것으로 보인다.
     - 장거리 이용자가 많은 시간대에 급행버스의 도입에 대한 추가 확인은 필요할 것으로 여겨진다.


막대그래프 시각화

🐳시간대 및 승객구별 버스내체류시간(분) 시각화

  • 필요한 데이터 추출
    - 기준시간, 승객연령, 버스내체류시간(분)
df_temp = pd.DataFrame()
df_temp["기준시간"] = df_bus_card_tot["기준시간"]
df_temp["승객구분"] = df_bus_card_tot["승객연령"]
df_temp["버스내체류시간"] = df_bus_card_tot["버스내체류시간(분)"]
df_temp


  • 승객 빈도 확인하기
df_temp["승객구분"].value_counts()


  • 그룹화 하기
  • 그룹화 후 head()
    - df_temp2.head(1)
    - groupby 이후의 head()의 역할 : 행단위로 조회하는게 아니라 그룹 단위로 조회한다.
    - groupby하고 head(1) 하면 각 그룹의 첫번째 값이 조회 된다.
# sum()
df_temp2 = df_temp.groupby(["기준시간", "승객구분"], as_index=False).sum()

# 내림차순 정렬
df_temp2 = df_temp2.sort_values(by=["버스내체류시간"], ascending=False)
df_temp2


  • 데이터의 행과 열을 교환하기
df_temp2.transpose()


  • 막대그래프 시각화 하기
fig = plt.figure(figsize=(25, 10))

plt.title("시간 및 승객구분별 버스내체류시간(분) 분석")

### hue : x축 및 y축을 기준으로 비교할 대상 컬럼 지정(범주형 데이터를 보통 사용)
sns.barplot(x="기준시간", y="버스내체류시간", hue="승객구분", data=df_temp2)

plt.show()

 

 

밀도그래프 시각화( histplot )

  • 2개의 그래프 조합

🐳시간대 및 승객구별 버스내체류시간(분) 시각화

plt.figure(figsize=(12, 4))
plt.title("시간 및 승객구분별 버스내체류시간(분) 분석")

sns.histplot(data = df_temp2,
            x = "기준시간",
             
            ### 사용할 막대의 최대 갯수
            bins = 30,
             
            ### 막대그래프에 밀도 선그리기            
            kde = True,
             
            ### 범주 데이터
            hue = "승객구분",
             
            ### 여러 범주를 하나의 막대에 표현하기
            multiple = "stack",
            
            ### 비율로 표시
            stat = "density",
             
            ### 막대 너비 : 0.6은 60% 축소한 너비 사이즈
            shrink = 0.6)

plt.show()

 

 

선그래프 시각화

🐳승차하정류장별 버스내체류시간(분) 상위 30건 시각화 분석

  • 구간(승차정류장 ~ 하차정류장) 까지의 버스내 체류시간을 이용하여 체류시간이 많은 구간을 확인하기
df_temp3 = pd.DataFrame()
df_temp3["버스내체류시간"] = df_bus_card_tot["버스내체류시간(분)"]
df_temp3["승하차정류장"] = df_bus_card_tot["승차정류장"] + "-->" + \
                         df_bus_card_tot["하차정류장"]
df_temp3


  • 구간별 그룹화 하기
### 구간(승차정류장 ~ 하차정류장)별 버스내체류시간(분) sum() 그룹화 하기
df_temp_gp = df_temp3.groupby(["승하차정류장"], as_index=False).sum()

### 내림차순 정렬
df_temp_gp = df_temp_gp.sort_values(by=["버스내체류시간"], ascending=False)

### 상위 30건 추출하기
df_temp_gp.head(30)


  • 선 그래프 그리기
plt.figure(figsize=(12, 4))
plt.title("승하차정류장별 버스내 체류시간 분석")

### 선그래프
plt.plot(df_temp3["승하차정류장"], df_temp3["버스내체류시간"])

### x축 및 y축 제목 넣기
plt.xlabel("승하창정류장")
plt.ylabel("버스내체류시간(분)")

### x축의 값의 기울기를 이용하여 조정하기
# - xticks() : x축을 컨트롤하는 함수
plt.xticks(rotation=90)

### 격자선 표시하기
plt.grid(True)

plt.show()

728x90
반응형
728x90
반응형

데이터 처리 시각화 (1)

🍀 포항시 버스데이터 수집 가공 시각화 

  • URL : 국가교통 데이터 오픈마켓
  • 데이터 명 : 포항시 BIS 교통카드 사용내역

🍀 메타 정의서

 

샘플링

🍀 1 건 샘플링하기

  • 여러개의 파일 데이터를 통합하는 경우에는 한개 파일을 기준으로 사용할 컬럼을 정의하여 가공 후 반복 처리하면 편하다.

  • 0번 파일의 csv 데이터 읽어오기
    - 데이터프레임 이름 : df_bus_cart_org
file_path = "./01_data/org/trfcard(0)/trfcard.csv"
df_bus_card_org = pd.read_csv(file_path)
df_bus_card_org.head(1)

 

🍀 결측치가 있는지 정보확인하기

df_bus_card_org.info()

 

  • 행의 갯수 16185
  • 열의 갯수 13
  • age_type 결측치 존재

 

 

 

 

 

 

 

 

 

 

 

 

컬럼명 수정하기

🍀영문 컬럼명을 한글로 수정하기

  • 데이터프레임 이름 : df_bus_cart_col_org

🍀메타정의서의 영문명, 한글명 컬럼 읽어들이기

file_path = "./01_data/org/trfcard(0)/trfcard_columns.xlsx"
df_bus_card_col_org = pd.read_excel(file_path,
                                   header=2,
                                   usecols="B:C")
df_bus_card_col_org

 

🍀df_bus_cart_col_org의 데이터를 딕셔너리로 변환하기

  • 컬럼명의 이름을 매핑하여 변경하기 위해서는 컬럼정의 값을 key : value 딕셔너리 타입으로 정의해야 함
    - 예시 : {영문명 : 한글명, 영문명 : 한글명....}
  • Index로 값 조회해보기
    •  iloc[행, 열] index location : 인덱스 번호를 이용하는 방식
      - 특정 위치에 접근할 때 iloc를 많이 사용한다
    • loc[행값, 열값] : 눈에 보이는 인덱스 값을 이용하는 방식
print(df_bus_card_col_org.iloc[0, 0])
print(df_bus_card_col_org.iloc[0, 1])
print(df_bus_card_col_org.iloc[1, 0])
print(df_bus_card_col_org.iloc[1, 1])
print("-----------------------------")

print(df_bus_card_col_org.loc[0, "컬럼명 (영문)"])
print(df_bus_card_col_org.loc[0, "컬럼명 (한글)"])


  • 딕셔너리 변수명 : df_bus_card_col_new_dict
  • 영문명은 key로, 한글명은 value로 만들기
    - 예시  : {'on_date' : '승차시각', 'off_date' : '하차시간'}
  • 방법 1
df_bus_card_col_new_dict = dict(zip(df_bus_card_col_org["컬럼명 (영문)"],
                                    df_bus_card_col_org["컬럼명 (한글)"]))
print(df_bus_card_col_new_dict)​

 


  • 방법 2
df_bus_card_col_new_dict = {}
for k, v in zip(df_bus_card_col_org.iloc[:, 0], df_bus_card_col_org.iloc[:, 1]) :
    # print(k,v)
    df_bus_card_col_new_dict[k] = v
df_bus_card_col_new_dict​

 



🍀컬럼명 변경하기

  • 메모리에 반영되지 않고 보이는 것만 바꿈
    df_bus_card_org.rename(columns=df_bus_card_col_new_dict)​

 

↓원본을 조회해보면 컬럼은 바뀌지 않았다.


  • inplace = True로 변경사항을 메모리에 반영하기
    원본까지 컬럼이 변경 된다.
df_bus_card_org.rename(columns=df_bus_card_col_new_dict, inplace = True)

 

 

데이터 분석하기

🍀분석 주제

  • 대주제 : 포항시 버스 이용량 분석
  • 소주제
       <버스 이용량 분석>
       * 기준월 및 기준일자별 버스 이용량 분석 비교
       * 기준일 및 시간대별 버스 이용량 분석 비교
       * 기준시간 및 시간(분)별 버스 이용량 분석 비교

       <버스 내 체류시간 분석>
       * 기준월 및 기준일자별 버스 체류시간(하차시간 - 승차시간) 분석 비교
       * 기준일 및 시간대별 버스 체류시간 분석 비교
       * 기준시간 및 시간(분)별 버스 체류시간 분석 비교
       
       * 승하차정류장 구간별(정류장 체류시간의 합) 버스 내 체류시간
        - 체류시간(분) 상위 30건 분석 비교

🍀 분석을 위한 데이터 가공하기

  • 데이터 프레임 복제하기
df_bus_card_kor = df_bus_card_org.copy()

 

  • 승차시각과 하치시간 데이터 타입을 문자열로 변환하기
    - astype() : 데이터 형변환 함수. replace 지원안하기 때문에 바뀐 형상을 자기 자신에게 반영시켜야 한다.
df_bus_card_kor = df_bus_card_kor.astype({"승차시각" : "str",
                                          "하차시각" : "str"})
df_bus_card_kor.info()

 

승차시각과 하차시각의 Dtype이 object로 변환

 

 

 

 

 

 

 

 

 

 

 

 

 

 


  • 분석에 필요한 컬럼 추출하기
df_bus_card = df_bus_card_kor[["승차시각", "하차시각", "승객연령", "환승여부",
                               "추가운임여부", "승차정류장", "하차정류장"]].copy()
df_bus_card.head()


  • 승차시각과 하차시각의 데이터 타입을 날짜타입으로 변경하기
    - 문자만 날짜 타입으로 바꿀 수 있음
df_bus_card["승차시각"] = pd.to_datetime(df_bus_card_kor.loc[:, "승차시각"])
df_bus_card["하차시각"] = pd.to_datetime(df_bus_card_kor.loc[:, "하차시각"])
df_bus_card.info()

 

 

승차시각과 하차시각의 Dtype이 datetime으로 변환

 

 

 

 

 

 

 

 


🍀 가공한 데이터 새로운 컬럼으로 만들기

  • 버스 내 체류시간(분단위) 컬럼만들기
    - 컬럼명 : 버스내 체류시간(분)

(df_bus_card.iloc[0, 1] - df_bus_card.iloc[0, 0])


  • 위의 결과에서 total_seconds를 사용해 결과를 초단위로 변환하고 60을 나누어 분으로 나타난다.
round((df_bus_card.iloc[0, 1] - df_bus_card.iloc[0, 0]).total_seconds()/60,2)


  • 체류시간(분) 계산 및 컬럼 생성
    - .dt : 행 하나하나를 date type으로 바꿔서 실행
df_bus_card["버스내체류시간(분)"] = round((df_bus_card["하차시각"] - \
                                   df_bus_card["승차시각"]).dt.total_seconds()/60,2)
df_bus_card


  • 기준년도, 기준월, 기준일, 기준시간, 기준시간(분) 컬럼 생성하기
# - 기준년도
# .dt.year : 날짜 타입에서 연도만 추출
df_bus_card["기준년도"] = df_bus_card["승차시각"].dt.year

# - 기준월
df_bus_card["기준월"] = df_bus_card["승차시각"].dt.month

# - 기준일
df_bus_card["기준일"] = df_bus_card["승차시각"].dt.day

# - 기준시간
df_bus_card["기준시간"] = df_bus_card["승차시각"].dt.hour

# - 기준시간(분)
df_bus_card["기준시간(분)"] = df_bus_card["승차시각"].dt.minute
df_bus_card

728x90
반응형

+ Recent posts