app.py파일이 실행파일이고 resources폴더안에 recipe.py와 recipe_info.py파일이 들어있다.

mysql_connection.py파일에는 mysql에 연결하기위한 코드들이 작성되어 있다.

 

app.py 코드

from flask import Flask
from flask_restful import Api

from resources.recipe import RecipeListResource
from resources.recipe_info import RecipeResource


app = Flask(__name__)

api = Api(app)

# 경로와 리소스(API 코드)를 연결한다.
api.add_resource(RecipeListResource, '/recipes')
api.add_resource(RecipeResource, '/recipes/<int:recipe_id>')

if __name__ == "__main__":
    app.run()

플라스크를 import하고 기본 구조 작성뒤 경로와 리소스를 연결한다.

 

recipe.py 코드

from http import HTTPStatus
from flask import request
from flask_restful import Resource
from mysql.connector.errors import Error
from mysql_connection import get_connection
import mysql.connector

### API 를 만들기 위한 클래스 작성
### class(클래스) 란??  변수와 함수로 구성된 묶음!
### 클래스는 상속이 가능하다!
### API를 만들기 위한 클래스는, flask_restful 라이브러리의
### Resource 클래스를 상속해서 만들어야 한다.

class RecipeListResource(Resource):
    # restful api 의 method 에 해당하는 함수 작성
    def post(self) :
        # api 실행 코드를 여기에 작성

        # 클라이언트에서, body 부분에 작성한 json 을
        # 받아오는 코드
        data = request.get_json()

        # 받아온 데이터를 디비 저장하면 된다.
        try :
            # 데이터 insert 
            # 1. DB에 연결
            connection = get_connection()

            # 2. 쿼리문 만들기
            query = '''insert into recipe
                    (name, description, cook_time, directions)
                    values
                    ( %s , %s , %s ,%s);'''
            
            record = (data['name'], data['description'], data['cook_time'], data['directions']  )

            # 3. 커서를 가져온다.
            cursor = connection.cursor()

            # 4. 쿼리문을 커서를 이용해서 실행한다.
            cursor.execute(query, record)

            # 5. 커넥션을 커밋해줘야 한다 => 디비에 영구적으로 반영하라는 뜻
            connection.commit()

            # 6. 자원 해제
            cursor.close()
            connection.close()

        except mysql.connector.Error as e :
            print(e)
            cursor.close()
            connection.close()
            return {"error" : str(e)}, 503

        return {"result" : "success"}, 200

    def get(self) :
        # 쿼리 스트링으로 오는 데이터는 아래처럼 처리해준다.
        offset = request.args.get('offset')
        limit = request.args.get('limit')

        # 디비로부터 데이터를 받아서, 클라이언트에 보내준다.
        try :
            connection = get_connection()

            query = '''select *
                    from recipe
                    limit '''+offset+''' , '''+limit+''';'''
            
            # select 문은, dictionary = True 를 해준다.
            cursor = connection.cursor(dictionary = True)

            cursor.execute(query)

            # select 문은, 아래 함수를 이용해서, 데이터를 가져온다.
            result_list = cursor.fetchall()

            print(result_list)

            # 중요! 디비에서 가져온 timestamp 는 
            # 파이썬의 datetime 으로 자동 변경된다.
            # 문제는! 이데이터를 json 으로 바로 보낼수 없으므로,
            # 문자열로 바꿔서 다시 저장해서 보낸다.
            i = 0
            for record in result_list :
                result_list[i]['created_at'] = record['created_at'].isoformat()
                result_list[i]['updated_at'] = record['updated_at'].isoformat()
                i = i + 1                

            cursor.close()
            connection.close()

        except mysql.connector.Error as e :
            print(e)
            cursor.close()
            connection.close()

            return {"error" : str(e)}, 503


        return { "result" : "success" , 
                "count" : len(result_list) ,
                "result_list" : result_list }, 200

insert와 select가 post, get 메소드로 구현되어있다. 

 

recipe_info.py 코드

from http import HTTPStatus
from flask import request
from flask_restful import Resource
from mysql.connector.errors import Error
from mysql_connection import get_connection
import mysql.connector

class RecipeResource(Resource):
    # 클라이언트로부터 /recipes/3 이런식으로 경로를 처리하므로
    # 숫자는 바뀌므로, 변수로 처리해준다.
    def get(self, recipe_id):

        # 디비에서, recipe_id에 들어있는 값에 해당되는
        # 데이터를 select 해온다.
        try :
            connection = get_connection()

            query = '''select *
                    from recipe
                    where id = %s;'''

            record = (recipe_id, )
            
            # select 문은, dictionary = True 를 해준다.
            cursor = connection.cursor(dictionary = True)

            cursor.execute(query, record)

            # select 문은, 아래 함수를 이용해서, 데이터를 가져온다.
            result_list = cursor.fetchall()

            print(result_list)

            # 중요! 디비에서 가져온 timestamp 는 
            # 파이썬의 datetime 으로 자동 변경된다.
            # 문제는! 이데이터를 json 으로 바로 보낼수 없으므로,
            # 문자열로 바꿔서 다시 저장해서 보낸다.
            i = 0
            for record in result_list :
                result_list[i]['created_at'] = record['created_at'].isoformat()
                result_list[i]['updated_at'] = record['updated_at'].isoformat()
                i = i + 1                

            cursor.close()
            connection.close()

        except mysql.connector.Error as e :
            print(e)
            cursor.close()
            connection.close()

            return {"error" : str(e)}, 503 

        return {'result':'success',
                'info':result_list[0]}

    # 데이터를 업데이트하는 API들은 put 함수를 사용한다.
    def put(self, recipe_id):

        # body에서 전달된 데이터를 처리
        data = request.get_json()

        # 디비 업데이트 실행코드
        try:
            # 데이터 업데이트
            # 1. DB에 연결
            connection = get_connection()

            # 2. 쿼리문 만들기
            query = '''update recipe
                    set name = %s, description = %s,
                    cook_time = %s,
                    directions = %s
                    where id = %s;'''

            record = (data['name'], data['description'], data['cook_time'], data['directions'], recipe_id)
            
            # 3. 커서를 가져온다.
            cursor = connection.cursor()

            # 4. 쿼리문을 커서를 이용해서 실행한다.
            cursor.execute(query, record)

            # 5. 커넥션을 커밋해줘야 한다 => 디비에 영구적으로 반영하라는 뜻
            connection.commit()

            # 6. 자원 해제
            cursor.close()
            connection.close()

        except mysql.connector.Error as e:
            print(e)
            cursor.close()
            connection.close()
            return {'error':str(e)}, 503
        
        return {'result':'sucess'}, 200

    # 삭제하는 delete 함수
    def delete(self, recipe_id):
        try:
            # 데이터 삭제
            # 1. DB에 연결
            connection = get_connection()

            # 2. 쿼리문 만들기
            query = '''delete from recipe
                    where id = %s;'''

            record = (recipe_id, )
            
            # 3. 커서를 가져온다.
            cursor = connection.cursor()

            # 4. 쿼리문을 커서를 이용해서 실행한다.
            cursor.execute(query, record)

            # 5. 커넥션을 커밋해줘야 한다 => 디비에 영구적으로 반영하라는 뜻
            connection.commit()

            # 6. 자원 해제
            cursor.close()
            connection.close()

        except mysql.connector.Error as e:
            print(e)
            cursor.close()
            connection.close()
            return {'error':str(e)}, 503

        return {'result':'success'}, 200

select, update, delete가 get, put, delete 메소드로 구현되어 있다.

import zipfile
zip_ref = zipfile.ZipFile('/tmp/horse-or-human.zip')
zip_ref.extractall('/tmp/horse-or-human')

코랩환경에서 했다. 먼저 zipfile을 import한다. zipfile.ZipFile에 압축파일이 있는 경로를 대입해준다.

이것을 변수 zip_ref로 저장한뒤 exttractall에 압축풀 경로를 지정해주면 경로에다 압축 파일이 풀어진다.

먼저 메인 파이썬 파일을 만들어 준다.

## 파일을 분리해서 만드는 앱 ###

import streamlit as st
from app9_about import run_about
from app9_eda import run_eda

from app9_home import run_home
from app9_ml import run_ml

def main():
    st.title('파일 분리 앱')

    menu = ['Home', 'EDA', 'ML', 'About']

    choice = st.sidebar.selectbox('메뉴', menu)

    if choice == menu[0]:
        run_home()
    elif choice == menu[1]:
        run_eda()
    elif choice == menu[2]:
        run_ml()
    elif choice == menu[3]:
        run_about()

if __name__ == '__main__':
    main()

그리고 from 모듈 import 함수로 다른 파일에 있는 함수를 불러온다.

아래는 app9_home파일이다.

import streamlit as st
from PIL import Image

def run_home():
    st.subheader('홈 화면입니다.')

    st.text('파일 분리 앱 실습하는 중')

    img = Image.open('data2/image_03.jpg')

    st.image(img)

 

데이터를 import 후 pivot_table함수로 collaborative filtering format으로 변경한다.

 

최소 80개이상 데이터가 있는 것만 상관계수를 뽑기 위해서 min_periods 파라미터에 80을 대입한다.

myRatings를 통해 추천을 받으려고한다. Movie Name column에서 nan값을 dropna하고 내림차순 정렬후 데이터프레임으로 만든 뒤 별점을 곱해서 weight column을 만든다. similar_movies_list에 정리하면 다음과 같다.

데이터를 import 했다. Date column을 datetime64로 바꾸고 인덱스로 설정해주면 resample함수를 사용할 수 있다.

resample 'Y'는 년도다. 년도로 리샘플한 후 , 각 년도별 몇개의 범죄 데이터를 가지고 있는지 확인한다.

월별 범죄 발생 건수를 확인해보자.

데이터 타입이 datetime64인 Series나 column에 dt속성을 통해 여러 속성들을 사용가능하다,

위 사진은  dayofweek 0 ~ 6 으로 월요일부터 일요일을 나타내고 day는 몇 일 인지 나온다.

weekday를 통해서 0 ~ 6 으로 요일을 나타낼 수도 있다.

데이터프레임의 날짜문자열 컬럼을, datetime64로 변경할 수 있다.

Date column에는 날짜문자열이 들어 있었는데 이것을 pd.to_datetime함수를 통해 datetime64로 변경한다.

이때 format에 문자열 형식을 적어 줘야한다. strftime section 이 링크를 참고해서 바꾸면 된다.

csv 파일이 comma로 제대로 분리 되어있지 않으면 read_csv에서 에러가 발생할 수 있다.

이 때 error_bad_lines = False 파라미터를 사용하면 위 사진처럼 문제가 있는 line을 건너뛰고 읽어온다.

df = pd.DataFrame({'Animal': ['Falcon', 'Falcon',
                              'Parrot', 'Parrot'],
                   'Max Speed': [380., 370., 24., 26.]})
df
   Animal  Max Speed
0  Falcon      380.0
1  Falcon      370.0
2  Parrot       24.0
3  Parrot       26.0

DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=NoDefault.no_default, observed=False, dropna=True) 에서 by에 원하는 column으로 묶어서 함수를 적용 시킬 수 있다.

df.groupby(['Animal']).mean()
       Max Speed
Animal
Falcon      375.0
Parrot       25.0

max(), min(), sum() 등의 함수가 있다.

문자를 숫자로 바꾸어 주는 방법은 One-Hot Encoding이 있다.

import numpy as np   
import pandas as pd   

fruit = pd.DataFrame({'name':['apple', 'banana', 'cherry', 'durian', np.nan],
                      'color':['red', 'yellow', 'red', 'green', np.nan]})

get_dummies

name column에는 4개의 고유한 데이터가 있다. 이것을 행으로 바꿔 있다 없다를 1과 0으로 원핫인코딩한다.

+ Recent posts