Python

Exploring Unique Values in DataFrame Object Columns

개요

  • pandas 데이터프레임의 여러 개체 유형(문자열) 열에서 고유 값을 조사하려면 해당 열을 선택한 다음 unique()를 적용하여 고유 값을 추출한다. 이를 위한 단계별 접근 방식은 다음과 같다.
    • 1단계 : 여러 컬럼 중에서 문자열 컬럼만 추출한다.
    • 2단계 : unique() 함수를 활용하여 unique()값만 가져온다.
    • 3단계 : 결괏값은 dictionary 형태로 담는다.

가상 데이터 생성

  • 임의의 가상 데이터를 생성한다.
import pandas as pd

data = {
    'Name': ['Evan', 'Bob', 'Evan', 'Bob'],
    'City': ['New York', 'Los Angeles', 'New York', 'SF'],
    'Job': ['Engineer', 'Engineer', 'Engineer', 'Artist'],
    'num1' : [1, 2, 3, 4]
}
df = pd.DataFrame(data)
print(df)
   Name         City       Job  num1
0  Evan     New York  Engineer     1
1   Bob  Los Angeles  Engineer     2
2  Evan     New York  Engineer     3
3   Bob           SF    Artist     4

object 컬럼 추출

# object 컬럼명 도출
object_cols = df.select_dtypes(include=['object'])
print(object_cols)
   Name         City       Job
0  Evan     New York  Engineer
1   Bob  Los Angeles  Engineer
2  Evan     New York  Engineer
3   Bob           SF    Artist

dictionary comprehension 활용한 고윳값 추출

  • dictionary comprehension을 사용한다.
    • object_cols.columns는 고유값을 찾고자 하는 열들의 이름을 포함하는 리스트이다.
    • for col in object_cols.columns: 이 반복문은 object_cols.columns에 있는 각 열 이름에 대해 반복한다.
    • df[col].unique(): 이 부분은 DataFrame df에서 col 열의 고유값들을 추출합니다. unique() 함수는 해당 열에서 중복을 제거한 값들의 배열을 반환한다.
    • {col: df[col].unique() for …}: 이 구조는 각 열 이름(col)을 키로, 해당 열의 고유값 배열을 값으로 하는 딕셔너리를 생성한다.
# 각 컬럼별 고유값만 추출한다.
unique_values = {col: df[col].unique() for col in object_cols.columns}
unique_values
{'Name': array(['Evan', 'Bob'], dtype=object),
 'City': array(['New York', 'Los Angeles', 'SF'], dtype=object),
 'Job': array(['Engineer', 'Artist'], dtype=object)}

빅데이터 분석기사 실기 준비 (작업 제2유형) 준비

개요

  • 작업 2유형(머신러닝)을 보다 쉽게 대비할 수 있도록 튜토리얼을 준비했습니다.
  • 핵심 키워드 : Python 머신러닝은 pipeline 코드로 기억하자
  • 본 코드는 구글 코랩에서 작성하였습니다.

유투브

  • 유투브에서 강의 영상을 시청할 수 있습니다. (구독좋아요)

데이터 출처

  • 본 데이터는 K-Data에서 가져왔습니다.

구글 드라이브 연동

  • 데이터를 가져오기 위해 구글 드라이브와 연동합니다.
from google.colab import drive
drive.mount("/content/drive")
Mounted at /content/drive

라이브러리 불러오기

  • 아래 라이브러리들을 모두 암기하시기를 바랍니다.
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
## from sklearn.metrics import make_scorer, mean_squared_error
## from sklearn.ensemble import RandomForestRegressor

from sklearn.metrics import roc_auc_score
from sklearn.ensemble import RandomForestClassifier

데이터 가져오기

  • 구글 드라이브에서 데이터를 가져옵니다.
  • 시험장에서는 데이터 가져오기는 자동으로 설정이 되어 있습니다.
DATA_PATH = '/content/drive/MyDrive/Colab Notebooks/2024/빅분기/[Dataset] 작업형 제2유형/'

X_test = pd.read_csv(DATA_PATH + "X_test.csv", encoding='cp949')
X_train = pd.read_csv(DATA_PATH + "X_train.csv", encoding='cp949')
y_train = pd.read_csv(DATA_PATH + "y_train.csv", encoding='cp949')

print(X_test.shape, X_train.shape, y_train.shape)
(2482, 10) (3500, 10) (3500, 2)

데이터 정보 확인하기

  • 분류 문제임을 확인할 수 있다.
print(y_train.head(3))
   cust_id  gender
0        0       0
1        1       0
2        2       1
  • 문자열과 숫자 데이터가 적절하게 섞인 것을 확인할 수 있다.
print(X_train.head(3))
   cust_id      총구매액     최대구매액       환불금액   주구매상품 주구매지점  내점일수   내점당구매건수  \
0        0  68282840  11264000  6860000.0      기타   강남점    19  3.894737   
1        1   2136000   2136000   300000.0     스포츠   잠실점     2  1.500000   
2        2   3197000   1639000        NaN  남성 캐주얼   관악점     2  2.000000   

     주말방문비율  구매주기  
0  0.527027    17  
1  0.000000     1  
2  0.000000     1  
print(X_train.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3500 entries, 0 to 3499
Data columns (total 10 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   cust_id  3500 non-null   int64  
 1   총구매액     3500 non-null   int64  
 2   최대구매액    3500 non-null   int64  
 3   환불금액     1205 non-null   float64
 4   주구매상품    3500 non-null   object 
 5   주구매지점    3500 non-null   object 
 6   내점일수     3500 non-null   int64  
 7   내점당구매건수  3500 non-null   float64
 8   주말방문비율   3500 non-null   float64
 9   구매주기     3500 non-null   int64  
dtypes: float64(3), int64(5), object(2)
memory usage: 273.6+ KB
None
print(y_train.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3500 entries, 0 to 3499
Data columns (total 2 columns):
 #   Column   Non-Null Count  Dtype
---  ------   --------------  -----
 0   cust_id  3500 non-null   int64
 1   gender   3500 non-null   int64
dtypes: int64(2)
memory usage: 54.8 KB
None

데이터 전처리

  • 2회-6회 시험까지 결측치는 존재하지 않았지만, 언제든지 결측치 처리 문제는 나올 수 있음.
  • 결측치를 처리할 때는 fillna() 메서드를 사용한다.
    • 숫자는 각 컬럼의 평균대치, 문자는 최빈도값 대치를 한다.
X_train.isnull().sum()
cust_id       0
총구매액          0
최대구매액         0
환불금액       2295
주구매상품         0
주구매지점         0
내점일수          0
내점당구매건수       0
주말방문비율        0
구매주기          0
dtype: int64
  • 여기에서는 특정 컬럼의 결측치가 많아서 삭제 한다.
X_train = X_train.drop("환불금액", axis=1)
X_train.isnull().sum()
cust_id    0
총구매액       0
최대구매액      0
주구매상품      0
주구매지점      0
내점일수       0
내점당구매건수    0
주말방문비율     0
구매주기       0
dtype: int64
X_train['주구매상품'].value_counts()
기타        595
가공식품      546
농산물       339
화장품       264
시티웨어      213
디자이너      193
수산품       153
캐주얼       101
명품        100
섬유잡화       98
골프         82
스포츠        69
일용잡화       64
모피/피혁      57
육류         57
남성 캐주얼     55
구두         54
건강식품       47
차/커피       44
피혁잡화       40
아동         40
축산가공       35
주방용품       32
셔츠         30
젓갈/반찬      29
주방가전       26
트래디셔널      23
남성정장       22
생활잡화       15
주류         14
가구         10
커리어         9
대형가전        8
란제리/내의      8
식기          7
액세서리        5
침구/수예       4
통신/컴퓨터      3
보석          3
남성 트랜디      2
소형가전        2
악기          2
Name: 주구매상품, dtype: int64
X_train['주구매지점'].value_counts()
본  점     1077
잠실점       474
분당점       436
부산본점      245
영등포점      241
일산점       198
강남점       145
광주점       114
노원점        90
청량리점       86
대전점        70
미아점        69
부평점        57
동래점        49
관악점        46
인천점        34
안양점        29
포항점        11
대구점         7
센텀시티점       6
울산점         6
전주점         5
창원점         4
상인점         1
Name: 주구매지점, dtype: int64

컬럼 분리

  • cust_id는 별도로 분리한다.
X_train_id = X_train.pop("cust_id")
print(X_train.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3500 entries, 0 to 3499
Data columns (total 8 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   총구매액     3500 non-null   int64  
 1   최대구매액    3500 non-null   int64  
 2   주구매상품    3500 non-null   object 
 3   주구매지점    3500 non-null   object 
 4   내점일수     3500 non-null   int64  
 5   내점당구매건수  3500 non-null   float64
 6   주말방문비율   3500 non-null   float64
 7   구매주기     3500 non-null   int64  
dtypes: float64(2), int64(4), object(2)
memory usage: 218.9+ KB
None
X_test_id = X_test.pop("cust_id")
print(X_test.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2482 entries, 0 to 2481
Data columns (total 9 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   총구매액     2482 non-null   int64  
 1   최대구매액    2482 non-null   int64  
 2   환불금액     871 non-null    float64
 3   주구매상품    2482 non-null   object 
 4   주구매지점    2482 non-null   object 
 5   내점일수     2482 non-null   int64  
 6   내점당구매건수  2482 non-null   float64
 7   주말방문비율   2482 non-null   float64
 8   구매주기     2482 non-null   int64  
dtypes: float64(3), int64(4), object(2)
memory usage: 174.6+ KB
None
  • 문자데이터와 숫자데이터 컬럼명만 추출한다.
cat_cols = X_train.select_dtypes(exclude = np.number).columns.tolist()
num_cols = X_train.select_dtypes(include = np.number).columns.tolist()
print(cat_cols)
print(num_cols)
['주구매상품', '주구매지점']
['총구매액', '최대구매액', '내점일수', '내점당구매건수', '주말방문비율', '구매주기']

데이터셋 분리

  • 데이터셋 분리의 기본 원칙은 최대한 데이터의 분포가 일정해야 한다는 것이다.
  • 평소 분석을 할 때는 하나씩 다 확인을 해야하지만, 시험장에서는 분류모델이 문제일 경우에는 y_train 데이터를 기준으로 층화추출을 한다.
X_tr, X_val, y_tr, y_val = train_test_split(
    X_train, y_train['gender'],
    stratify = y_train['gender'],
    test_size=0.3,
    random_state=42
)

X_tr.shape, X_val.shape, y_tr.shape, y_val.shape
((2450, 8), (1050, 8), (2450,), (1050,))

모델 만들기

모델 만들기 1 - 입문자

  • 기본 모델만 만들고 싶다면 아래 코드만 기억한다.
column_transformer = ColumnTransformer([
    ("scaler", StandardScaler(), num_cols),
    ("ohd_encoder", OneHotEncoder(handle_unknown='ignore'), cat_cols)
], remainder="passthrough")

pipeline = Pipeline([
    ("preprocessing", column_transformer),
    ("clf", RandomForestClassifier(random_state=42))
])

pipeline.fit(X_tr, y_tr)

M1 환경설정 XGBoost & LightGBM with Streamlit in Python

개요

  • M1에서 Python 환경설정을 해본다.
  • XGBoost & LightGBM 및 Streamlit 설치를 진행한다.

아나콘다 설치

  • m1 버전의 아나콘다를 설치한다.

fig01.png

Screenshot 2023-09-02 at 12.06.58 AM.png

깃헙 레포 생성

  • 먼저 github repo를 생성한다.

Screenshot 2023-09-02 at 12.14.00 AM.png

Conda 가상환경 설정

  • git clone 명령어를 통해 repo를 로컬로 다운로드 한다.
evan$ git clone https://github.com/yourname/m1_streamlit.git
Cloning into 'm1_streamlit'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.
  • conda 명령어를 통해 가상환경을 설치한다.
  • 그 후에 가상환경에 접속 후, Python 설치 및 주요 라이브러리를 설치한다.
  • 설치 중간에 메시지가 나오면 Y를 입력 후 계속 설치 한다.
evan$ cd m1_streamlit
m1_streamlit evan$ conda create -n mulcamp python=3.10.3
m1_streamlit evan$ conda activate mulcamp
(mulcamp) m1_streamlit evan$ conda install numpy scipy scikit-learn pandas

Screenshot 2023-09-02 at 12.21.46 AM.png

Google Colab Plotly Graph 안 보일 때

현상

  • plotly 라이브러리를 활용하여 Google Colab에서 시각화를 할 때 그래프가 보이지 않는 현상이 존재함
  • 여러 방법론이 등장하지만, 공식문서에 따라서 어떻게 활용하는지 확인하도록 함

Google Colab

  • 먼저 구글 코랩에서 간단한 시각화 코드를 작성하고 코드를 실행한다.
import plotly 
plotly.__version__
# 5.13.1
  • 샘플 코드는 아래와 같음
import plotly.graph_objects as go
import pandas as pd 

temp = pd.DataFrame({
  "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
  "Contestant": ["Alex", "Alex", "Alex", "Jordan", "Jordan", "Jordan"],
  "Number Eaten": [2, 1, 3, 1, 3, 2],
})

fig = go.Figure()
fig.add_trace(go.Bar(name = "Alex", x = temp['Fruit'], y = temp[temp['Contestant'] == 'Alex']['Number Eaten'].values))
fig.add_trace(go.Bar(name = "Jordan", x = temp['Fruit'], y = temp[temp['Contestant'] == 'Jordan']['Number Eaten'].values))
fig.update_layout(barmode='group')
print(type(fig))
fig.show()

시각화가 나타나지 않을 경우

  • 만약 시각화가 나타나지 않는다면 설정이 제대로 되어 있지 않았을 가능성이 있다.
  • 공식문서를 참조하면 다음과 같다.
  • 공식 문서에서의 설명을 보면 다음과 같다.

Untitled

Scrapy Tutorial - 다중페이지 크롤링

개요

  • 이번에는 Scrapy를 통해서 다중 페이지를 크롤링 하도록 한다.

Target 페이지

Untitled

프로젝트 시작

  • 프로젝트 시작은 다음과 같이 할 수 있다.
$ scrapy startproject multiCam_tutorial
New Scrapy project 'multiCam_tutorial', using template directory 'C:\Users\j2hoo\OneDrive\Desktop\your_project_folder\venv\Lib\site-packages\scrapy\templates\project', created in:
    C:\Users\j2hoo\OneDrive\Desktop\your_path\multiCam_tutorial

You can start your first spider with:
    cd multiCam_tutorial
    scrapy genspider example example.com
  • 해당 multiCam_tutorial 경로에서 다음 명령어를 실행하여 타겟 사이트를 설정한다.
$ scrapy genspider audible www.audible.com/search
Created spider 'audible' using template 'basic' in module:
  multiCam_tutorial.spiders.audible
  • audible.py 파일을 찾아 코드를 확인한다.

Scrapy Tutorial - 기본편

개요

  • Scrapy Tutorial 설치 과정 및 기본 크롤링 과정을 살펴본다.

라이브러리 설치

  • 라이브러리 설치는 다음과 같다.
pip install scrapy

프로젝트 시작

  • Django와 비슷하게 터미널 명령어는 startproject라고 입력한다.
$ scrapy startproject multiCam_tutorial
New Scrapy project 'multiCam_tutorial', using template directory 'C:\Users\j2hoo\OneDrive\Desktop\your_project_folder\venv\Lib\site-packages\scrapy\templates\project', created in:
    C:\Users\j2hoo\OneDrive\Desktop\your_path\multiCam_tutorial

You can start your first spider with:
    cd multiCam_tutorial
    scrapy genspider example example.com
  • 파일 구조는 아래와 같이 여러개의 파일로 구성되었다.

Untitled

$ scrapy genspider worldometer www.worldometers.info/world-population/population-by-country
Created spider 'worldometer' using template 'basic' in module:
  multiCam_tutorial.spiders.worldometer

Untitled

Django - ExcelCalCulator_7

개요

  • Django 한 그릇 뚝딱 교재의 내용에서 멀티캠퍼스 강의에 맞게 일부 수정함
  • 2019년 버전이고 현재는 2023년이기 때문에 소스코드 변경 사항이 필요할 거 같아서 글을 남김

교재 홍보

Untitled

Step 01 - 이전 글

Step 02 - 프로젝트 완성하기

  • 지금까지 구현한 기능과 미완료된 기능을 확인한다.

Untitled

Step 03 - 로그인 실패 시 보이는 화면을 구현

  • 우선 사용자가 로그인 실패 시, 보이는 화면으로 구현한다.

Django - ExcelCalCulator_6

개요

  • Django 한 그릇 뚝딱 교재의 내용에서 멀티캠퍼스 강의에 맞게 일부 수정함
  • 2019년 버전이고 현재는 2023년이기 때문에 소스코드 변경 사항이 필요할 거 같아서 글을 남김

교재 홍보

Untitled

Step 01 - 이전 글

Step 02 - 프로젝트 완성하기

  • 지금까지 구현한 기능과 미완료된 기능을 확인한다.

Untitled

Step 03 - 엑셀 결과 화면 출력 위한 세션값 저장

  • 우선 calculate 함수의 마지막에 엑셀 결과 화면으로 데이터와 함께 url을 이동시켜본다.
  • views.py에 코드를 추가한다.
  • 파일 경로 : ExcelCalculate > calculate > views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
import pandas as pd

# Create your views here.
def calculate(request):
    file = request.FILES['fileInput']
    print("# 사용자가 등록한 파일의 이름: ", file)
    df = pd.read_excel(file, sheet_name="Sheet1", header=0)
    print(df.head())
    # grade별 value 리스트 만들기
    grade_dic = {}
    total_row_num = len(df.index)
    for i in range(total_row_num):
        data = df.loc[i, :]
        if not data.grade in grade_dic.keys():
            grade_dic[data.grade] = [data.value]
        else:
            grade_dic[data.grade].append(data.value)

    # print(grade_dic)
    # grade별 최솟값 최댓값 평균값 구하기
    grade_calculate_dic = {}
    for key in grade_dic.keys():
        grade_calculate_dic[key] = {}
        grade_calculate_dic[key]['min'] = min(grade_dic[key])
        grade_calculate_dic[key]['max'] = max(grade_dic[key])
        grade_calculate_dic[key]['avg'] = float(sum(grade_dic[key])) / len(grade_dic[key])

    # 결과 출력
    grade_list = list(grade_calculate_dic.keys())
    grade_list.sort()
    for key in grade_list:
        print("# grade: ", key)
        print("min:", grade_calculate_dic[key]['min'], end="")
        print("/ max:", grade_calculate_dic[key]['max'], end="")
        print("/ avg:", grade_calculate_dic[key]['avg'], end="\n\n")

    # 아래 코드와 동일
    result = df.groupby('grade')['value'].agg(["min", "max", "mean"])
    print(result)

    # 이메일 주소 도메인별 인원 구하기
    email_domain_dic = {}
    for i in range(total_row_num):
        data = df.loc[i, :]
        email_domain = data['email'].split("@")[1]
        if not email_domain in email_domain_dic.keys():
            email_domain_dic[email_domain] = 1
        else:
            email_domain_dic[email_domain] += 1
    print("## EMAIL 도메인별 사용 인원")
    for key in email_domain_dic.keys():
        print("#", key, ": ", email_domain_dic[key], "명")

    df['domain'] = df['email'].apply(lambda x : x.split("@")[1])
    result2 = df.groupby('domain')['value'].agg("count").sort_values(ascending=False)
    print(result2)

    # 세션 추가
    grade_calculate_dic_to_session = {}
    for key in grade_list:
        grade_calculate_dic_to_session[int(key)] = {}
        grade_calculate_dic_to_session[int(key)]['max'] = float(grade_calculate_dic[key]['max'])
        grade_calculate_dic_to_session[int(key)]['avg'] = float(grade_calculate_dic[key]['avg'])
        grade_calculate_dic_to_session[int(key)]['min'] = float(grade_calculate_dic[key]['min'])
     request.session['grade_calculate_dic'] = grade_calculate_dic_to_session
      request.session['email_domain_dic'] = email_domain_dic

    # return HttpResponse("calculate, calculate function!")
    return redirect('/result')
  • 세션 추가 이하의 코드를 살펴보면 다음과 같다.
    • pandas의 기본 자료형은 numpy 기반인데, 장고에서는 numpy 기반의 자료형이 아닌 파이썬 기본 자료형으로 변환해주어야 한다.
    • 따라서, 정수형 숫자로 된 것으로 int형으로 유리수 형태의 숫자를 float형으로 자료를 변환한다.
    • 형 변환을 하고 나서 해당 값들을 결과 화면에서 사용하려고 세션에 저장해준다.
    • 마지막으로 redirect(”/result”) 로 처리하였다.
      • 결과 화면을 관리하는 함수는 main app에 있는 result 함수이다. 따라서, 해당 url로 갈 수 있도록 처리한 것이다.

Step 04 - result 함수 수정

  • 파일 경로 : ExcelCalculate > main > views.py

Django - ExcelCalCulator_5

개요

  • Django 한 그릇 뚝딱 교재의 내용에서 멀티캠퍼스 강의에 맞게 일부 수정함
  • 2019년 버전이고 현재는 2023년이기 때문에 소스코드 변경 사항이 필요할 거 같아서 글을 남김

교재 홍보

Untitled

Step 01 - 이전 글

Step 02 - 파일 업로드 하기

  • 로그인을 통해 메인 화면으로 왔다면, 파일 업로드 기능 구현

Step 03 - 파일 업로드 기능 구현

check - 1 : index.html 구현

  • 파일 경로 : ExcelCalculate > main > templates > main > index.html
  • 파일 제출 버튼을 눌렀을 때 가려는 url을 등록한다.
  • 또한 enctype="multipart/form-data" 를 추가한다.
    • 이것을 사용해야 파일의 내용이 올바르게 전달된다.
        <div class="content">
            <div class="fileInputDiv">
                <form action="**calculate/**" method="POST" enctype="multipart/form-data">{% csrf_token %}
                    <div class="input-group">
                        하단 버튼을 통해 파일을 업로드 해주세요.(.xls 확장자의 파일만 가능합니다.)<br>
                        <input id="fileInput" name="fileInput" type="file" class="form-control">
                        <input type="submit" class="btn btn-success btn-lg" value="파일 제출">
                    </div>
                </form>
            </div>
        </div>
  • calculate/ 경로는 초기에 ExcelCalculate > ExcelCalculate > urls.py에서 이미 설정해놨다.
    • 링크 참조 :
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('email/', include('sendEmail.urls'), name="email"), 
    path('calculate/', include('calculate.urls'), name="calculate"),
    path('', include('main.urls'), name="main"),
    path("admin/", admin.site.urls),
]
  • ExcelCalcalculate > calculate > urls.py 에서도 이미 설정을 해놨다.
from django.urls import path
from . import views

urlpatterns = [
    path('', views.calculate, name="calculate_do"), 
]

check - 2 : views.py 구현

  • 파일 경로 : ExcelCalculate > calculate > views.py
  • 이 때, request.POST가 아닌 request.FILES를 이용한다.
# Create your views here.
def calculate(request):
    file = request.FILES['fileInput']
    print("# 사용자가 등록한 파일의 이름: ", file)
    return HttpResponse("calculate, calculate function!")

check - 3 : 테스트

  • 이제 data.xlsx 파일을 업로드 한다.
  • 파일 제출 버튼을 누를 시, 웹에서는 정상적으로 calculate, calculate function! 출력이 되어야 하고 터미널에서는 아래와 같이 print() 문구가 나와야 한다.

Untitled