<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>_zeroiszero.log</title>
        <link>https://velog.io/</link>
        <description>나의 기록장</description>
        <lastBuildDate>Fri, 19 Sep 2025 03:52:37 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>_zeroiszero.log</title>
            <url>https://velog.velcdn.com/images/__zeroiszero/profile/258713a3-9a97-4f81-9360-5aaab4ab69ae/image.gif</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. _zeroiszero.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/__zeroiszero" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[3. 비정제데이터 체험하기2]]></title>
            <link>https://velog.io/@__zeroiszero/3.-%EB%B9%84%EC%A0%95%EC%A0%9C%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B2%B4%ED%97%98%ED%95%98%EA%B8%B02</link>
            <guid>https://velog.io/@__zeroiszero/3.-%EB%B9%84%EC%A0%95%EC%A0%9C%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B2%B4%ED%97%98%ED%95%98%EA%B8%B02</guid>
            <pubDate>Fri, 19 Sep 2025 03:52:37 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/f430b201-d8b6-4cf0-a0be-8ceac1266515/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/86b4db22-7c4b-420f-95a5-ba6c71234789/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/24cccffd-c9ed-4c99-a945-3fd1cb9f77fa/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/9d8c4cca-9a71-4e70-8eb8-5091b35d51bf/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/46fde132-29f3-4be3-a777-122776620175/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트]]></title>
            <link>https://velog.io/@__zeroiszero/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@__zeroiszero/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Fri, 15 Dec 2023 14:56:34 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="목차">&lt;목차&gt;</h2>
<h3 id="1-주제-및-선정-이유">1 주제 및 선정 이유</h3>
<h3 id="2-코드-및-결과-설명">2 코드 및 결과 설명</h3>
<h3 id="3-느낀점">3 느낀점</h3>
<hr>
<h1 id="1-주제-및-선정-이유-1">1 주제 및 선정 이유</h1>
<hr>
<h4 id="2023-2학기에-데이터-전처리-수업을-들으면서-머릿속에-흩어져서-존재하던-데이터-분석-과정과-그-과정에서-활용되는-분석-절차-코드-여러가지-툴이-어느정도-정리가-되는것-같았다">2023-2학기에 &#39;데이터 전처리&#39; 수업을 들으면서 머릿속에 흩어져서 존재하던 데이터 분석 과정과 그 과정에서 활용되는 분석 절차, 코드, 여러가지 툴이 어느정도 정리가 되는것 같았다.</h4>
<h4 id="그래서-데이터-전처리-수업-시간에-배운-내용-일부분을-적용하여-내용-정리-겸-실제-데이터-분석에-적용을-해보고자-한다">그래서 데이터 전처리 수업 시간에 배운 내용 일부분을 적용하여 내용 정리 겸 실제 데이터 분석에 적용을 해보고자 한다.</h4>
<h4 id="주제는-남산도서관의-도서-대출건수-예측-이다-도서관-대출-데이터를-사용해-분석에-불필요한-문자-행-열-등을-제거하고-머신러닝-기법을-이용하여-남산도서관의-도서-대출건수를-예측하는-간단한-프로젝트를-해보는-것이다">주제는 &#39;남산도서관의 도서 대출건수 예측&#39; 이다. 도서관 대출 데이터를 사용해 분석에 불필요한 문자, 행, 열 등을 제거하고 머신러닝 기법을 이용하여 남산도서관의 도서 대출건수를 예측하는 간단한 프로젝트를 해보는 것이다.</h4>
<h4 id="데이터-전처리-과정에서-중간중간-코드-실행은-했지만-너무-분량이-많아져서-벨로그에-첨부하지-않은-것도-있음">(데이터 전처리 과정에서 중간중간 코드 실행은 했지만, 너무 분량이 많아져서 벨로그에 첨부하지 않은 것도 있음!!)</h4>
<hr>
<h1 id="2-코드-및-설명">2 코드 및 설명</h1>
<hr>
<h2 id="1-데이터-전처리-하기">1. 데이터 전처리 하기</h2>
<h3 id="1-불필요한-데이터-삭제하기">1) 불필요한 데이터 삭제하기</h3>
<p>📝 불필요한 행과 열을 제거하기 위해 짧게 여러개씩 작성했던 코드들을 새로운 데이터에 적용하기 쉽도록 일괄처리하는 data_cleansing( ) 이라는 일괄처리용 함수를 만들어서 처리를 해보았다. 남산도서관에서 새로운 도서 데이터를 다운로드 했을때 dropna() 하고 groupby()등을 일일이 하기에는 너무 코드가 길었다. 따라서 필요한 코드만 파이썬 def함수로 만들어서 저장하면 간단하게 함수를 호출하거나 파이썬 스크립트를 실행하여 데이터 전처리를 하는 과정을 단순하게 만들 수 있다.</p>
<pre><code class="language-{python}">ns_book4.to_csv(&#39;ns_book4.csv&#39;, index=False) # 분석에 활용할 csv파일 (한줄한줄씩 전처리해서 만든 데이터프레임 (불필요한 데이터들 제거한거))

# 남산 도서관 장서 csv 데이터 전처리 함수 
def data_cleaning(filename):
     # 파일을 데이터프레임으로 읽음
    ns_df = pd.read_csv(filename, low_memory=False) # 여기서 filename은 csv파일 이름을 말함 
    # NaN인 열을 삭제함
    ns_book = ns_df.dropna(axis=1, how=&#39;all&#39;)

    # 대출건수를 합치기 위해 필요한 행만 추출하여 count_df 데이터프레임을 만듦
    count_df = ns_book[[&#39;도서명&#39;,&#39;저자&#39;,&#39;ISBN&#39;,&#39;권&#39;,&#39;대출건수&#39;]]
    # 도서명, 저자, ISBN, 권을 기준으로 대출건수를 groupby함
    loan_count = count_df.groupby(by=[&#39;도서명&#39;,&#39;저자&#39;,&#39;ISBN&#39;,&#39;권&#39;], dropna=False).sum()
    # 원본 데이터프레임에서 중복된 행을 제외하고 고유한 행만 추출하여 복사함
    dup_rows = ns_book.duplicated(subset=[&#39;도서명&#39;,&#39;저자&#39;,&#39;ISBN&#39;,&#39;권&#39;])
    unique_rows = ~dup_rows
    ns_book3 = ns_book[unique_rows].copy()
    # 도서명, 저자, ISBN, 권을 인덱스로 설정
    ns_book3.set_index([&#39;도서명&#39;,&#39;저자&#39;,&#39;ISBN&#39;,&#39;권&#39;], inplace=True)
    # load_count에 저장된 누적 대출건수를 업데이트함
    ns_book3.update(loan_count)

    # 인덱스 재설정함
    ns_book4 = ns_book3.reset_index()
    # 원본 데이터프레임의 열 순서로 변경함
    ns_book4 = ns_book4[ns_book.columns]

    return ns_book4</code></pre>
<p>📝 위에서 원본 데이터인 ns_202104.csv 파일을 전달하여 새로운 데이터프레임인 new_ns_book4를 만들고, 내가 개인적으로 한줄한줄씩 전처리해서 만든 ns_book4 데이터프레임과 같은지 비교를 해보았다. 다른 데이터프레임과 비교할때는 equals() 사용!!
(개인적으로 한줄씩 전처리를 해본 ns_book4는 너무 내용이 많아서 못넣었음)</p>
<pre><code class="language-{python}">new_ns_book4 = data_cleaning(&#39;ns_202104.csv&#39;)

ns_book4.equals(new_ns_book4)</code></pre>
<h3 id="결과">결과</h3>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/742b30d7-977f-4f24-b5c1-430e72f612a1/image.png" alt=""></p>
<p> 👉 내가 개인적으로 한줄씩 전처리를한 ns_book4 와 위의 일괄처리 함수가 수행한 데이터프레임이 같다고 나왔다. 이를 통해서 남산 도서관을 제외한 새로운 장서 데이터를 분석하고 싶으면, 위의 일괄처리용 함수를 수행해서 전처리 작업을 간단하게 한번에 끝낼 수 있다.</p>
<h3 id="2-잘못된-데이터-수정하기">2) 잘못된 데이터 수정하기</h3>
<p>📝 1)의 &#39;불필요한 데이터 삭제하기&#39; 과정에서도 말했듯이 2)의 과정도 한줄한줄씩 코랩에서 잘못된 데이터에 한해서 개인적으로 전처리를 해보았다. 그러나 코드가 너무 길어져서 1)과 마찬가지로 일괄처리 함수를 작성하여 그나마 간단하게 잘못된 데이터를 전처리를 해보았다.</p>
<pre><code class="language-{python}">ns_book6.to_csv(&#39;ns_book6.csv&#39;, index=False) # 한줄씩 전처리해서 만든 데이터프레임 (NaN이랑 잘못된거 처리한거)


def data_fixing(ns_book4):
    # 도서권수와 대출건수를 int32로 바꿈 
    ns_book4 = ns_book4.astype({&#39;도서권수&#39;:&#39;int32&#39;, &#39;대출건수&#39;: &#39;int32&#39;})
    # NaN인 세트 ISBN을 빈문자열로 바꿈
    set_isbn_na_rows = ns_book4[&#39;세트 ISBN&#39;].isna()
    ns_book4.loc[set_isbn_na_rows, &#39;세트 ISBN&#39;] = &#39;&#39;

    # 발행년도 열에서 연도 네 자리를 추출하여 대체, 나머지 발행년도는 -1로 바꿈
    ns_book5 = ns_book4.replace({&#39;발행년도&#39;:&#39;.*(\d{4}).*&#39;}, r&#39;\1&#39;, regex=True)
    unkown_year = ns_book5[&#39;발행년도&#39;].str.contains(&#39;\D&#39;, na=True)
    ns_book5.loc[unkown_year, &#39;발행년도&#39;] = &#39;-1&#39;


    # 발행년도를 int32로 바꿈
    ns_book5 = ns_book5.astype({&#39;발행년도&#39;: &#39;int32&#39;})
    # 4000년 이상인 경우 2333년을 뺀다
    dangun_yy_rows = ns_book5[&#39;발행년도&#39;].gt(4000)
    ns_book5.loc[dangun_yy_rows, &#39;발행년도&#39;] = ns_book5.loc[dangun_yy_rows, &#39;발행년도&#39;] - 2333
    # 여전히 4000년 이상인 경우 -&gt; -1로 바꿈
    dangun_year = ns_book5[&#39;발행년도&#39;].gt(4000)
    ns_book5.loc[dangun_year, &#39;발행년도&#39;] = -1
    # 0~1900년 사이의 발행년도는 -1로 바꿈
    old_books = ns_book5[&#39;발행년도&#39;].gt(0) &amp; ns_book5[&#39;발행년도&#39;].lt(1900)
    ns_book5.loc[old_books, &#39;발행년도&#39;] = -1

     # 도서명, 저자, 출판사가 NaN이거나 발행년도가 -1인 행을 찾음
    na_rows = ns_book5[&#39;도서명&#39;].isna() | ns_book5[&#39;저자&#39;].isna() \
              | ns_book5[&#39;출판사&#39;].isna() | ns_book5[&#39;발행년도&#39;].eq(-1)
    # 교보문고 도서 상세 페이지에서 누락된 정보를 채움
    updated_sample = ns_book5[na_rows].apply(get_book_info,
        axis=1, result_type =&#39;expand&#39;)
    updated_sample.columns = [&#39;도서명&#39;,&#39;저자&#39;,&#39;출판사&#39;,&#39;발행년도&#39;]
    ns_book5.update(updated_sample)

     # 도서명, 저자, 출판사가 NaN이거나 발행년도가 -1인 행을 삭제함
    ns_book6 = ns_book5.dropna(subset=[&#39;도서명&#39;,&#39;저자&#39;,&#39;출판사&#39;])
    ns_book6 = ns_book6[ns_book6[&#39;발행년도&#39;] != -1]

    return ns_book6
</code></pre>
<p> 👉 위의 일괄처리 함수도 엄~청 분량이 많은 편이지만, 한줄한줄 전처리를 했을 때보다는 그래도 적은편이었다. 이렇게 불필요한 데이터들과 결측치, 오류가 있는 데이터들을 처리하면 드디어 분석에 활용할 데이터가 만들어진 것이다. </p>
<h2 id="2-머신러닝으로-예측하기">2. 머신러닝으로 예측하기</h2>
<p>📝 위에서 전처리해서 만든 ns_book6 에서 sum(ns_book[&#39;도서권수&#39;]==0) 으로 도서권수의 열의 값이 0인 행의 개수를 확인했더니, 3206개가 나왔다. 정확하지 않은 판단일수도 있지만 0권은 의미없다고 생각해서 삭제했다.</p>
<pre><code class="language-{python}">ns_book7 = ns_book6[ns_book6[&#39;도서권수&#39;]&gt;0]
# 도서권수가 0인 데이터 제외한것을 ns_book7에 저장함</code></pre>
<p>📝 이제 머신러닝에 활용할 데이터는 ns_book7이다. </p>
<h3 id="1-대출건수-예측하기">1) 대출건수 예측하기</h3>
<h4 id="✔-훈련-데이터와-검증-데이터로-나누기">✔ 훈련 데이터와 검증 데이터로 나누기</h4>
<pre><code class="language-{python}"># ns_book7 데이터를 다운받고 데이터프레임으로 불러옴 
import gdown

gdown.download(&#39;https://bit.ly/3pK7iuu&#39;, &#39;ns_book7.csv&#39;, quiet=False)

import pandas as pd

ns_book7 = pd.read_csv(&#39;ns_book7.csv&#39;, low_memory=False)
ns_book7.head()</code></pre>
<h4 id="결과-1">결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/d3f82ca4-0da2-4664-a96f-19d7780c9382/image.png" alt=""></p>
<pre><code class="language-{python}">from sklearn.model_selection import train_test_split

train_set, test_set = train_test_split(ns_book7, random_state=42)

print(len(train_set), len(test_set))
</code></pre>
<h4 id="결과-2">결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/11ca5e73-f8f3-4e0d-9b45-8e15717747d1/image.png" alt=""></p>
<p>📝 코드 실행결과 전체에서 75%가 훈련 데이터, 25%가 검증 데이터로 나누어졌다. 이제 사이킷런에 있는 선형회귀모델을 위의 데이터로 훈련해본다. </p>
<pre><code class="language-{python}">X_train = train_set[[&#39;도서권수&#39;]]
y_train = train_set[&#39;대출건수&#39;]

print(X_train.shape, y_train.shape)</code></pre>
<h4 id="결과-3">결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/e24e9c16-3e34-4317-b993-8d85292121d5/image.png" alt=""></p>
<p>📝 X_train은 282577개의 행과 1개의 열로 이루어진 데이터프레임이고, y_train은 &#39;시리즈 객체&#39; 즉 282577개 원소를 가진 1차원 배열이다. (사이킷런이 입력으로는 2차원 배열, target으로는 1차원 배열을 기대하기 때문에 이런식으로 해줬다.) </p>
<h4 id="✔-선형회귀모델-훈련">✔ 선형회귀모델 훈련</h4>
<p>📝 이제 사이킷런의 linear_model 모듈의 LinearRegression 클래스를 불러와서 선형회귀모델을 훈련시켜본다. </p>
<pre><code class="language-{python}">from sklearn.linear_model import LinearRegression

lr = LinearRegression() # LinearRegression 클래스의 객체 lr 만들었음
lr.fit(X_train, y_train) # fit() 메서드를 호출해서 모델을 훈련함</code></pre>
<h4 id="결과-4">결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/10d23b23-db5b-4209-8cf4-9bb610ec754e/image.png" alt=""></p>
<h4 id="✔-훈련시킨-모델-평가하기">✔ 훈련시킨 모델 평가하기</h4>
<pre><code class="language-{python}">X_test = test_set[[&#39;도서권수&#39;]]
y_test = test_set[&#39;대출건수&#39;]

lr.score(X_test, y_test)</code></pre>
<h4 id="결과-5">결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/beb4892a-9a6c-4400-b488-c76bfa75b5a2/image.png" alt=""></p>
<p>📝 위의 결과를 보면 점수가 0.1이므로 점수가 안좋다. 도서권수로 대출건수를 예측하는건 어렵다고 본다.</p>
<h4 id="✔-선형회귀로-연속적인-값을-예측하기">✔ 선형회귀로 연속적인 값을 예측하기</h4>
<ul>
<li>선형회귀 : 선형함수를 사용하여 모델을 만드는 알고리즘<ul>
<li>식 : y = ax + b<ul>
<li>선형회귀알고리즘이 fit() 메서드를 호출했을때 데이터에서 학습한것이 기울기 a와 절편 b이다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code class="language-{python}">print(lr.coef_, lr.intercept_)
# lr.coef_ : 학습된 기울기, lr.intercept_ : 절편</code></pre>
<h4 id="결과-6">결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/562731df-389a-4f1f-8222-2491c8025b45/image.png" alt=""></p>
<p>📝 위의 결과를 보면 기울기는 1, 절편은 0에 매우 가까운 음수이다. 따라서 선형회귀모델 : y = x 이다. </p>
<h4 id="✔-로지스틱회귀로-카테고리-예측하기">✔ 로지스틱회귀로 카테고리 예측하기</h4>
<ul>
<li>로지스틱회귀 : 분류 알고리즘의 대표적인 예시</li>
<li>로지스틱 함수를 사용하여 연속적인 실수 출력값을 1 또는 0으로 변환한다.<ul>
<li>로지스틱 함수를 &#39;시그모이드 함수&#39; 라고 한다.</li>
</ul>
</li>
</ul>
<p>📝 로지스틱회귀 모델을 만들기 전에, 먼저 타겟 y_train과 y_test를 이진 분류에 맞게 바꿔야한다. 즉, 음성 클래스에 해당하는 0과 양성 클래스에 해당하는 1로 바꿔야한다. 아래 코드는 도서권수로 대출건수가 평균보다 높은지 아닌지를 예측하는 이진분류를 하는 코드이다.</p>
<pre><code class="language-{python}">borrow_mean = ns_book7[&#39;대출건수&#39;].mean()
y_train_c = y_train &gt; borrow_mean
y_test_c = y_test &gt; borrow_mean</code></pre>
<pre><code class="language-{python}">from sklearn.linear_model import LogisticRegression

logr = LogisticRegression()
logr.fit(X_train, y_train_c) # 훈련 세트로 fit() 메서드를 호출함
logr.score(X_test, y_test_c) # 검증 세트로 score() 메서드를 호출함 </code></pre>
<h4 id="결과-7">결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/656477fc-7903-4bcd-b5a8-eab3fdc7c3c2/image.png" alt=""></p>
<p>📝 실행 결과를 보면 71%정도를 맞췄다. 나름 괜찮은 결과가 나왔다. 그러나, y_test_c에 있는 음성 클래스와 양성 클래스의 비율이 비슷하지 않다는 문제점이 있다.</p>
<h4 id="✔-양성-클래스와-음성-클래스-분포-확인해보기">✔ 양성 클래스와 음성 클래스 분포 확인해보기</h4>
<pre><code class="language-{python}">y_test_c.value_counts()</code></pre>
<h4 id="결과-8">결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/3f1899e7-a106-4f59-9493-a2df1ea293e6/image.png" alt=""></p>
<p>📝 음성 클래스가 69% 정도이고 양성 클래스는 31% 정도이다. 이제 더미모델로 score() 메서드의 결과를 확인해본다.</p>
<pre><code class="language-{python}">from sklearn.dummy import DummyClassifier

dc = DummyClassifier()
dc.fit(X_train, y_train_c)
dc.score(X_test, y_test_c)</code></pre>
<h4 id="결과-9">결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/2c3e8c8f-97a7-409e-be87-8c7cb5cfcc00/image.png" alt=""></p>
<p>📝 69% 정도로 정확도가 나왔다. 이 값이 모델을 만들때 기준점이 되는 점수이다. 만약 이 점수보다 낮으면 좋은 모델이라고 하기 어렵다. </p>
<hr>
<h1 id="3-느낀점-1">3 느낀점</h1>
<hr>
<h4 id="이번-프로젝트를-하면서-데이터-전처리-과정은-형식적인-과정은-딱-정해져-있다는걸-알면서도-막상-해보면-그-안에서-논리적으로-꼼꼼하게-생각해야-할-것들이-많다고-느꼈다">이번 프로젝트를 하면서 데이터 전처리 과정은 형식적인 과정은 딱 정해져 있다는걸 알면서도, 막상 해보면 그 안에서 논리적으로 꼼꼼하게 생각해야 할 것들이 많다고 느꼈다.</h4>
<h4 id="그렇지만-이러한-점은-내가-전처리를-많이-해보지-않아서-능숙하지-않기-때문에-어렵다고-느끼는-것이다-많이-해봐야지-실력이-늘-것이기-때문에-방학기간을-활용해서-파이썬으로-데이터-전처리를-능숙하게-할-수-있도록-연습을-해야겠다-또-코딩만-잘하면-되는것이-아니라-모델을-사용할-때-통계적-개념이-거의-필수이기-때문에-통계-공부도-같이-해야겠다고-생각했다-나는-r데이터분석-수업을-들을때도-로지스틱회귀가-정말-헷갈리고-어려웠는데-여기서도-하는-데에-애를-먹었었다-로지스틱회귀는-이번에-실습하면서-80는-이해한것-같다">그렇지만 이러한 점은 내가 전처리를 많이 해보지 않아서 능숙하지 않기 때문에 어렵다고 느끼는 것이다. 많이 해봐야지 실력이 늘 것이기 때문에 방학기간을 활용해서 파이썬으로 데이터 전처리를 능숙하게 할 수 있도록 연습을 해야겠다. 또, 코딩만 잘하면 되는것이 아니라 모델을 사용할 때 통계적 개념이 거의 필수이기 때문에 통계 공부도 같이 해야겠다고 생각했다. 나는 R데이터분석 수업을 들을때도 로지스틱회귀가 정말 헷갈리고 어려웠는데, 여기서도 하는 데에 애를 먹었었다. 로지스틱회귀는 이번에 실습하면서 80%는 이해한것 같다.</h4>
<h4 id="더-나아가서-나는-파이썬보다는-r이-그나마-익숙한데-r로-코드를-작성한-것을-파이썬으로-그대로-작성해-보는-공부를-할-예정이다">더 나아가서 나는 파이썬보다는 R이 그나마 익숙한데, R로 코드를 작성한 것을 파이썬으로 그대로 작성해 보는 공부를 할 예정이다.</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[PP-파이프라인]]></title>
            <link>https://velog.io/@__zeroiszero/PP-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8</link>
            <guid>https://velog.io/@__zeroiszero/PP-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8</guid>
            <pubDate>Sun, 03 Dec 2023 13:38:04 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="1-파이프라인">1 파이프라인</h1>
<hr>
<h2 id="11-파이프라인-pipeline">1.1 파이프라인 (Pipeline)</h2>
<ul>
<li>여러 개의 데이터의 처리(preprocessor, classifier, regressor, estimator 등)를 <strong>하나의 처리과정(pipeline, sequence)으로 만들어 데이터를 일괄처리</strong>해 주는 기능</li>
<li>파이프라인을 사용하면 데이터 전처리나 모델 구축 과정 등을 <strong>더 짧은 코드로, 더 가시성 있게, 더 효율적으로 처리</strong>할 수 있음</li>
<li><strong>다양한 패키지에서 파이프라인을 지원</strong>하고 있음<ul>
<li>데이터 프레임: Pandas, Polars</li>
<li>머신러닝: SciKit-Learn</li>
<li>딥러닝: TensorFlow, PyTorch</li>
</ul>
</li>
</ul>
<h4 id="파이프라인-처리-차이">파이프라인 처리 차이</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/ed5f7dce-7cae-44fe-96f0-ff9807e63bf8/image.png" alt=""></p>
<hr>
<h2 id="12-scikit-learn의-파이프라인">1.2 SciKit-Learn의 파이프라인</h2>
<ul>
<li>SciKit-Learn에서는 Pipeline 클래스를 통해 파이프라인을 구현할 수 있음<ul>
<li>Pipeline 클래스는 <strong>여러 개의 추정기(estimator)를 하나의 추정기처럼 사용</strong>할 수 있도록 해 줌</li>
</ul>
</li>
<li>파이프라인 사용 목적<ul>
<li><strong>편의성과 캡슐화</strong><ul>
<li>전체 데이터 처리 시퀀스에서 fit과 predict를 한 번만 적용하면 됨</li>
</ul>
</li>
<li><strong>통합된 하이퍼 파라미터 최적화</strong><ul>
<li>grid search를 이용하여 한 번에 하이퍼 파라미터 최적화 가능</li>
</ul>
</li>
<li><strong>안전성 강화</strong><ul>
<li>교차검증(cross-validation)시 랜덤성에 의한 데이터의 통계적 특성이 변경되는 것을 방지하여 일관성을 유지할 수 있음</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="13-파이프라인을-이용하여-연결형-추정기-만들기">1.3 파이프라인을 이용하여 연결형 추정기 만들기</h2>
<h4 id="파이프라인을-사용하지-않은-경우">파이프라인을 사용하지 않은 경우</h4>
<pre><code class="language-{python}">from sklearn.feature_selection import SelectKBest, f_classif # 피처선택 메서드
from sklearn.preprocessing import StandardScaler # 데이터 표준화
from sklearn.tree import DecisionTreeClassifier # 의사결정나무 분류기
from sklearn.datasets import load_iris # iris 데이터세트

# iris 데이터세트 로드
X, y = load_iris(return_X_y=True)

## 피쳐 선택
feat_sel = SelectKBest(f_classif, k=2)
X_selected = feat_sel.fit_transform(X, y)
print(&#39;Selected features:&#39;, feat_sel.get_feature_names_out())

## 표준화
scaler = StandardScaler()
scaler.fit(X_selected)
X_transformed = scaler.transform(X_selected)
print(&#39;Standard Scaled: \n&#39;, X_transformed[:5, :])

## 모델 학습
clf = DecisionTreeClassifier(max_depth=3)
clf.fit(X_transformed, y)
print(&#39;Estimate : &#39;, clf.predict(X_transformed)[:3])
print(&#39;Accuracy : &#39;, clf.score(X_transformed, y))</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/ee5dd7d1-957d-4a19-8d7e-543a10474b55/image.png" alt=""></p>
<h4 id="파이프라인을-사용한-경우">파이프라인을 사용한 경우</h4>
<ul>
<li>파이프라인은 (key, value)의 리스트를 구성하여 만듦</li>
<li>파이프라인을 사용하면, 변환된 데이터를 별도로 저장하지 않고 연속적으로 사용하므로 속도가 개선되고 메모리가 절약됨</li>
</ul>
<pre><code class="language-{python}">from sklearn.pipeline import Pipeline # 파이프라인 구성을 위한 함수
from sklearn.feature_selection import SelectKBest, f_classif # 피처선택 메서드
from sklearn.preprocessing import StandardScaler # 데이터 표준화
from sklearn.tree import DecisionTreeClassifier # 의사결정나무 분류기
from sklearn.datasets import load_iris # iris 데이터세트

# iris 데이터세트 로드
X, y = load_iris(return_X_y=True)

## pipeline 구축
pipeline = Pipeline([
    (&#39;Feature_Selection&#39;, SelectKBest(f_classif, k=2)), ## 피쳐 선택
    (&#39;Standardization&#39;, StandardScaler()),  ## 표준화
    (&#39;Decision_Tree&#39;, DecisionTreeClassifier(max_depth=3)) ## 학습 모델
])
display(pipeline) # 파이프라인 그래프로 구성 확인

pipeline.fit(X, y) ## 모형 학습
print(&#39;Estimate : &#39;, pipeline.predict(X)[:3]) ## 예측
print(&#39;Accuracy : &#39;, pipeline.score(X, y)) ## 성능 평가</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/e2c49667-8c97-4b20-8584-b422d6594c30/image.png" alt=""></p>
<ul>
<li>make_pipeline() 함수를 사용하여 파이프라인을 만들 수 있음<ul>
<li>make_pipeline() 함수는 파이프라인의 이름을 자동으로 만들어 줌</li>
<li>파이프라인의 이름은 각 추정기의 클래스 이름을 소문자로 바꾼 것과 같음</li>
<li>파이프라인의 이름을 지정하려면 Pipeline() 클래스를 사용해야 함</li>
</ul>
</li>
</ul>
<pre><code class="language-{python}">from sklearn.pipeline import make_pipeline # 파이프라인 구성을 위한 함수

pipeline_auto = make_pipeline(SelectKBest(f_classif, k=2), 
              StandardScaler(), 
              DecisionTreeClassifier(max_depth=3))
display(pipeline_auto) # 파이프라인 그래프로 구성 확인</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/e5db8c3b-4da9-4542-a8d0-0f5441f0852d/image.png" alt=""></p>
<ul>
<li>파이프라인 내부의 중간결과 확인하기<ul>
<li>pipeline의 인덱스나 named_steps로 확인이 가능</li>
</ul>
</li>
</ul>
<pre><code class="language-{python}"># pipiline의 Feature_Selection step의 결과 확인
# pipeline.named_steps[&#39;Feature_Selection&#39;] == pipeline[0]
# pipeline.named_steps[&#39;Standardization&#39;] == pipeline[1]
# pipeline.named_steps[&#39;Decision_Tree&#39;] == pipeline[2]
print(&#39;Selected features:&#39;, pipeline.named_steps[&#39;Feature_Selection&#39;].get_feature_names_out())
X_transformed = pipeline[1].transform(X_selected)
print(&#39;Standard Scaled: \n&#39;, X_transformed[:5, :])</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a9bd8934-dc6e-4b46-8d2d-6e20bdacc67a/image.png" alt=""></p>
<hr>
<h1 id="2-파이프라인의-결합">2 파이프라인의 결합</h1>
<hr>
<h2 id="21-수치형-데이터-파이프라인-처리">2.1 수치형 데이터 파이프라인 처리</h2>
<pre><code class="language-{python}">import seaborn as sns
import pandas as pd
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer

# 데이터 로드
df = sns.load_dataset(&#39;diamonds&#39;)
print(df.info())
X = df.drop(&#39;price&#39;, axis=1)
y = df[&#39;price&#39;]

# 데이터를 유형에 따라 분리
numeric_col = list(X.select_dtypes(exclude=&#39;category&#39;).columns)
category_col = list(X.select_dtypes(include=&#39;category&#39;).columns)
print(f&#39;numeric_col: {numeric_col}&#39;)
print(f&#39;category_col: {category_col}&#39;)</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/82723113-70b3-41e9-b00e-42cccccd6d5f/image.png" alt=""></p>
<pre><code class="language-{python}"># 파이프라인 구축
numeric_pipeline = Pipeline(
    steps=[
        (&#39;imputer&#39;, SimpleImputer(strategy=&#39;mean&#39;)), # 평균값으로 Nan값 채워주기
        (&#39;scaler&#39;, StandardScaler()) # 표준화
    ])

display(numeric_pipeline) # 파이프라인 그래프로 구성 확인

# 파이프라인 학습
numerical_data_piped = numeric_pipeline.fit_transform(X[numeric_col])
pd.DataFrame(numerical_data_piped, columns=numeric_col).head()</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/df68e559-c382-4810-af32-ff6c115cd95e/image.png" alt=""></p>
<hr>
<h2 id="22-범주형-데이터-파이프라인-처리">2.2 범주형 데이터 파이프라인 처리</h2>
<pre><code class="language-{python}">from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder

# 파이프라인 구축
category_pipeline = Pipeline(
    steps=[
        (&#39;imputer&#39;, SimpleImputer(strategy=&#39;constant&#39;, fill_value=&#39;missing&#39;)), # 비어있는 값을 &#39;missing&#39;으로 채우기
        (&#39;onehot&#39;, OneHotEncoder(sparse_output=False)), # Onehotencoder
    ])

display(category_pipeline) # 파이프라인 그래프로 구성 확인

# 파이프라인 학습
category_data_piped = category_pipeline.fit_transform(X[category_col])
# Onehotencoder의 컬럼명을 확인
category_colnames = category_pipeline[1].get_feature_names_out(category_col)
# 파이프라인 이후 데이터(array형 -&gt; 데이터프레임)
pd.DataFrame(category_data_piped, columns=category_colnames).head()</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/20fa93fd-b913-4265-8a55-bd357f1ac9be/image.png" alt=""></p>
<hr>
<h2 id="23-수치형--범주형-파이프라인-결합한-파이프라인">2.3 수치형 + 범주형 파이프라인 결합한 파이프라인</h2>
<ul>
<li>ColumnTransformer 클래스를 사용하여 수치형 데이터와 범주형 데이터의 파이프라인을 결합할 수 있음</li>
</ul>
<pre><code class="language-{python}">from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LinearRegression

# numeric &amp; category 파이프라인 합치기
preprocessor = ColumnTransformer(
    transformers=[
        (&#39;numeric&#39;, numeric_pipeline, numeric_col),
        (&#39;category&#39;, category_pipeline, category_col)
    ])

pipe = make_pipeline(preprocessor, LinearRegression())
display(pipe) # 파이프라인 그래프로 구성 확인
pipe.fit(X,y)

print(&#39;Estimate : &#39;, pipe.predict(X))
print(&#39;Accuracy : &#39;, pipe.score(X, y))</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/d7ae1538-7ac6-46db-b638-e9a3ec923197/image.png" alt=""></p>
<hr>
<h2 id="24-columntransformer">2.4 ColumnTransformer</h2>
<ul>
<li>컬럼 기준으로 데이터를 복합하여 처리해주는 함수</li>
</ul>
<pre><code class="language-{python}">from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
import pandas as pd
import numpy as np

data_df = pd.DataFrame({
    &quot;height&quot;:[165,  np.nan, 182],
    &quot;weight&quot;:[70,   62,     np.nan],
    &quot;age&quot;   :[np.nan,18,    15]
})

# SimpleImputer를 사용해서 height의 null 값들은 평균으로 출력하고 나머지 column은 통과
col_transformer = ColumnTransformer([
    (&quot;Impute_mean&quot;, SimpleImputer(strategy=&quot;mean&quot;), [&quot;height&quot;])
    ], 
    remainder=&quot;passthrough&quot;
)

display(col_transformer) # 파이프라인 그래프로 구성 확인
print(data_df)
print(col_transformer.fit_transform(data_df))</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/bbac33c9-5134-442a-9823-44fb7963c949/image.png" alt=""></p>
<pre><code class="language-{python}"># SimpleImputer를 사용해서 mean과 median 값을 null에 넣고 
# 나머지 열(column)에 대한 값은 상수로 -1 값을 넣어 줌
col_transformer2 = ColumnTransformer([
    (&quot;Impute_mean&quot;  , SimpleImputer(strategy=&quot;mean&quot;)  , [&quot;height&quot;]),
    (&quot;Impute_median&quot;, SimpleImputer(strategy=&quot;median&quot;), [&quot;weight&quot;])
    ],
    remainder=SimpleImputer(strategy=&quot;constant&quot;, fill_value=-1)
)

display(col_transformer2) # 파이프라인 그래프로 구성 확인
print(data_df)
print(col_transformer2.fit_transform(data_df))</code></pre>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/83ac86e3-580a-409b-bd89-cd5208e3cdf6/image.png" alt=""></p>
<hr>
<h1 id="응용-사례">응용 사례</h1>
<hr>
<h2 id="13-make_pipeline--응용">1.3 make_pipeline( ) 응용</h2>
<h4 id="위스콘신-유방암-데이터셋을-활용하여-종양이-악성인지-양성인지-예측하는-모델-만들기">위스콘신 유방암 데이터셋을 활용하여 종양이 악성인지 양성인지 예측하는 모델 만들기</h4>
<pre><code class="language-{python}">import pandas as pd
df = pd.read_csv(&#39;https://archive.ics.uci.edu/ml/&#39;
                 &#39;machine-learning-databases&#39;
                 &#39;/breast-cancer-wisconsin/wdbc.data&#39;,
                header=None)</code></pre>
<h4 id="👉-pandas를-사용하여-uci서버에서-직접-데이터셋을-불러옴">👉 pandas를 사용하여 UCI서버에서 직접 데이터셋을 불러옴</h4>
<pre><code class="language-{python}">from sklearn.preprocessing import LabelEncoder

X = df.loc[:, 2:].values
y = df.loc[:, 1].values
le = LabelEncoder()
y = le.fit_transform(y)
le.classes_</code></pre>
<h4 id="👉-30개의-특성을-넘파이-배열x에-할당---labelencoder-객체를-사용하여-클래스-레이블을-원본-문자열-표현에서-정수로-변환함">👉 30개의 특성을 넘파이 배열X에 할당 -&gt; LabelEncoder 객체를 사용하여 클래스 레이블을 원본 문자열 표현에서 정수로 변환함</h4>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/da1a9915-aef2-427a-8446-87089d4ac004/image.png" alt=""></p>
<pre><code class="language-{python}">le.transform([&#39;M&#39;, &#39;B&#39;])</code></pre>
<h4 id="👉-두개의-더미-클래스-레이블-샘플로-labelencoder-객체의-transform-메서드를-호출하여-매핑-확인함">👉 두개의 더미 클래스 레이블 샘플로 LabelEncoder 객체의 transform 메서드를 호출하여 매핑 확인함</h4>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/db30f8ed-6733-405d-9218-43470a471746/image.png" alt=""></p>
<pre><code class="language-{python}">from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = \
     train_test_split(X, y,
                      test_size=0.20,
                      stratify=y,
                      random_state=1)</code></pre>
<h4 id="👉-전체-데이터셋을-훈련-데이터셋전체-데이터의-80과-별도의-테스트-데이터셋전체-데이터의-20으로-나눔">👉 전체 데이터셋을 훈련 데이터셋(전체 데이터의 80%)과 별도의 테스트 데이터셋(전체 데이터의 20%)으로 나눔</h4>
<pre><code class="language-{python}">from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
pipe_lr = make_pipeline(StandardScaler(),
                         PCA(n_components=2),
                         LogisticRegression(random_state=1))
pipe_lr.fit(X_train, y_train)
y_pred = pipe_lr.predict(X_test)
print(&#39;테스트 정확도: %.3f&#39; % pipe_lr.score(X_test, y_test))</code></pre>
<h4 id="👉-훈련-데이터셋과-테스트-데이터셋을-각각-학습하고-변환하는-단계를-구성하는-대신-standardscaler-pca-logisticregression-객체를-make_pipeline-를-활용하여-하나의-파이프라인으로-연결함">👉 훈련 데이터셋과 테스트 데이터셋을 각각 학습하고 변환하는 단계를 구성하는 대신 StandardScaler, PCA, LogisticRegression 객체를 &#39;make_pipeline()&#39; 를 활용하여 하나의 파이프라인으로 연결함</h4>
<p>** ↳ 결과**
<img src="https://velog.velcdn.com/images/__zeroiszero/post/3022b6a2-3b85-4f41-83c3-31dfbd1e8091/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PP-피쳐엔지니어링]]></title>
            <link>https://velog.io/@__zeroiszero/PP-%ED%94%BC%EC%B3%90%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81</link>
            <guid>https://velog.io/@__zeroiszero/PP-%ED%94%BC%EC%B3%90%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81</guid>
            <pubDate>Sun, 03 Dec 2023 13:17:22 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="1-피쳐엔지니어링">1 피쳐엔지니어링</h1>
<hr>
<h2 id="11-피쳐feature">1.1 피쳐(feature)</h2>
<ul>
<li>데이터 모델(특히, 인공지능)에서 예측을 수행하는 데 사용되는 입력변수를 의미</li>
<li>통계학에서는 독립 변수라고 함</li>
</ul>
<h4 id="피쳐의-유형">피쳐의 유형</h4>
<ul>
<li>속성에 따라<ul>
<li><strong>범주형(categorical)</strong>: 범주나 순위가 있는 변수</li>
<li><strong>수치형(numerical)</strong>: 수치로 표현되는 변수</li>
</ul>
</li>
<li>인과관계에 따라<ul>
<li><strong>독립변수(independent variable)</strong>: 다른 변수에 영향을 받지 않고 종속변수에 영향을 주는 변수</li>
<li><strong>종속변수(dependent variable)</strong>: 독립 변수로부터 영향을 받는 변수</li>
</ul>
</li>
<li>머신러닝에서<ul>
<li><strong>입력(input)</strong>: 변수(Feature), 속성(Attribute), 예측변수(Predictor), 차원(Dimension), 관측치(Observation), 독립변수(Independent Variable)</li>
<li><strong>출력(output)</strong>: 라벨(Label), 클래스(Class), 목푯값(Target), 반응(Response), 종속변수(Dependent Variable)</li>
</ul>
</li>
</ul>
<hr>
<h2 id="12-피쳐-엔지니어링feature-engineering">1.2 피쳐 엔지니어링(Feature Engineering)</h2>
<ul>
<li>머신러닝 알고리즘의 <strong>성능을 향상시키기 위하여</strong> 데이터에 대한 도메인 지식을 활용하여 <strong>변수를 조합하거나 새로운 변수를 만드는 과정</strong></li>
</ul>
<h4 id="피쳐-추출feature-extraction">피쳐 추출(feature extraction)</h4>
<ul>
<li>피쳐들 사이에 내재한 특성이나 관계를 분석하여 이들을 잘 표현할 수 있는 새로운 선형 혹은 비선형 결합 변수를 만들어 데이터를 줄이는 방법</li>
<li>고차원의 원본 피쳐 공간을 저차원의 새로운 피쳐 공간으로 투영</li>
<li>PCA(주성분 분석), LDA(선형 판별 분석) 등</li>
</ul>
<h4 id="피쳐-선택feature-selection">피쳐 선택(feature selection)</h4>
<ul>
<li>피쳐 중 타겟에 가장 관련성이 높은 피쳐만을 선정하여 피쳐의 수를 줄이는 방법</li>
<li>관련없거나 중복되는 피쳐들을 필터링하고 간결한 subset을 생성</li>
<li>모델 단순화, 훈련 시간 축소, 차원의 저주 방지, 과적합(Over-fitting)을 줄여 일반화해주는 장점이 있음</li>
<li>Filter, Wrapper, Embedded 메서드
<img src="https://velog.velcdn.com/images/__zeroiszero/post/2466ba43-f079-4560-8db5-733ec208db8b/image.png" alt=""></li>
</ul>
<h4 id="머신러닝-성능-향상을-위한-방법">머신러닝 성능 향상을 위한 방법</h4>
<ul>
<li>피쳐 엔지니어링 적용</li>
<li>머신러닝 알고리즘의 하이퍼 파라미터를 최적화</li>
</ul>
<hr>
<h1 id="2-피쳐-추출">2 피쳐 추출</h1>
<hr>
<h2 id="21-피쳐-추출-feature-extraction">2.1 피쳐 추출 (Feature Extraction)</h2>
<ul>
<li><p>변수들 사이에 내재한 특성이나 관계를 분석하여 이들을 잘 표현할 수 있는 새로운 선형 혹은 비선형 결합 변수를 만들어 데이터를 줄이는 방법</p>
</li>
<li><p>주성분 분석(Principal Component Analysis, PCA)</p>
<ul>
<li>변수들의 공분산 행렬이나 상관행렬을 이용</li>
<li>원래 데이터 특징을 잘 설명해주는 성분을 추출하기 이하여 고차원 공간의 표본들을 선형 연관성이 없는 저차원 공간으로 변환하는 기법</li>
<li>행의 수와 열의 수가 같은 정방행렬에서만 사용</li>
</ul>
</li>
<li><p>선형판별분석(Linear Discriminant Analysis, LDA)</p>
<ul>
<li>데이터의 Target값 클래스끼리 최대한 분리할 수 있는 축을 찾음</li>
<li>특정 공간상에서 클래스 분리를 최대화하는 축을 찾기 위해 클래스 간 분산(between-class scatter)과 클래스 내부 분산(within-class scatter)의 비율을 최대화하는 방식으로 차원을 축소</li>
</ul>
</li>
<li><p>특이값 분해(Singular Value Decomposition)</p>
<ul>
<li>M X N 차원의 행렬데이터에서 특이값을 추출하고 이를 통해 주어진 데이터 세트를 효과적으로 축약할 수 있는 기법</li>
</ul>
</li>
<li><p>요인분석(Factor Analysis)</p>
<ul>
<li>데이터 안에 관찰할 수 있는 잠재적인 변수(Latent Variable)가 존재한다고 가정</li>
<li>모형을 세운 뒤 관찰 가능한 데이터를 이용하여 해당 잠재 요인을 도출하고 데이터 안의 구조를 해석하는 기법</li>
<li>주로 사회과학이나 설문 조사 등에서 많이 활용</li>
</ul>
</li>
<li><p>독립성분분석(Independent Component Analysis)</p>
<ul>
<li>주성분 분석과는 달리 다변량의 신호를 통계적으로 독립적인 하부성분으로 분리하여 차원을 축소하는 기법</li>
<li>독립 성분의 분포는 비정규 분포를 따르게 되는 차원축소 기법</li>
</ul>
</li>
<li><p>다차원 척도법(Multi-Dimensional Scaling)</p>
<ul>
<li>개체들 사이의 유사성, 비유사성을 측정하여 2차원 또는 3차원 공간상에 점으로 표현하여 개체들 사이의 집단화를 시각적으로 표현하는 분석 방법</li>
</ul>
</li>
</ul>
<hr>
<h2 id="22-주성분-분석">2.2 주성분 분석</h2>
<h4 id="주성분-분석-principal-component-analysis">주성분 분석 (Principal Component Analysis)</h4>
<ul>
<li>가장 널리 사용되는 차원(변수) 축소 기법 중 하나</li>
<li>원 데이터의 분산(variance)을 최대한 보존하면서 서로 직교하는 새 기저(축)를 찾아, 고차원 공간의 표본들을 선형 연관성이 없는 저차원 공간으로 변환하는 기법</li>
<li>PCA는 기존의 변수를 조합하여 서로 연관성이 없는 새로운 변수, 즉 주성분(principal component, PC)들을 만들어 냄</li>
<li>주성분의 개수를 증가시킴에 따라 원 데이터의 분산의 보존수준이 높아짐</li>
</ul>
<h4 id="pca-절차">PCA 절차</h4>
<ul>
<li>학습 데이터셋에서 분산이 최대인 축(axis)을 찾음</li>
<li>첫번째 축과 직교(orthogonal)하면서 분산이 최대인 두 번째 축을 찾음</li>
<li>첫 번째 축과 두 번째 축에 직교하고 분산을 최대한 보존하는 세 번째 축을 찾음</li>
<li>1~3과 같은 방법으로 데이터셋의 차원(특성 수)만큼의 축을 찾음</li>
</ul>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/b9f1211b-9e07-4353-b399-ed473691821b/image.png" alt=""></p>
<hr>
<h2 id="23-선형판별분석">2.3 선형판별분석</h2>
<h4 id="선형판별분석linear-discriminant-analysis-lda">선형판별분석(Linear Discriminant Analysis, LDA)</h4>
<ul>
<li>입력 데이터 세트를 저차원 공간으로 투영(projection)해 차원을 축소하는 기법</li>
<li>데이터의 Target값 클래스끼리 최대한 분리할 수 있는 축을 찾음 → 지도 학습</li>
<li>PCA는 Target값을 사용하지 않으므로 비지도 학습</li>
</ul>
<h4 id="lda-절차">LDA 절차</h4>
<ul>
<li>특정 공간상에서 클래스 분리를 최대화하는 축을 찾기 위해 클래스 간 분산(between-class scatter)과 클래스 내부 분산(within-class scatter)의 비율을 최대화하는 방식으로 차원을 축소</li>
<li>SVM 같은 다른 분류 알고리즘을 적용하기 전에 차원을 축소시키는 데 사용
<img src="https://velog.velcdn.com/images/__zeroiszero/post/41fe5f40-f593-47ab-8f5b-935ff1c51d20/image.png" alt=""></li>
</ul>
<hr>
<h2 id="24-scikit-learn으로-pca와-lda-수행하기">2.4 Scikit-Learn으로 PCA와 LDA 수행하기</h2>
<pre><code class="language-{python}">from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

# iris 데이터셋을 로드
iris = datasets.load_iris()

X = iris.data # iris 데이터셋의 피쳐들
y = iris.target # iris 데이터셋의 타겟
target_names = list(iris.target_names) # iris 데이터셋의 타겟 이름

print(f&#39;{X.shape = }, {y.shape = }&#39;) # 150개 데이터, 4 features
print(f&#39;{target_names = }&#39;)  </code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/c9c84fe1-f089-421f-8f2b-9d559567ed8c/image.png" alt=""></p>
<pre><code class="language-{python}"># PCA의 객체를 생성, 차원은 2차원으로 설정(현재는 4차원)
pca = PCA(n_components=2)

# PCA를 수행. PCA는 비지도 학습이므로 y값을 넣지 않음
pca_fitted = pca.fit(X)

print(f&#39;{pca_fitted.components_ = }&#39;)  # 주성분 벡터
print(f&#39;{pca_fitted.explained_variance_ratio_ = }&#39;) # 주성분 벡터의 설명할 수 있는 분산 비율

X_pca = pca_fitted.transform(X) # 주성분 벡터로 데이터를 변환
print(f&#39;{X_pca.shape = }&#39;)  # 4차원 데이터가 2차원 데이터로 변환됨</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/ad0df5f7-7c72-4bbb-b084-c4c1800af618/image.png" alt=""></p>
<pre><code class="language-{python}"># LDA의 객체를 생성. 차원은 2차원으로 설정(현재는 4차원)
lda = LinearDiscriminantAnalysis(n_components=2)

# LDA를 수행. LDA는 지도학습이므로 타겟값이 필요
lda_fitted = lda.fit(X, y)

print(f&#39;{lda_fitted.coef_=}&#39;) # LDA의 계수
print(f&#39;{lda_fitted.explained_variance_ratio_=}&#39;) # LDA의 분산에 대한 설명력

X_lda = lda_fitted.transform(X)
print(f&#39;{X_lda.shape = }&#39;)  # 4차원 데이터가 2차원 데이터로 변환됨</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/c4de3369-1133-4ed6-8ffb-cedac90fb4d0/image.png" alt=""></p>
<pre><code class="language-{python}"># 시각화 하기
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

# Seaborn을 이용하기 위해 데이터프레임으로 변환
df_pca = pd.DataFrame(X_pca, columns=[&#39;PC1&#39;, &#39;PC2&#39;])
df_lda = pd.DataFrame(X_lda, columns=[&#39;LD1&#39;, &#39;LD2&#39;])
y = pd.Series(y).replace({0:&#39;setosa&#39;, 1:&#39;versicolor&#39;, 2:&#39;virginica&#39;})

# subplot으로 시각화
fig, ax = plt.subplots(1, 2, figsize=(10, 4))

sns.scatterplot(df_pca, x=&#39;PC1&#39;, y=&#39;PC2&#39;, hue=y, style=y, ax=ax[0], palette=&#39;Set1&#39;)
ax[0].set_title(&#39;PCA of IRIS dataset&#39;)

sns.scatterplot(df_lda, x=&#39;LD1&#39;, y=&#39;LD2&#39;, hue=y, style=y, ax=ax[1], palette=&#39;Set1&#39;)
ax[1].set_title(&#39;LDA of IRIS dataset&#39;)

plt.show()</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/58bbde40-e44d-45aa-8f02-9cbf538e9640/image.png" alt=""></p>
<hr>
<h1 id="3-피쳐-선택-기법">3 피쳐 선택 기법</h1>
<hr>
<ul>
<li>종속변수 활용여부에 따라<ul>
<li>Supervised: 종속변수를 활용하여 선택</li>
<li>Unsupervised: 독립변수들 만으로 선택</li>
</ul>
</li>
<li>선택 메커니즘에 따라<ul>
<li>Filter: 통계적인 방법으로 선택</li>
<li>Wrapper: 모델을 활용하여 선택</li>
<li>Embedded: 모델 훈련 과정에서 자동으로 선택</li>
<li>Hybrid: Filter + Wrapper
<img src="https://velog.velcdn.com/images/__zeroiszero/post/ed420b7d-d589-42a9-afd6-d433116d3aa2/image.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<h2 id="31-필터-기법filter-method">3.1 필터 기법(Filter Method)</h2>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/7ece5d69-2e9d-4ea6-814e-d9f137e2e65b/image.png" alt=""></p>
<h4 id="필터기법의-종류">필터기법의 종류</h4>
<ul>
<li>분산 기반 선택(Variance-based Selection)<ul>
<li>분산이 낮은 변수를 제거하는 방법</li>
</ul>
</li>
<li>정보 소득(Information Gain)<ul>
<li>가장 정보 소득이 높은 속성을 선택하여 데이터를 더 잘 구분하게 되는 것</li>
</ul>
</li>
<li>카이제곱 검정(Chi-Square Test)<ul>
<li>카이제곱  분포에 기초한 통계적 방법으로 관찰된 빈도가 기대되는 빈도와 의미있게 다른지 여부를 검증하기 위해 사용되는 검증 방법</li>
</ul>
</li>
<li>피셔 스코어(Fisher Score)<ul>
<li>최대 가능성 방정식을 풀기 위해 통계에 사용되는 뉴턴(Newton)의 방법</li>
</ul>
</li>
<li>상관계수(Correlation Coefficient)<ul>
<li>두 변수 사이의 통계적 관계를 표현하기 위해 특정한 상관관계의 정도를 수치적으로 나타낸 계수</li>
</ul>
</li>
</ul>
<h4 id="분산-기반-선택variance-based-selection">분산 기반 선택(Variance-based Selection)</h4>
<pre><code class="language-{python}">from sklearn import datasets
from sklearn.feature_selection import VarianceThreshold

# iris 데이터셋을 로드
iris = datasets.load_iris()

X = iris.data # iris 데이터셋의 피쳐들
y = iris.target # iris 데이터셋의 타겟
X_names = iris.feature_names # iris 데이터셋의 피쳐 이름
y_names = iris.target_names # iris 데이터셋의 타겟 이름

# 분산이 0.2 이상인 피쳐들만 선택하도록 학습
sel = VarianceThreshold(threshold=0.2).fit(X)
print(f&#39;{sel.variances_ = }&#39;) # 각 피쳐의 분산 확인

# 분산이 0.2 이상인 피쳐들만 선택 적용
X_selected = sel.transform(X) # 분산이 0.2 이상인 피쳐들만 선택
X_selected_names = [X_names[i] for i in sel.get_support(indices=True)] # 선택된 피쳐들의 이름

print(f&#39;{X_selected_names = }&#39;)
print(f&#39;{X_selected[:5] = }&#39;)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/4da0c622-d3a4-4ab1-b8da-bf87902b95a0/image.png" alt=""></p>
<h4 id="scikit-learn-제공-피쳐-선택-메서드">Scikit-Learn 제공 피쳐 선택 메서드</h4>
<ul>
<li>SelectKBest(): 고정된 k개의 피쳐 선택기</li>
<li>SelectPercentile(): 분위수 기반 선택기</li>
<li>SelectFpr(): False positive rate 기반 선택기</li>
<li>SelectFdr(): 추정된 False discovery rate 기반 선택기</li>
<li>SelectFwe(): familiy-wise error rate 기반 선택기</li>
<li>GenericUnivariateSelect(): 단변량 피쳐 선택기</li>
</ul>
<h4 id="scikit-learn-제공-피쳐-선택-기준">Scikit-Learn 제공 피쳐 선택 기준</h4>
<ul>
<li>f_classif: ANOVA F-value 분류</li>
<li>mutual_info_classif: 상호정보량(mutual information) 분류</li>
<li>chi2: 카이제곱 분류</li>
<li>f_regression: F-value 회귀</li>
<li>mutual_info_regression: 상호정보량(mutual information) 회귀</li>
</ul>
<h4 id="f-value">F-value</h4>
<ul>
<li>두 모집단(확률변수)의 분산의 비율을 나타내는 값</li>
<li>ANOVA, Regression에서는 모형이 설명하는 분산/잔차의 분산<ul>
<li>F-value가 크면 모형이 잘 설명하고 있다는 의미</li>
</ul>
</li>
</ul>
<h4 id="상호정보량mutual-information">상호정보량(mutual information)</h4>
<ul>
<li>하나의 확률변수가 다른 하나의 확률변수에 대해 제공하는 정보의 양</li>
<li>두 확률변수가 공유하는 엔트로피<ul>
<li>두 확률변수가 독립이라면, 상호정보량은 0</li>
<li>두 확률변수의 상관관계가 강할수록 상호정보량이 커짐</li>
</ul>
</li>
</ul>
<h4 id="χ2-test">χ2-test</h4>
<ul>
<li>범주형 데이터에서 두 요인간 독립성 검정에서 사용<ul>
<li>χ2-value가 크면 두 요인간 독립이 아니라는 의미(즉, 상관관계가 있음)</li>
</ul>
</li>
</ul>
<pre><code class="language-{python}">from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif, f_regression, chi2

# k개의 베스트 피쳐를 선택
sel_fc = SelectKBest(f_classif, k=2).fit(X, y)
print(&#39;f_classif: &#39;)
print(f&#39;{sel_fc.scores_ = }&#39;)
print(f&#39;{sel_fc.pvalues_ = }&#39;)
print(f&#39;{sel_fc.get_support() = }&#39;)
print(&#39;Selected features: &#39;, [X_names[i] for i in sel_fc.get_support(indices=True)]) # 선택된 피쳐들의 이름

sel_fr = SelectKBest(f_regression, k=2).fit(X, y)
print(&#39;\nf_regression: &#39;)
print(f&#39;{sel_fr.scores_ = }&#39;)
print(f&#39;{sel_fr.pvalues_ = }&#39;)
print(f&#39;{sel_fr.get_support() = }&#39;)
print(&#39;Selected features: &#39;, [X_names[i] for i in sel_fr.get_support(indices=True)]) # 선택된 피쳐들의 이름

sel_chi2 = SelectKBest(chi2, k=2).fit(X, y)
print(&#39;\nchi2: &#39;)
print(f&#39;{sel_chi2.scores_ = }&#39;)
print(f&#39;{sel_chi2.pvalues_ = }&#39;)
print(f&#39;{sel_chi2.get_support() = }&#39;)
print(&#39;Selected features: &#39;, [X_names[i] for i in sel_chi2.get_support(indices=True)]) # 선택된 피쳐들의 이름</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/65fb131d-5d6c-4dd3-a389-0a23b4729662/image.png" alt=""></p>
<hr>
<h2 id="32-래퍼-기법wrapper-method">3.2 래퍼 기법(Wrapper Method)</h2>
<ul>
<li><img src="https://velog.velcdn.com/images/__zeroiszero/post/c79228e0-7961-4927-9e3c-86e940d38df0/image.png" alt=""></li>
</ul>
<h4 id="변수-선택을-위한-알고리즘">변수 선택을 위한 알고리즘</h4>
<ul>
<li>전진 선택법(Forward Selection)<ul>
<li>모형을 가장 많이 향상시키는 변수를 하나씩 점진적으로 추가하는 방법</li>
</ul>
</li>
<li>후진 제거법(Backward Elimination)<ul>
<li>모두 포함된 상태에서 시작하여 가장 적은 영향을 주는 변수부터 하나씩 제거</li>
</ul>
</li>
<li>단계적 방법(Stepwise Method)<ul>
<li>전진선택과 후향제거의 결합</li>
<li>각 단계에서 최상의 속성을 선택하고 나머지 속성 중 최악의 속성을 제거하는 과정을 실행</li>
</ul>
</li>
<li>의사결정트리</li>
</ul>
<h4 id="래퍼기법의-종류">래퍼기법의 종류</h4>
<ul>
<li>RFE(Recursive Feature Elimination)<ul>
<li>SVM(Support Vector Machine)을 사용하여 재귀적으로 제거하는 방법</li>
<li>전진 선택, 후진 제거, 단계적 방법 사용</li>
</ul>
</li>
<li>SFS(Sequential Feature Selection)<ul>
<li>그리디 알고리즘(Greedy Algorithm)으로 빈 부분 집합에서 특성 변수를 하나씩 추가하는 방법</li>
<li>전진 선택, 후진 제거 사용
<img src="https://velog.velcdn.com/images/__zeroiszero/post/10bde7c4-c2cb-4499-b85b-04cab154cac1/image.png" alt=""></li>
</ul>
</li>
</ul>
<pre><code class="language-{python}"># RFE(Recursive Feature Elimination) 적용
from sklearn.datasets import load_iris
from sklearn.feature_selection import RFE, RFECV, SelectFromModel, SequentialFeatureSelector
from sklearn.svm import SVC, SVR

# iris 데이터셋 로드
X, y = load_iris(return_X_y=True)

# 분류기 SVC 객체 생성, 선형분류, 3개의 클래스 
svc = SVR(kernel=&quot;linear&quot;, C=3)

# RFE 객체 생성, 2개의 피쳐 선택, 1개씩 제거 
rfe = RFE(estimator=svc, n_features_to_select=2, step=1)
# RFE+CV(Cross Validation), 5개의 폴드, 1개씩 제거
rfe_cv = RFECV(estimator=svc, step=1, cv=5) 

# 데이터셋에 RFE 적용
rfe.fit(X, y)
print(&#39;RFE Rank: &#39;, rfe.ranking_)

# rank가 1인 피쳐들만 선택
X_selected = rfe.transform(X) 
X_selected_names = [X_names[i] for i in rfe.get_support(indices=True)] # 선택된 피쳐들의 이름

print(f&#39;{X_selected_names = }&#39;)
print(f&#39;{X_selected[:5] = }&#39;)

# 데이터셋에 RFECV 적용
rfe_cv.fit(X, y)
print(&#39;RFECV Rank: &#39;, rfe_cv.ranking_)

# rank가 1인 피쳐들만 선택
X_selected = rfe_cv.transform(X) 
X_selected_names = [X_names[i] for i in rfe_cv.get_support(indices=True)] # 선택된 피쳐들의 이름

print(f&#39;{X_selected_names = }&#39;)
print(f&#39;{X_selected[:5] = }&#39;)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/3a9c2500-e26a-47ed-8a69-0ee66afadd0a/image.png" alt=""></p>
<pre><code class="language-{python}"># SFS(Sequential Feature Selector) : 순차적으로 특성을 선택하는 방법

from sklearn.feature_selection import SequentialFeatureSelector
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris

# 데이터를 로드하고, 분류기를 초기화한 후 SFS를 적용
X, y = load_iris(return_X_y=True)
knn = KNeighborsClassifier(n_neighbors=3)
sfs = SequentialFeatureSelector(knn, n_features_to_select=2, direction=&#39;backward&#39;)

# SFS를 학습하고, 선택된 특성을 출력
sfs.fit(X, y)
print(&#39;SFS selected: &#39;, sfs.get_support())

# 선택된 피쳐들만 선택
X_selected = sfs.transform(X) 
X_selected_names = [X_names[i] for i in sfs.get_support(indices=True)] # 선택된 피쳐들의 이름

print(f&#39;{X_selected_names = }&#39;)
print(f&#39;{X_selected[:5] = }&#39;)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/b6b172b6-c3ee-4a98-8333-ff3be837ec52/image.png" alt=""></p>
<hr>
<h2 id="33-임베디드-기법embedded-method">3.3 임베디드 기법(Embedded Method)</h2>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/c04c75e8-7234-429d-b05c-504a3d172413/image.png" alt=""></p>
<h4 id="임베디드-기법의-종류">임베디드 기법의 종류</h4>
<ul>
<li>SelectFromModel<ul>
<li>의사결정나무 기반 알고리즘에서 변수를 선택하는 기법</li>
</ul>
</li>
</ul>
<pre><code class="language-{python}">from sklearn.feature_selection import SelectFromModel
from sklearn import tree
from sklearn.datasets import load_iris

# 데이터를 로드하고, 분류기를 초기화한 후 SFS를 적용
X, y = load_iris(return_X_y=True)
clf = tree.DecisionTreeClassifier()
sfm = SelectFromModel(estimator=clf)

# 모형 구조 확인 및 출력을 pandas로 설정
sfm.set_output(transform=&#39;pandas&#39;)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/2308da14-84d7-4709-92ec-d9a75d53df73/image.png" alt=""></p>
<pre><code class="language-{python}"># 모형 학습
sfm.fit(X, y)
print(&#39;SFM threshold: &#39;, sfm.threshold_)

# 선택된 피쳐들만 선택
X_selected = sfm.transform(X) 
X_selected.columns = [X_names[i] for i in sfm.get_support(indices=True)] # 선택된 피쳐들의 이름

X_selected.head()</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/fbce9ec8-0b96-41fb-a989-a197d7962af6/image.png" alt=""></p>
<hr>
<h1 id="응용-사례">응용 사례</h1>
<hr>
<h2 id="22-주성분-분석pca-응용">2.2 주성분 분석(PCA) 응용</h2>
<h4 id="pca는-다양한-분야에서-사용된다-주식이나-금융-분야에서도-pca는-다양하게-쓰인다-미국과-일본-유럽-한국의-과거-20년간의-주가를-살펴보는-예시에서-pca가-사용된다">PCA는 다양한 분야에서 사용된다. 주식이나 금융 분야에서도 PCA는 다양하게 쓰인다. 미국과 일본, 유럽, 한국의 과거 20년간의 주가를 살펴보는 예시에서 PCA가 사용된다.</h4>
<pre><code class="language-{python}">pd.core.common.is_list_like = pd.api.types.is_list_like
import pandas_datareader.data as web
import datetime

symbols = [
    &quot;SPASTT01USM661N&quot;, # US: 미국
    &quot;SPASTT01JPM661N&quot;, # JP: 일본
    &quot;SPASTT01EZM661N&quot;, # EZ: 유럽
    &quot;SPASTT01KRM661N&quot;, # KR: 한국
]

data = pd.DataFrame()
for sym in symbols:
    data[sym] = web.DataReader(sym, data_source=&#39;fred&#39;, 
                               start=datetime.datetime(1998, 1, 1),
                               end=datetime.datetime(2017, 12, 31))[sym]
data.columns = [&quot;US&quot;, &quot;JP&quot;, &quot;EZ&quot;, &quot;KR&quot;]
data = data / data.iloc[0] * 100

styles = [&quot;b-.&quot;, &quot;g--&quot;, &quot;c:&quot;, &quot;r-&quot;]
data.plot(style=styles)
plt.title(&quot;세계 주요국의 20년간의 주가&quot;)
plt.show()</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/8048a22a-fc04-467e-8ca9-0ff6ba06b841/image.png" alt=""></p>
<pre><code class="language-{python}"># 세계 주가의 공통요인은 평균값으로 구할수 있음
m = pca2.mean_
m</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/7ec6712f-d894-47e1-a399-31976609cf60/image.png" alt=""></p>
<pre><code class="language-{python}"># 나라별로 주가를 다르게 하는 요인은 &#39;주성분&#39; 으로 구할 수 있음
p1 = pca2.components_[0]
p1</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/c0e543a2-2250-4149-9fa6-8a3fb10e1c2c/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PP-인코딩과 범주화]]></title>
            <link>https://velog.io/@__zeroiszero/PP-%EC%9D%B8%EC%BD%94%EB%94%A9%EA%B3%BC-%EB%B2%94%EC%A3%BC%ED%99%94</link>
            <guid>https://velog.io/@__zeroiszero/PP-%EC%9D%B8%EC%BD%94%EB%94%A9%EA%B3%BC-%EB%B2%94%EC%A3%BC%ED%99%94</guid>
            <pubDate>Sun, 03 Dec 2023 12:22:40 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="1-인코딩">1 인코딩</h1>
<hr>
<h2 id="11-인코딩encoding">1.1 인코딩(Encoding)</h2>
<ul>
<li>많은 실제 데이터셋에는 <strong>수치형(numerical)과 범주형(categorical) 변수가 혼재</strong>하고 있음</li>
<li>인코딩은 컴퓨터가 처리하기 용이하도록 기존의 데이터를 변경하는 것<ul>
<li>범주형 데이터는 일반적으로 텍스트(string)로 되어 있으므로 이를 숫자(일반적으로 양의 정수)로 변환 → <strong>레이블 인코딩(Label encoding)</strong></li>
<li>분류(classification) 문제에서는 종속변수가 범주형이어야 하므로 수치형(numerical) 데이터는 범주형으로 변환해주어야 함 -&gt; <strong>이진화(Binarizsaztion), 이산화(Discretization)</strong></li>
<li>회귀(regression) 모형이나 신경망에서는 독립변수는 수치형 변수이어야 하므로 범주형 변수를 수치형으로 변환해주어야 함 → <strong>원핫인코딩(One-hot encoding), 더미변수화(Dummy encoding)</strong></li>
<li>텍스트 데이터는 자연어 처리를 위해 토큰화(tokenization) 과정을 거쳐야 함
→ <strong>정수인코딩(Integer encoding)</strong></li>
</ul>
</li>
<li>인코딩된 코드를 원래의 데이터로 변환하는 것은 <strong>디코딩(Decoding)</strong>이라고 함</li>
</ul>
<h4 id="인코딩의-장단점">인코딩의 장단점</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/94cac62e-3cff-4823-9fc8-0ca530f7ffc1/image.png" alt=""></p>
<hr>
<h2 id="12-인코딩-분류">1.2 인코딩 분류</h2>
<h4 id="1-범주형-데이터---이산-수치형-데이터">1. 범주형 데이터 -&gt; 이산 수치형 데이터</h4>
<ul>
<li><strong>OrdinalEncoder() (1:1)</strong><ul>
<li>범주형 데이터를 정수로 인코딩</li>
<li>여러 컬럼(독립변수)에 사용 가능</li>
</ul>
</li>
<li><strong>LabelEncoder() (1:1)</strong><ul>
<li>범주형 데이터를 정수로 인코딩</li>
<li>하나의 컬럼(종속변수, 타겟)에만 사용 가능</li>
</ul>
</li>
<li><strong>TargetEncoder() (1:1)</strong><ul>
<li>범주형 데이터를 특정한 컬럼(타겟)의 값의 크기와 비례한 숫자로 인코딩</li>
</ul>
</li>
</ul>
<h4 id="2-범주형-데이터---이진-데이터">2. 범주형 데이터 -&gt; 이진 데이터</h4>
<ul>
<li><strong>One-hot encoding (1:M)</strong><ul>
<li>하나의 컬럼에 있는 범주형 데이터를 여러개의 이진수 컬럼(수치형 데이터)로 인코딩</li>
<li>one-of-K 인코딩이라고도 함</li>
</ul>
</li>
<li><strong>Dummy encoding (1:M)</strong><ul>
<li>One-hot encoding과 동일한 기능</li>
<li>회귀분석에서 범주형 변수를 고려할 때 사용<h4 id="3-연속-수치형-데이터---이진-데이터">3. 연속 수치형 데이터 -&gt; 이진 데이터</h4>
</li>
</ul>
</li>
<li><strong>Binarizer() (1:1)</strong><ul>
<li>연속 수치형 데이터를 기준값(threshold)을 기준으로 이진수로 인코딩</li>
</ul>
</li>
<li><strong>LabelBinarizer() (1:M)</strong><ul>
<li>연속형 데이터를 이진수 컬럼으로 인코딩</li>
<li>하나의 컬럼(종속변수, 타겟)에만 사용 가능</li>
</ul>
</li>
<li><strong>MultiLabelBinarizer() (1:M)</strong><ul>
<li>multi-class(여러개의 범주가 있는) 데이터를 이진수 컬럼으로 인코딩</li>
<li>하나의 컬럼(종속변수, 타겟)에만 사용 가능</li>
</ul>
</li>
</ul>
<hr>
<h1 id="2-인코딩-방법">2 인코딩 방법</h1>
<hr>
<h2 id="21-범주형-데이터---이산-수치형-데이터">2.1 범주형 데이터 -&gt; 이산 수치형 데이터</h2>
<h4 id="테스트를-위한-데이터-세트-생성하기">테스트를 위한 데이터 세트 생성하기</h4>
<pre><code class="language-{python}">import pandas as pd

df = pd.DataFrame({&#39;weight&#39;:[40, 80, 60, 50, 90], # feature: weight, continuous
                   &#39;height&#39;:[162, 155, 182, 173, 177], # feature: height, continuous
                   &#39;sex&#39;:[&#39;f&#39;, &#39;m&#39;, &#39;m&#39;, &#39;f&#39;, &#39;m&#39;], # feature: sex, categorical
                   &#39;blood_type&#39;:[&#39;O&#39;, &#39;A&#39;, &#39;B&#39;, &#39;O&#39;, &#39;A&#39;], # feature: blood_type, categorical
                   &#39;health&#39;:[&#39;good&#39;, &#39;excellent&#39;, &#39;bad&#39;, &#39;bad&#39;, &#39;good&#39;], # target: health, categorical
                   })
df</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/78440d8d-d06a-46e7-b2fe-a4adba51d54f/image.png" alt=""></p>
<h4 id="ordinalencoder">OrdinalEncoder</h4>
<ul>
<li>범주형 데이터를 정수로 인코딩</li>
<li>여러 컬럼(독립변수)에 사용 가능<pre><code class="language-{python}">from sklearn.preprocessing import OrdinalEncoder
</code></pre>
</li>
</ul>
<h1 id="데이터프레임-복사">데이터프레임 복사</h1>
<p>df_oe = df.copy()</p>
<h1 id="ordinalencoder에-대한-객체-생성">OrdinalEncoder에 대한 객체 생성</h1>
<p>oe = OrdinalEncoder()</p>
<h1 id="데이터로-oe-학습">데이터로 oe 학습</h1>
<p>oe.fit(df)</p>
<h1 id="학습된-결과">학습된 결과</h1>
<p>print(f&#39;{oe.categories_=}&#39;)</p>
<h1 id="ordinalencoder는-수치형-weight와-height도-범주형으로-인식하여-변경하므로-주의">OrdinalEncoder는 수치형 weight와 height도 범주형으로 인식하여 변경하므로 주의</h1>
<h1 id="학습된-결과를-적용하여-변환">학습된 결과를 적용하여 변환</h1>
<p>df_oe = pd.DataFrame(oe.transform(df), columns=df.columns)
df_oe</p>
<pre><code>**↳ 결과**
![](https://velog.velcdn.com/images/__zeroiszero/post/00797c3a-6ac2-4517-91e5-d9e59a004112/image.png)

```{python}
# OrdinalEncoder 수정된 사용

# 데이터프레임 복사
df_oe = df.copy()

# OrdinalEncoder에 대한 객체 생성
oe = OrdinalEncoder()

# 데이터로 oe 학습
oe.fit(df[[&#39;sex&#39;, &#39;blood_type&#39;]])

# 학습된 결과 
print(f&#39;{oe.categories_=}&#39;)

# 학습된 결과를 적용하여 삽입
df_oe.iloc[:,2:4] = oe.transform(df[[&#39;sex&#39;, &#39;blood_type&#39;]])
df_oe</code></pre><p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/5103892b-0e19-49fe-ba2c-d2680f01b255/image.png" alt=""></p>
<pre><code class="language-{python}"># 디코딩(decoding)
oe.inverse_transform(df_oe.iloc[:,2:4])  </code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/d83fb391-881b-40b9-9244-e22974f726e4/image.png" alt=""></p>
<h4 id="labelencoder">LabelEncoder</h4>
<ul>
<li>범주형 데이터를 정수로 인코딩</li>
<li>하나의 컬럼(종속변수, 타겟)에만 사용 가능</li>
</ul>
<pre><code class="language-{python}">from sklearn.preprocessing import LabelEncoder

# 데이터프레임 복사
df_le = df.copy()

# LabelEncoder는 하나의 변수에 대해서만 변환 가능
# LabelEncoder 객체 생성과 fit을 동시에 적용
health_le = LabelEncoder().fit(df.health)
df_le[&#39;health&#39;] = health_le.transform(df.health)
df_le</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/4098ae41-0a41-47a1-8e29-9cd48e4c671d/image.png" alt=""></p>
<pre><code class="language-{python}"># fit_transform() 메서드를 사용하여 한번에 인코딩 수행가능

# 데이터프레임 복사
df_le = df.copy()

# LabelEncoder 객체 생성과 fit을 동시에 적용
df_le[&#39;health&#39;] = LabelEncoder().fit_transform(df.health)
df_le</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/2a79f2a6-016d-4387-aba5-29db10894f01/image.png" alt=""></p>
<h4 id="targetencoder-적용">TargetEncoder 적용</h4>
<ul>
<li>범주형 데이터를 특정한 컬럼(타겟)의 값의 크기와 비례한 숫자로 인코딩</li>
</ul>
<pre><code class="language-{python}">from sklearn.preprocessing import TargetEncoder

# 데이터프레임 복사
df_te = df.copy()

# TargetEncoder에 대한 객체 생성
# smooth는 정밀도를 조정하고 target_type은 인코딩 타입을 지정
te = TargetEncoder(smooth=0, target_type=&#39;continuous&#39;)

# 데이터로 te 학습
# 타겟을 weight라고 가정하고 blood_type을 인코딩
# blood_type_target은 weight와 비례하여 인코딩된 값
# 인코딩이 되는 값은 2차원으로 변환해야 함
te.fit(df[&#39;blood_type&#39;].values.reshape(-1, 1), df.weight)

# 학습된 결과 
print(f&#39;{te.categories_=}&#39;)

# 학습된 결과를 적용하여 새로운 컬럼 삽입
df_te[&#39;blood_type_target&#39;] = te.transform(df[&#39;blood_type&#39;].values.reshape(-1, 1))
df_te</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/71d63304-35e3-4763-906e-74d28e308788/image.png" alt=""></p>
<hr>
<h2 id="22-범주형-데이터-→-이진-데이터">2.2 범주형 데이터 → 이진 데이터</h2>
<hr>
<h4 id="원핫인코딩one-hot-encoding">원핫인코딩(One-Hot-Encoding)</h4>
<ul>
<li>하나의 컬럼에 있는 범주형 데이터를 여러개의 이진수 컬럼(수치형 데이터)로 인코딩</li>
<li>one-of-K 인코딩이라고도 함</li>
</ul>
<pre><code class="language-{python}">from sklearn.preprocessing import OneHotEncoder

# 데이터프레임 복사
df_ohe = df.copy()

# OneHotEncoder에 대한 객체 생성 후 fit
ohe = OneHotEncoder().fit(df_ohe[[&#39;blood_type&#39;]])

# 학습된 결과 
print(f&#39;{ohe.categories_=}&#39;)

# 학습된 결과를 적용하여 새로운 컬럼 삽입
# OneHotEncoder는 결과를 sparse matrix로 반환하므로 toarray()를 통해 ndarray로 변환
df_ohe[ohe.categories_[0]] = ohe.transform(df_ohe[[&#39;blood_type&#39;]]).toarray()
df_ohe</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/9caa5607-a177-4a86-8314-d709fcbd6e66/image.png" alt=""></p>
<h4 id="dummy-encoding">Dummy encoding</h4>
<ul>
<li>Pandas에서 제공하는 get_dummies는 One-hot encoding과 동일한 기능<ul>
<li>여러 컬럼을 한 번에 변환 가능</li>
</ul>
</li>
<li>회귀분석에서 범주형 변수를 고려할 때 사용</li>
</ul>
<pre><code class="language-{python}">pd.get_dummies(df, columns=[&#39;sex&#39;, &#39;blood_type&#39;], drop_first=False)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/2b84487f-3594-4691-a401-f851482d066a/image.png" alt=""></p>
<hr>
<h2 id="23-연속-수치형-데이터-→-이진-데이터">2.3 연속 수치형 데이터 → 이진 데이터</h2>
<h4 id="binerizer">Binerizer</h4>
<pre><code class="language-{python}">from sklearn.preprocessing import Binarizer

# 데이터 불러오기
df_bin = df.copy()

# Binarizer 객체 생성과 fit, transform을 동시에 적용
# Binarizer는 수치형 변수에 대해서만 변환 가능
df_bin[&#39;weight_bin&#39;] = Binarizer(threshold=50).fit_transform(df.weight.values.reshape(-1,1))
df_bin[&#39;height_bin&#39;] = Binarizer(threshold=170).fit_transform(df.height.values.reshape(-1,1))
df_bin</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/82d8b491-e2de-475d-a1f3-6501c2215b4e/image.png" alt=""></p>
<h4 id="labelbinerizer">LabelBinerizer</h4>
<ul>
<li>연속형 데이터를 이진수 컬럼으로 인코딩</li>
<li>하나의 컬럼(종속변수, 타겟)에만 사용 가능</li>
</ul>
<pre><code class="language-{python}">from sklearn.preprocessing import LabelBinarizer

# 데이터프레임 복사
df_lb = df.copy()

# LabelBinarizer 객체 생성과 fit을 적용
lb = LabelBinarizer().fit(df.health)

# lb.classes_ : LabelBinarizer가 인코딩한 클래스 확인
print(f&#39;{lb.classes_ = }&#39;)

# lb.transform() : 인코딩 변환
health_lb = lb.transform(df.health)
print(&#39;health_lb = \n&#39;, health_lb)

# 인코딩된 데이터를 데이터프레임으로 변환
df_lb[lb.classes_] = health_lb
df_lb</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/ee3549e0-5c3b-47b4-8d6b-021ad8347276/image.png" alt=""></p>
<h4 id="multilabelbinerizer">MultiLabelBinerizer</h4>
<ul>
<li>multi-class(여러개의 범주가 있는) 데이터를 이진수 컬럼으로 인코딩</li>
<li>하나의 컬럼(종속변수, 타겟)에만 사용 가능</li>
</ul>
<pre><code class="language-{python}">from sklearn.preprocessing import MultiLabelBinarizer

# 데이터프레임 복사
df_mlb = df.copy()

# multi-class를 위한 컬럼 추가
df_mlb[&#39;test&#39;] = [[&#39;math&#39;, &#39;english&#39;], [&#39;math&#39;, &#39;science&#39;], [&#39;science&#39;], [&#39;math&#39;, &#39;english&#39;], 
                           [&#39;science&#39;]] # target: test, categorical, multi-class
df_mlb</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/20aa966f-7587-4e9b-8cf2-7a1611655e43/image.png" alt=""></p>
<pre><code class="language-{python}"># MultiLabelBinarizer 객체를 생성하고 fit() 메소드를 호출하여 클래스를 인코딩
mlb = MultiLabelBinarizer().fit(df_mlb.test)

# classes_ 속성을 사용하면 어떤 클래스가 인코딩되었는지 확인 가능
print(f&#39;{mlb.classes_ = }&#39;)

# 인코딩된 데이터를 데이터프레임으로 변환
df_mlb[mlb.classes_] = mlb.transform(df_mlb.test)
df_mlb</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/4f70f459-a073-48ea-8b56-2f5e1ee32a0c/image.png" alt=""></p>
<hr>
<h1 id="3-범주화">3 범주화</h1>
<hr>
<h2 id="31-범주화-discritization">3.1 범주화 (Discritization)</h2>
<ul>
<li>연속형 변수를 구간별로 나누어 범주형 변수로 변환하는 것</li>
<li>quantization 또는 binning이라고도 함</li>
</ul>
<h4 id="k-bins-discretization">K-bins discretization</h4>
<pre><code class="language-{python}">from sklearn.preprocessing import KBinsDiscretizer

# 데이터프레임 복사
df_kbd = df.copy()

# KBinsDiscretizer 객체 생성과 fit을 적용
kbd = KBinsDiscretizer(n_bins=3, encode=&#39;ordinal&#39;).fit(df[[&#39;weight&#39;, &#39;height&#39;]])

# kbd.transform() : 인코딩 변환
# 인코딩된 데이터를 데이터프레임으로 변환
df_kbd[[&#39;weight_bin&#39;, &#39;height_bin&#39;]] = kbd.transform(df[[&#39;weight&#39;, &#39;height&#39;]])
df_kbd</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/81beb17f-a9bb-4c77-b0e4-7601a180ebe1/image.png" alt=""></p>
<hr>
<h1 id="응용-사례">응용 사례</h1>
<hr>
<h2 id="22의-원핫인코딩one-hot-encoding-응용">2.2의 원핫인코딩(One-Hot-Encoding) 응용</h2>
<pre><code class="language-{python}"># 필요한 패키지 임포트
import numpy as np 
import pandas as pd

from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer, make_column_transformer

# pandas로 데이터프레임 생성
df = pd.DataFrame([
    [2,1,&#39;male&#39;,&#39;A&#39;,3],
    [3,2,&#39;female&#39;,&#39;C&#39;,5],
    [3,4,&#39;male&#39;,&#39;B&#39;,7],
    [5,5,&#39;female&#39;,&#39;A&#39;,10],
    [7,5,&#39;female&#39;,&#39;B&#39;,12],
    [2,5,&#39;male&#39;,&#39;A&#39;,7],
    [9,2,&#39;male&#39;,&#39;C&#39;,13]
], columns=[&#39;hours&#39;, &#39;attendance&#39;, &#39;sex&#39;, &#39;cate&#39;, &#39;score&#39;])

from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder(sparse=False) # OneHotEncoder에 대한 객체를 생성

ohe.fit(df[[&#39;sex&#39;]]) # 위에서 객체 생성후 fit
print(ohe.transform(df[[&#39;sex&#39;]])) # 학습된 결과를 적용하여 새로운 컬럼 삽입
&#39;&#39;&#39;
[[0. 1.]
 [1. 0.]
 [0. 1.]
 [1. 0.]
 [1. 0.]
 [0. 1.]
 [0. 1.]]
&#39;&#39;&#39;

ohe.fit(df[[&#39;cate&#39;]])
print(ohe.transform(df[[&#39;cate&#39;]]))
&#39;&#39;&#39;
[[1. 0. 0.]
 [0. 0. 1.]
 [0. 1. 0.]
 [1. 0. 0.]
 [0. 1. 0.]
 [1. 0. 0.]
 [0. 0. 1.]]
&#39;&#39;&#39;
</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a96be2c8-dba4-4c74-8cf8-70b2fffac0a5/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PP-스케일링]]></title>
            <link>https://velog.io/@__zeroiszero/PP-%EC%8A%A4%EC%BC%80%EC%9D%BC%EB%A7%81</link>
            <guid>https://velog.io/@__zeroiszero/PP-%EC%8A%A4%EC%BC%80%EC%9D%BC%EB%A7%81</guid>
            <pubDate>Sat, 18 Nov 2023 12:00:38 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="1-scikit-learn">1 Scikit-Learn</h1>
<hr>
<h2 id="11-scikit-learn">1.1 Scikit-Learn</h2>
<ul>
<li><strong>python을 대표하는 머신러닝 라이브러리</strong></li>
<li><strong>매우 다양한 전처리 도구와 알고리즘을 제공</strong>하고 있어 머신러닝 기법을 배우는 데 적합<ul>
<li>분류, 회귀, 클러스터링, 차원 축소 등을 포함한 광범위한 머신러닝 알고리즘을 제공</li>
<li>예제와 사용 설명서가 잘 되어있어 참고하여 코드를 작성하기 용이</li>
</ul>
</li>
<li>데이터 분석을 위한 간단하고 효율적인 도구를 제공<ul>
<li><strong>간단하고 직관적인 API를 제공</strong>하므로 다양한 수준의 전문 지식을 가진 사용자가 접근 가능<ul>
<li>fit(), transform(), predict() 등 체계적이고 일관된 분석 및 학습모형 운용 체계를 갖추고 있음</li>
</ul>
</li>
<li>다른 많은 패키지도 scikit-learn과 동일한 체계를 제공하여 유사한 프레임에서 사용이 가능</li>
</ul>
</li>
<li><strong>NumPy, Pandas, SciPy 및 matplotlib를 기반으로 구축</strong>되어 있어 다른 파이썬 패키지와 함께 사용하기 용이<ul>
<li>NumPy: 다차원 배열을 위한 기본 패키지</li>
<li>Pandas: 데이터프레임을 위한 기본 패키지</li>
<li>SciPy: 과학 계산용 함수를 모아놓은 패키지</li>
<li>matplotlib: 데이터 시각화를 위한 패키지</li>
</ul>
</li>
<li>단점<ul>
<li>딥러닝, 강화학습, 시계열 모형은 매우 약함</li>
<li>최근 개발된 대용량을 위한 데이터프레임인 Polars와 같은 라이브러리와는 연동이 잘 안됨
<img src="https://velog.velcdn.com/images/__zeroiszero/post/f958e6a5-d323-4cac-a316-8b219f1d4e57/image.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<h2 id="12-scikit-learn의-주요-기능">1.2 Scikit-Learn의 주요 기능</h2>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/ba75d6c0-c6f0-4d44-8d59-00bd835e670b/image.png" alt=""></p>
<ul>
<li><strong>분류</strong>: 로지스틱 회귀, 결정 트리, 서포트 벡터 머신(SVM)</li>
<li><strong>회귀</strong>: 선형 회귀, 릿지 회귀 등</li>
<li><strong>군집화</strong>: k-평균 군집화, 계층적 군집화 등</li>
<li><strong>차원 축소</strong>: 주성분 분석(PCA), t-분산 확률적 이웃 내재화(t-SNE) 등</li>
<li><strong>전처리</strong>: 데이터 정규화, 스케일링, 인코딩 등</li>
</ul>
<hr>
<h1 id="2-scikit-learn-preprocessing">2 Scikit-Learn Preprocessing</h1>
<hr>
<ul>
<li>Scikit-learn의 전처리 기능은 크게 4가지로 나눌 수 있음<ul>
<li><strong>스케일링(scaling)</strong>: 서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 것</li>
<li><strong>이진화(binarization)</strong>: 연속적인 값을 0 또는 1로 나누는 것, 연속형 변수 → 이진형 변수</li>
<li><strong>인코딩(encodig)</strong>: 범주형 값을 적절한 숫자형으로 변환하는 작업, 범주형 변수 → 수치형 변수</li>
<li><strong>변환(transformation)</strong>: 데이터의 분포를 변환하여 정규성을 확보하는 것
<img src="https://velog.velcdn.com/images/__zeroiszero/post/7755a8bd-147c-4073-91b6-abcf89d55a85/image.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<h2 id="21-스케일링scaling">2.1 스케일링(Scaling)</h2>
<ul>
<li>서로 다른 변수(feature)의 값 범위를 선형변환을 통하여 일정한 수준으로 맞추는 작업<ul>
<li><strong>독립변수(feature)별로 값의 변위가 상이하면</strong><ul>
<li>종속변수(target)에 대한 영향이 독립변수의 변위에 따라 크게 달라짐 → <strong>머신러닝 시 학습효과가 떨어짐</strong></li>
</ul>
</li>
<li>다차원의 값들을 동일한 수준에서 비교 분석하기 용이하게 만들어 줌</li>
<li>컴퓨터의 비트수로 인하여 다른 값으로 인식되는 오버플로우(overflow)나 언더플로우(underflow)를 방지</li>
<li><strong>최적화 과정에서의 안정성 및 수렴 속도를 향상</strong></li>
<li>특히 <strong>k-means 등 거리 기반의 모델에서는 스케일링이 매우 중요</strong></li>
</ul>
</li>
<li>표준화, 정규화, 변환이 있음<ul>
<li><strong>표준화(Standardization) → 표준분포화</strong>(평균을 0, 분산을 1 로 스케일링)<ul>
<li><strong>StandardScaler()</strong>: 기본 스케일러, 평균과 표준편차 사용</li>
<li><strong>RobustScaler()</strong>: 중앙값과 IQR(Q3-Q1)을 사용. 이상치의 영향을 최소화</li>
</ul>
</li>
<li><strong>정규화(Normalization) → 규격화</strong>(특정 범위(주로 [0,1]) 로 스케일링)<ul>
<li><strong>MinMaxScaler()</strong>: 범위가 [0,1]이 되도록 스케일링</li>
<li><strong>MaxAbsScaler()</strong>: 양수는 [0,1], 음수는 [-1,0], 양음수는 [-1,1]이 되도록 스케일링</li>
</ul>
</li>
<li><strong>변환(Transformation)</strong>(특정한 분포나 모양을 따르도록 스케일링)<ul>
<li><strong>PowerTransformer(): 정규분포화</strong>(Box-Cox 변환, Yeo-Johnson 변환)</li>
<li><strong>QuantileTransformer()</strong>: 균일(Uniform)분포 또는 정규(Gaussian)분포로 변환</li>
<li><strong>Normalizer()</strong>: 한 행의 모든 피처들 사이의 유클리드 거리가 1이 되도록 변환
<img src="https://velog.velcdn.com/images/__zeroiszero/post/335507f2-f68c-4310-9b20-f7467453a1e4/image.png" alt=""></li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="22-스케일링-절차">2.2 스케일링 절차</h2>
<p>✍ <strong>Scaler 객체를 이용</strong></p>
<ol>
<li><strong>fit()</strong>: 주어진 데이터에 맞추어 학습<ul>
<li>데이터 변환을 위한 기준 정보 설정을 적용 (ex) 최소값, 최대값 등)</li>
</ul>
</li>
<li><strong>transform()</strong>: Scaler 적용, fit()된 정보를 이용해 데이터를 변환</li>
<li><strong>fit_transform()</strong> : fit()과 transform()을 한 번에 실행</li>
</ol>
<p>✍ <strong>훈련 데이터와 평가 데이터의 스케일링 변환 시 유의점</strong></p>
<ul>
<li><strong>훈련 데이터는 fit()과 transform() 모두 적용</strong><ul>
<li><strong>평가 데이터는 fit()은 필요없으므로 transform()만 적용</strong>해야 함</li>
<li>훈련 데이터로 fit()된 스케일링 기준 정보를 그대로 테스트에 적용해야하기 때문</li>
</ul>
</li>
</ul>
<hr>
<h2 id="23-표준화standardization">2.3 표준화(Standardization)</h2>
<ul>
<li>표준화를 하면, 서로 다른 통계 데이터들을 비교하기 용이함<ul>
<li>평균은 0, 분산과 표준편차는 1이 되므로 데이터의 분포가 단순화되어 독립변수간 데이터 수준의 비교가 용이</li>
<li>RBF(Radial Basis Function) 커널을 이용하는 서포트 벡터 머신(Support Vector Machine), 선형회귀(Linear Regression), 로지스틱 회귀(Logistic Regression)는 데이터가 정규분포를 가지고 있다고 가정하고 구현됨<ul>
<li>RBF Kernel: Gaussian kernel, 가우시안 방사 기저 함수</li>
</ul>
</li>
</ul>
</li>
<li>이상치에 민감하며, 분류보다는 회귀에 유용
<img src="https://velog.velcdn.com/images/__zeroiszero/post/90c4f1db-dbe4-45d4-aac5-326d81713516/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/435b95ee-0488-44d5-ba60-748a74142e30/image.png" alt=""></li>
</ul>
<p>✍ <strong>데이터 로드</strong></p>
<pre><code class="language-{python}">import pandas as pd
import seaborn as sns

# Pandas 소수점 4째자리 이하에서 반올림
pd.set_option(&#39;display.float_format&#39;, lambda x: f&#39;{x:.4f}&#39;)

# iris 데이터 로드
iris = sns.load_dataset(&#39;iris&#39;)

# iris의 수치형 변수만 선택
iris = iris.select_dtypes(exclude=&#39;object&#39;)

# iris의 기술통계량을 확인
iris.describe()

# sepal_lengh와 petal_length의 jointplot을 그림
sns.jointplot(data=iris, x=&#39;petal_length&#39;, y=&#39;petal_width&#39;, kind=&#39;reg&#39;)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a4f0ca46-4aa0-474a-bee3-8e215193da25/image.png" alt=""></p>
<p>✍ <strong>표준화</strong></p>
<pre><code class="language-{python}">from sklearn.preprocessing import StandardScaler, RobustScaler

# Scaler 객체 생성
standard_scaler = StandardScaler()
robust_scaler = RobustScaler()

# 데이터 변환
iris_standard = pd.DataFrame(standard_scaler.fit_transform(iris), columns=iris.columns)
iris_robust = pd.DataFrame(robust_scaler.fit_transform(iris), columns=iris.columns)

# 결과 출력
print(&#39;Standard Scaled: \n&#39;, iris_standard.describe()) # mean = 0, std = 1
print()
print(&#39;Robust Scaled: \n&#39;, iris_robust.describe()) # median = 0, IQR = 1</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/3b900c23-b553-4a1d-820d-c43f87635520/image.png" alt=""></p>
<ul>
<li>위에서 seaborn의 jointplot은 figure의 axes를 지정할 수 없어 subplot을 그리기가 어려움</li>
<li>patchworklib 패키지8을 사용하여 subplot을 그림<ul>
<li>설치 : conda install patchworklib</li>
</ul>
</li>
</ul>
<pre><code class="language-{python}">pip install patchworklib

# 그래프로 확인
import seaborn as sns
import patchworklib as pw
pw.overwrite_axisgrid()

# 첫번째 그래프 
g1 = sns.jointplot(data=iris_standard, x=&#39;petal_length&#39;, y=&#39;petal_width&#39;, kind=&#39;reg&#39;)
g1 = pw.load_seaborngrid(g1)
g1.set_suptitle(&quot;Standard Scaled&quot;)

# 두번째 그래프 
g2 = sns.jointplot(data=iris_robust, x=&#39;petal_length&#39;, y=&#39;petal_width&#39;, kind=&#39;reg&#39;)
g2 = pw.load_seaborngrid(g2)
g2.set_suptitle(&quot;Robust Scaled&quot;)

# 그래프 합치기
g12 = (g1|g2)
g12</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/cf49fc16-532d-4def-9b48-1609f542a7c5/image.png" alt=""></p>
<hr>
<h2 id="24-정규화normalization">2.4 정규화(Normalization)</h2>
<ul>
<li><strong>MinMaxScaler()</strong>: 범위가 [0,1]이 되도록 스케일링</li>
<li><strong>MaxAbsScaler()</strong><ul>
<li>모든 값이 양수이면, 범위가 [0,1]이 되도록 스케일링, MinMaxScaler()와 유사</li>
<li>모든 값이 음수이면, 범위가 [-1,0]이 되도록 스케일링</li>
<li>양수와 음수가 혼재하면, 범위가 [-1,1]이 되도록 스케일링</li>
</ul>
</li>
</ul>
<pre><code class="language-{python}">from sklearn.preprocessing import MinMaxScaler, MaxAbsScaler

# Scaler 객체 생성
minmax_scaler = MinMaxScaler()
maxabs_scaler = MaxAbsScaler()

# 데이터 변환
iris_minmax = pd.DataFrame(minmax_scaler.fit_transform(iris), columns=iris.columns)
iris_maxabs = pd.DataFrame(maxabs_scaler.fit_transform(iris), columns=iris.columns)

# 결과 출력
print(&#39;MinMax Scaled: \n&#39;, iris_minmax.describe()) # min = 0, max = 1
print()
print(&#39;MaxAbs Scaled: \n&#39;, iris_maxabs.describe()) # min ~ 0, max = 1</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a5a02396-e172-4e0c-ad4d-177254804e8a/image.png" alt=""></p>
<pre><code class="language-{python}"># 세번째 그래프 
g3 = sns.jointplot(data=iris_minmax, x=&#39;petal_length&#39;, y=&#39;petal_width&#39;, kind=&#39;reg&#39;)
g3 = pw.load_seaborngrid(g3)
g3.set_suptitle(&quot;MinMax Scaled&quot;)

# 네번째 그래프 
g4 = sns.jointplot(data=iris_maxabs, x=&#39;petal_length&#39;, y=&#39;petal_width&#39;, kind=&#39;reg&#39;)
g4 = pw.load_seaborngrid(g4)
g4.set_suptitle(&quot;MaxAbs Scaled&quot;)

# 그래프 합치기
g34 = (g3|g4)
g34</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/9eb561f6-572b-40ae-a31b-79ecca36279e/image.png" alt=""></p>
<hr>
<h2 id="25-변환transformation">2.5 변환(Transformation)</h2>
<ul>
<li><strong>PowerTransformer()</strong>: 정규성 변환(Box-Cox 변환, Yeo-Johnson 변환)</li>
<li><strong>QuantileTransformer()</strong>: 균일(Uniform)분포 또는 정규(Gaussian)분포로 변환</li>
<li><strong>Normalizer()</strong>: 한 행의 모든 피처들 사이의 유클리드 거리가 1이 되도록 변환</li>
</ul>
<pre><code class="language-{python}">import numpy as np
from sklearn.preprocessing import PowerTransformer, Normalizer

# Scaler 객체 생성
power_scaler = PowerTransformer()
normal_scaler = Normalizer()

# 데이터 변환
iris_power = pd.DataFrame(power_scaler.fit_transform(iris), columns=iris.columns)
iris_normal = pd.DataFrame(normal_scaler.fit_transform(iris), columns=iris.columns)

# 결과 출력
print(&#39;PowerTranformer Scaled: \n&#39;, iris_power.describe()) # mean = 0, std = 1
print()
print(&#39;Normalizer Scaled: \n&#39;, iris_normal.describe())
print(&#39;Euclidian Distance from 0: \n&#39;, np.linalg.norm(iris_normal, axis=1)) # 각 행의 벡터 크기가 1이 되는지 확인</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/d5188378-4f44-436a-b846-ac0614101f95/image.png" alt=""></p>
<pre><code class="language-{python}"># 다섯번째 그래프
g5 = sns.jointplot(data=iris_power, x=&#39;petal_length&#39;, y=&#39;petal_width&#39;, kind=&#39;reg&#39;)
g5 = pw.load_seaborngrid(g5)
g5.set_suptitle(&quot;PowerTransformer Scaled&quot;)

# 여섯번째 그래프
g6 = sns.jointplot(data=iris_normal, x=&#39;petal_length&#39;, y=&#39;petal_width&#39;, kind=&#39;reg&#39;)
g6 = pw.load_seaborngrid(g6)
g6.set_suptitle(&quot;Normalizer Scaled&quot;)

# 그래프 합치기
g56 = (g5|g6)
g56</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/f8b73141-2cf1-46e1-9977-ea1e8896a4e2/image.png" alt=""></p>
<pre><code class="language-{python}">from sklearn.preprocessing import QuantileTransformer

# Scaler 객체 생성
gaussian_scaler = QuantileTransformer(output_distribution=&#39;normal&#39;)
uniform_scaler = QuantileTransformer(output_distribution=&#39;uniform&#39;)

# 데이터 변환
iris_gaussian = pd.DataFrame(gaussian_scaler.fit_transform(iris), columns=iris.columns)
iris_uniform = pd.DataFrame(uniform_scaler.fit_transform(iris), columns=iris.columns)

# 결과 출력
print(&#39;QuantileTranformer_Gaussian Scaled: \n&#39;, iris_gaussian.describe())
print()
print(&#39;QuantileTranformer_Uniform Scaled: \n&#39;, iris_uniform.describe())</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/55f52d22-8dbd-4bfd-bbbd-f12268f40cdc/image.png" alt=""></p>
<pre><code class="language-{python}"># 일곱번째 그래프
g7 = sns.jointplot(data=iris_gaussian, x=&#39;petal_length&#39;, y=&#39;petal_width&#39;, kind=&#39;reg&#39;)
g7 = pw.load_seaborngrid(g7)
g7.set_suptitle(&quot;QuantileTranformer_Gaussian Scaled&quot;)

# 여덟번째 그래프
g8 = sns.jointplot(data=iris_uniform, x=&#39;petal_length&#39;, y=&#39;petal_width&#39;, kind=&#39;reg&#39;)
g8 = pw.load_seaborngrid(g8)
g8.set_suptitle(&quot;QuantileTranformer_Uniform Scaled&quot;)

# 그래프 합치기
g78 = (g7|g8)
g78</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a2cb4d62-900e-40cc-a9d6-52909657d9ec/image.png" alt=""></p>
<pre><code class="language-{python}"># 모든 그래프 합치기

(g1|g2|g3|g4)/(g5|g6|g7|g8)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/21cfd0f2-f3a5-442e-aba7-6546df268762/image.png" alt=""></p>
<hr>
<h1 id="응용-사례">응용 사례</h1>
<hr>
<h3 id="정규화-응용">정규화 응용</h3>
<pre><code class="language-{python}"># 판다스 불러오기
import pandas as pd
from sklearn.preprocessing import MinMaxScaler</code></pre>
<pre><code class="language-{python}"># 데이터 불러오기
df = pd.DataFrame([
    [2, 1, 3],
    [3, 2, 5],
    [3, 4, 7],
    [5, 5, 10],
    [7, 5, 12],
    [2, 5, 7],
    [8, 9, 13],
    [9, 10, 13],
    [6, 12, 12],
    [9, 2, 13],
    [6, 10, 12],
    [2, 4, 6]
], columns=[&#39;hour&#39;, &#39;attendance&#39;, &#39;score&#39;]) # hour, attendance, score 열로 할당</code></pre>
<p><strong>↳ 결과</strong></p>
<pre><code class="language-{python}"># 데이터 전처리
x_data = df.drop([&#39;score&#39;], axis=1) 
y_data = df[&#39;score&#39;]

x_data = df.drop([&#39;score&#39;], axis=1) 
y_data = df[&#39;score&#39;]

transformer = MinMaxScaler() #transformer = MinMaxScaler 적용 (feature_range는 (0, 1))

transformer.fit(x_data) #MinMaxScaler 모델에 x_train_df 데이터 적용 (최소값, 최대값 계산)
print(transformer.data_min_)
print(transformer.data_max_) 
x_data = transformer.transform(x_data)
print(x_data) # print해서 결과를 보면, 특성들의 범위가 0에서 1사이가 되도록 비례적으로 맞춰진것을 볼 수 있음 </code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a29859d6-932b-47a8-8d25-8f5a83e6fd3d/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PP-노이즈처리]]></title>
            <link>https://velog.io/@__zeroiszero/PP-%EB%85%B8%EC%9D%B4%EC%A6%88%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@__zeroiszero/PP-%EB%85%B8%EC%9D%B4%EC%A6%88%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Sat, 18 Nov 2023 10:08:50 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="1-노이즈">1 노이즈</h1>
<hr>
<h2 id="11-노이즈noise">1.1 노이즈(Noise)</h2>
<ul>
<li>측정된 변수에 무작위의 오류(random error) 또는 분산(variance)이 존재하는 것<h3 id="11-1-정형-데이터의-노이즈">1.1-1 정형 데이터의 노이즈</h3>
</li>
<li>정형 데이터에서 노이즈는 <strong>분산(varianve)</strong>으로 나타냄<ul>
<li><strong>분산</strong> : <strong>데이터의 무작위 변동</strong>을 의미함</li>
<li><strong>이상치</strong> : <strong>데이터의 무작위 변동을 초과하는 특정한 값</strong>으로 별도로 처리함</li>
<li>통계 모형에서는 오차항으로 나타남<ul>
<li><strong>오차항</strong> : <strong>모형에서 설명하지 못하는 무작위 변동</strong>을 의미함</li>
<li>ex) 단순선형회귀모형 -&gt; <strong>오차항 ϵi</strong>가 노이즈
<img src="https://velog.velcdn.com/images/__zeroiszero/post/9cefb1b9-af73-43f1-b043-49e297fb8bfc/image.png" alt=""><h3 id="11-2-이미지영상-데이터의-노이즈">1.1-2 이미지/영상 데이터의 노이즈</h3>
</li>
</ul>
</li>
</ul>
</li>
<li>이미지/영상에서 노이즈는 <strong>blur, white noise, pink noise, Guasian noise</strong>등 다양한 형태로 나타남<ul>
<li><strong>blur</strong> : <strong>이미지가 흐릿하게 보이는</strong> 현상</li>
<li><strong>white noise</strong> : <strong>백색 잡음, 모든 주파수를 가진 잡음</strong></li>
<li><strong>pink noise</strong> : <strong>특정 주파수 대역 (일반적으로 낮은 주파수) 에서 강하게 나타나는 노이즈</strong></li>
<li><strong>Gaussian noise</strong> : <strong>가우시안 분포를 따르는 잡음</strong></li>
</ul>
</li>
<li>이미지/노이즈의 주요 원인<ul>
<li>이미지 획득 과정에서 너무 낮은 수집된 광자의 양, 센서/렌즈의 열화 (degradation 등</li>
<li>이미지 전송 중 무선 통신의 에코 및 대기 왜곡 등
<img src="https://velog.velcdn.com/images/__zeroiszero/post/1f2477bb-f6c9-4756-8419-57e35710ea67/image.png" alt=""><h3 id="11-3-시계열음성신호-데이터의-노이즈">1.1-3 시계열/음성/신호 데이터의 노이즈</h3>
</li>
</ul>
</li>
<li>시계열/음성/신호에서 노이즈는 일반적으로 <strong>white noise (백색잡음)</strong> or <strong>Gaussian noise (가우시안 잡음)</strong> 으로 나타남<ul>
<li><strong>백색잡음</strong> : <strong>모든 주파수 영역에서 동일한 에너지를 갖는 잡음</strong></li>
<li><strong>가우시안 잡음</strong> : <strong>평균이 0, 분산이 1인 정규분포를 따르는 잡음</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/fb1c2910-d0c5-4565-b767-72bd94059241/image.png" alt=""><h3 id="11-4-텍스트-데이터의-노이즈">1.1-4 텍스트 데이터의 노이즈</h3>
</li>
</ul>
</li>
<li>일반적으로 철자, 오류, 약어, 비표준 단어, 반복, 구두점 누락, 대소문자 정보누락, &quot;음&quot; 및 &quot;어&quot;와 같은 의성어 등</li>
<li>텍스트 데이터의 노이즈는 자연어 처리의 성능을 저하시키는 중요한 요인</li>
<li>자동 음성 인식, 광학 문자 인식, 기계 번역, Web Scraping 등으로 수집한 데이터에 노이즈가 많음</li>
</ul>
<p>👉 <strong>ex) 음성 인식</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/9ab4bebb-d4fb-41bf-bbb3-bb2ed6d38baa/image.png" alt=""></p>
<hr>
<h2 id="12-defact결함-vs-fault불량-vs-artifact아티팩트-vs-noise잡음-노이즈">1.2 Defact(결함) vs Fault(불량) vs Artifact(아티팩트) vs Noise(잡음, 노이즈)</h2>
<ul>
<li>Defact, Falut, Artifact, Noise는 의미는 명확하게 구분되지만, 혼재되어 사용됨</li>
</ul>
<p><strong>1. Defact</strong></p>
<ul>
<li>Defact는 전체 데이터에 존재하는 일부 <strong>오류(error) 데이터</strong><ul>
<li>범위에서 벗어난 이상치(outlier)가 아니라, 잘못된(error) 데이터</li>
<li>주로 <strong>생산, 제조 분야에서 사용</strong>하는 용어<ul>
<li>Defact가 <strong>제품/설비의 기능에 손상을 야기하면 제품/설비가 Fault(불량/기능이상)이 됨</strong></li>
<li>모든 defect가 fault를 야기하진 않음</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>👉 <strong>ex) 반도체 결함</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/c34c8cb2-0ca1-4ae3-9426-cc50b5990600/image.png" alt=""></p>
<p>-** Artifact(아티팩트)**는 Defact와 동일한 의미를 갖는 용어</p>
<ul>
<li>주로 <strong>과학기술 분야에서 사용</strong>하는 용어, 특히 이미지의 defect를 지칭</li>
</ul>
<p>👉 <strong>ex) 두개골</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/7d5ff224-87e6-428a-aaf2-cbf8c4e88d5d/image.png" alt=""></p>
<p><strong>2. Noise(잡음, 노이즈)</strong></p>
<ul>
<li>Noise는 일반적으로 그 원인을 알 수 없는 무작위 변동을 의미함<ul>
<li>무작위(random)가 발생하는 기전(mechanism)을 알 수 없다는 의미임</li>
</ul>
</li>
<li>주로 신호처리(signal processing) 분야에서 사용하는 용어임</li>
<li>데이터 과학에서는 데이터의 무작위 변동을 의미</li>
<li>동작 기전을 모르므로 제거는 불가하고, 이를 저감(Denoising) 해야함<ul>
<li>디노이징 기법은 기본적으로 평활화(smoothing, 구간평균), 구간화(binning, 구간집계), 필터링(filtering, 주파성분 저감) 기법을 사용함</li>
</ul>
</li>
</ul>
<hr>
<h1 id="2-디노이징denoising">2 디노이징(Denoising)</h1>
<ul>
<li>디노이징은 데이터에서 노이즈를 저감하여 모형이 더 좋은 성능을 할 수 있도록 하는 전처리 과정</li>
</ul>
<hr>
<h2 id="21-정형-데이터의-디노이징">2.1 정형 데이터의 디노이징</h2>
<ul>
<li>구간화(Binning)<ul>
<li>정렬된 데이터 값들을 몇 개의 bin(혹은 bucket)으로 분할하여 대표값으로 대체</li>
</ul>
</li>
<li>군집화(clustering)<ul>
<li>유사한 값들을 하나의 군집으로 처리하여 중심점(centroid)을 대표값으로 대체</li>
</ul>
</li>
</ul>
<h3 id="21-1-구간화binning">2.1-1 구간화(Binning)</h3>
<p>✍ <strong>구간설정 방법</strong></p>
<p><strong>1. 동일 간격(equal-distance) 구간화 -&gt; pandas의 cut() 사용</strong></p>
<ul>
<li>동일한 간격으로 구간을 설정<ul>
<li>정상 데이터가 한쪽으로 편중(biassed)되고 outlier에 의해 영향을 많이 받음</li>
<li>한쪽으로 몰려있는 데이터들은 다 동일한 bin으로 들어오기 때문에 skewed data를 다룰 수 없음</li>
</ul>
</li>
</ul>
<p><strong>2. 동일 빈도(eual-frequency) 구간화 → pandas의 qcut() 사용</strong></p>
<ul>
<li>동일한 개수의 데이터를 가지는 구간으로 설정</li>
</ul>
<p>✍ <strong>구간별 대표값 설정 방법</strong></p>
<ul>
<li>평균값 평활화 : bin에 있는 값들을 평균값으로 대체</li>
<li>중앙값 평활화 : 중앙값으로 대체</li>
<li>경계값 평활화 : 경계값 중 가까운 값으로 대체<pre><code class="language-{python}">import pandas as pd
import numpy as np
</code></pre>
</li>
</ul>
<h1 id="데이터-생성하기-결과를-보기-용이하도록-sort">데이터 생성하기, 결과를 보기 용이하도록 sort</h1>
<p>df = pd.DataFrame({&#39;uniform&#39;: np.sort(np.random.uniform(0,10,10)),
                     &#39;normal&#39;: np.sort(np.random.normal(5,1,10)),
                     &#39;gamma&#39;: np.sort(np.random.gamma(2, size=10))})</p>
<h1 id="데이터-확인하기">데이터 확인하기</h1>
<p>df.plot(kind=&#39;hist&#39;, bins=15, alpha=0.5)
df.describe()                     </p>
<pre><code> **↳ 결과**
 ![](https://velog.velcdn.com/images/__zeroiszero/post/9d081281-a456-48e4-9aa0-986119b571ac/image.png)

#### 2.1-1-(1) Pandas로 구간화
```{python}
# cut(), qcut() 기본 동작 확인
col = &#39;uniform&#39;
num_bins = 5
df_binned = pd.DataFrame()
df_binned[col] = df[col].sort_values()  # 원 데이터
df_binned[&#39;eq_dist_auto&#39;] = pd.cut(df_binned[col], num_bins)  # 동일 간격으로 나누기
df_binned[&#39;eq_dist_fixed&#39;] = pd.cut(df_binned[col], bins=[0,2,4,6,8,10]) # 지정된 구간으로 나누기
df_binned[&#39;eq_freq_auto&#39;] = pd.qcut(df_binned[col], num_bins) # 동일 빈도로 나누기
df_binned</code></pre><p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/7ff408e4-a4e5-4d84-b1ef-29726d699b1e/image.png" alt=""></p>
<pre><code class="language-{python}"># 구간화하여 평균값 대체하기
cols = [&#39;uniform&#39;, &#39;normal&#39;, &#39;gamma&#39;]

# 동일 간격 구간화
df_ew = df.copy()
for col in cols:
    df_ew[col+&#39;_eq_dist&#39;] = pd.cut(df_ew[col], 3)   # 구간으로 나누기
    means = df_ew.groupby(col+&#39;_eq_dist&#39;)[col].mean() # 구간별 평균값 계산
    df_ew.replace({col+&#39;_eq_dist&#39;: means}, inplace=True) # 평균값으로 대체

display(df_ew)

# 동일 빈도 구간화
df_ef = df.copy()
for col in cols:
    df_ef[col+&#39;_eq_freq&#39;] = pd.qcut(df_ef[col], 3)   # 구간으로 나누기
    means = df_ef.groupby(col+&#39;_eq_freq&#39;)[col].mean() # 구간별 평균값 계산
    df_ef.replace({col+&#39;_eq_freq&#39;: means}, inplace=True) # 평균값으로 대체

display(df_ef)

# 시각화
import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 2, figsize=(10,5))
df_ew.astype(float).plot(ax=axes[0])
df_ef.astype(float).plot(ax=axes[1])
plt.show()</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/dab142d9-4c0f-4bde-ae80-6bb8d13b49f7/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/6d7647d7-1bcd-40ba-bc54-34eb4269ed18/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/9db7095d-84b9-46a9-a3a3-ea0f427f6c39/image.png" alt=""></p>
<h3 id="21-2-군집화clustering">2.1-2 군집화(clustering)</h3>
<h4 id="21-2-1-scikit-learn으로-구간화">2.1-2-(1) Scikit-Learn으로 구간화</h4>
<ul>
<li>KBinsDiscretizer() 사용<ul>
<li>encode{‘onehot’, ‘onehot-dense’, ‘ordinal’}, default=’onehot’</li>
<li>strategy{‘uniform’(동일간격), ‘quantile’(동일빈도), ‘kmeans’(K-Means 군집화)}, default=’quantile’</li>
</ul>
</li>
</ul>
<pre><code class="language-{python}">import warnings

# hide warnings
warnings.filterwarnings(&quot;ignore&quot;)

from sklearn.preprocessing import KBinsDiscretizer

# 동일 간격 구간화
ed_binner = KBinsDiscretizer(n_bins=3, encode=&#39;ordinal&#39;, strategy=&#39;uniform&#39;, subsample=None)
df_ed = ed_binner.fit_transform(df)

# 동일 빈도 구간화
ef_binner = KBinsDiscretizer(n_bins=3, encode=&#39;ordinal&#39;, strategy=&#39;quantile&#39;, subsample=None)
df_ef = ef_binner.fit_transform(df)

# K-means 구간화
km_binner = KBinsDiscretizer(n_bins=3, encode=&#39;ordinal&#39;, strategy=&#39;kmeans&#39;, subsample=None)
df_km = km_binner.fit_transform(df)

# 결과 확인
df_ed = pd.DataFrame(df_ed, columns=df.columns+&#39;_eq_dist&#39;)
df_ef = pd.DataFrame(df_ef, columns=df.columns+&#39;_eq_freq&#39;)
df_km = pd.DataFrame(df_km, columns=df.columns+&#39;_km&#39;)
df_bin = pd.concat([df, df_ed, df_ef, df_km], axis=1)
df_bin</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a811ff25-59ed-4f1e-a845-82fd2e5b3a93/image.png" alt=""></p>
<pre><code class="language-{python}"># 구간화하여 평균값 대체하기
for bin_col in df_bin.columns:
    col = bin_col.split(&#39;_&#39;)[0]
    means = df_bin.groupby(by=bin_col)[col].mean() # 구간별 평균값 계산
    df_bin.replace({bin_col: means}, inplace=True) # 평균값으로 대체

df_bin</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/29b27d9b-e075-40f9-aa92-9b16dd48e641/image.png" alt=""></p>
<pre><code class="language-{python}"># 시각화
import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 3, figsize=(15,5))
pd.concat([df_bin.iloc[:,:3], df_bin.iloc[:,3:6]], axis=1).astype(float).plot(ax=axes[0])
pd.concat([df_bin.iloc[:,:3], df_bin.iloc[:,6:9]], axis=1).astype(float).plot(ax=axes[1])
pd.concat([df_bin.iloc[:,:3], df_bin.iloc[:,9:]], axis=1).astype(float).plot(ax=axes[2])
plt.show()</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/973b526d-57b9-468a-b595-e3361ddffe3b/image.png" alt=""></p>
<hr>
<h1 id="응용-사례">응용 사례</h1>
<hr>
<h3 id="2-디노이징-응용">2 디노이징 응용</h3>
<pre><code class="language-{python}"># 특성 이산화

# 라이브러리 불러오기
import numpy as np
from sklearn.preprocessing import Binarizer

# 특성 만들기
age = np.array([[6],
                [12],
                [20],
                [36],
                [65]])

# Binarizer 객체를 만들기
binarizer = Binarizer(threshold=18)

# 특성 변환하기
binarizer.fit_transform(age)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/b1413917-1ce6-4620-9bc9-e04aca237b6c/image.png" alt=""></p>
<pre><code class="language-{python}"># 특성을 나눈다
np.digitize(age, bins=[20,30,64])</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/e9e648ab-17bd-4d28-a488-011f42b9d38d/image.png" alt=""></p>
<pre><code class="language-{python}"># 특성을 나눈다
np.digitize(age, bins=[20,30,64], right=True)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/39c09310-276b-486c-b648-c525397e1cbc/image.png" alt=""></p>
<pre><code class="language-{python}"># 특성을 나눈다
np.digitize(age, bins=[18])</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/295d6295-4631-4e2b-b756-ee37a2c82266/image.png" alt=""></p>
<pre><code class="language-{python}">from sklearn.preprocessing import KBinsDiscretizer

# 네 개의 구간으로 나누기
kb = KBinsDiscretizer(4, encode=&#39;ordinal&#39;, strategy=&#39;quantile&#39;)
kb.fit_transform(age)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/4e25b096-96e3-420e-932a-d2cfae9732a4/image.png" alt=""></p>
<pre><code class="language-{python}"># 원-핫 인코딩을 반환함
kb = KBinsDiscretizer(4, encode=&#39;onehot-dense&#39;, strategy=&#39;quantile&#39;)
kb.fit_transform(age)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/8acc36db-af29-4410-8ae7-06aee6d9e061/image.png" alt=""></p>
<pre><code class="language-{python}"># 동일한 길이의 구간을 만듦
kb = KBinsDiscretizer(4, encode=&#39;onehot-dense&#39;, strategy=&#39;uniform&#39;)
kb.fit_transform(age)</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/cc4dc506-cc7e-4522-aba2-ab36415eb67e/image.png" alt=""></p>
<pre><code class="language-{python}">kb.bin_edges_</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/26f17e27-ffa0-45c8-9e28-6aa09dd59bea/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PP-결측치처리]]></title>
            <link>https://velog.io/@__zeroiszero/PP-%EA%B2%B0%EC%B8%A1%EC%B9%98%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@__zeroiszero/PP-%EA%B2%B0%EC%B8%A1%EC%B9%98%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Sun, 15 Oct 2023 07:50:58 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="1-결측치-탐색">1 결측치 탐색</h1>
<hr>
<h2 id="11-결측치">1.1 결측치</h2>
<ul>
<li>데이터의 값이 누락된것 = 결측값, Missing Values<ul>
<li>NA 또는 N/A(Not Applicable or Not Available), NaN(Not a Number), NULL로 표기됨</li>
</ul>
</li>
<li>전산오류, 입력누락, 인위적 누락 등으로 발생함</li>
<li>설문조사(survey)와 종단연구(longitudinal research)에서 보편적으로 발생<ul>
<li>설문조사는 참가자 중 일부가 답변하기 곤란한 질문에 의도적으로 응답을 하지 않을 수 있음</li>
<li>종단연구는 특정 대상을 장기간에 걸쳐 조사하는 것으로, 사망, 임의탈퇴, 연락두절 등의 상태가 발생</li>
</ul>
</li>
</ul>
<hr>
<h2 id="12-결측치의-유형">1.2 결측치의 유형</h2>
<ul>
<li><strong>MCAR</strong>(Missing <strong>Completely</strong> At Random, <strong>완전 무작위</strong> 결측)<ul>
<li>결측치가 발생한 변수의 값에 상관없이 전체에 걸쳐 무작위로 발생한 경우</li>
<li>통계적으로 결측치의 영향이 없으므로 제거 가능</li>
</ul>
</li>
<li><strong>MAR</strong>(Missing At Random, <strong>무작위 결측</strong>)<ul>
<li>결측치가 발생한 변수의 값이 다른 변수와 상관관계가 있어 추정이 가능한 경우</li>
<li>통계적으로 결측치의 영향이 다소 있으나 편향은 없으므로 대체 가능함</li>
</ul>
</li>
<li><strong>MNAR</strong>(Missing <strong>Not At Random</strong>, <strong>비무작위</strong> 결측)<ul>
<li>결측치가 발생한 변수의 값과 관계가 있고 그 이유가 있는 경우</li>
<li>통계적으로 결측치의 영향이 크므로 결측치의 원인에 대한 조사 후 대응이 필요함
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a52511b2-7d27-489a-b11f-f9dd48ae5f9e/image.png" alt=""></li>
</ul>
</li>
</ul>
<h4 id="👉-결측치의-유형-예">👉 결측치의 유형 예</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/cfd2812c-7054-423e-b155-996db1ab6004/image.png" alt=""></p>
<p>(위에서)</p>
<ul>
<li>MCAR은 특별한 패턴이 없이 데이터가 누락</li>
<li>MAR은 낮은 IQ영역에서만 데이터 누락, IQ로 Job Performance Ratings를 어느정도 추정 가능</li>
<li>MNAR은 패턴은 존재하나 IQ로 추정이 불가능</li>
</ul>
<hr>
<h2 id="13-결측치-탐색">1.3 결측치 탐색</h2>
<h3 id="13-1-pandas를-이용한-결측치-탐색">1.3-1 Pandas를 이용한 결측치 탐색</h3>
<ul>
<li>(colab 기준) preprocessing_students.csv 를 다운로드 하여 content 파일에 업로드 해준다<pre><code class="language-python">import pandas as pd
</code></pre>
</li>
</ul>
<h1 id="데이터-세트-불러오기">데이터 세트 불러오기</h1>
<p>df = pd.read_csv(&#39;preprocessing_students.csv&#39;, sep=&#39;,&#39;)
df.head()</p>
<pre><code> #### 👉 결과
 ![](https://velog.velcdn.com/images/__zeroiszero/post/f413bfce-f1b6-49c6-9534-07dc11583cc8/image.png)

#### ✍ 결측치 갯수 확인하기
- df.info(), df.isnull(), df.notnull(), sum(0), sum(1)
``` python
# 데이터 정보에서 Non-Null Count 갯수로 결측치 확인
df.info()</code></pre><h4 id="👉-결과">👉 결과</h4>
<p> <img src="https://velog.velcdn.com/images/__zeroiszero/post/029689a1-9584-4a74-bb3c-39882119e3a9/image.png" alt=""></p>
<pre><code class="language-python"># isnull()의 True 개수를 합하여 확인 
print(df.isnull().sum(axis=0)) #  axis = 0 열기준, 1 행기준</code></pre>
<h4 id="👉-결과-1">👉 결과</h4>
<p> <img src="https://velog.velcdn.com/images/__zeroiszero/post/618a2cb2-fccb-4312-9aaf-988db5745b91/image.png" alt=""></p>
<ul>
<li>결측치는 weight, IQ, mid_score, employed로 각각 4,6,6,2개가 있음 (결측치의 유형은 파악 어려움)</li>
</ul>
<h3 id="13-2-klib을-이용한-결측치-탐색">1.3-2 klib을 이용한 결측치 탐색</h3>
<pre><code class="language-python">pip install klib

import klib
import warnings

# 경고 메시지 무시
warnings.filterwarnings(action=&#39;ignore&#39;) 

# 결측치에 대한 프로파일링 플롯
klib.missingval_plot(df)</code></pre>
<h4 id="👉-결과-2">👉 결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/f2fe3de1-26ae-4723-a035-6ee9f5dbb884/image.png" alt=""></p>
<pre><code class="language-python"># 결측치에 대한 프로파일링 플롯
klib.missingval_plot(df, sort=True)</code></pre>
<h4 id="👉-결과-3">👉 결과</h4>
<p> <img src="https://velog.velcdn.com/images/__zeroiszero/post/baf9eb65-c21b-4827-9378-aae776a5b41a/image.png" alt=""></p>
<ul>
<li>결측치 프로파일링 결과 weight, IQ, mid_score에 다수의 결측치가 존재</li>
</ul>
<pre><code class="language-python"># 상관관계 플롯
klib.corr_plot(df) </code></pre>
<h4 id="👉-결과-4">👉 결과</h4>
<p> <img src="https://velog.velcdn.com/images/__zeroiszero/post/5654013b-2a8b-4c3e-875a-386d87bbea82/image.png" alt=""></p>
<ul>
<li>변수간 상관분석 결과 weight와 height의 상관관계가 강한 양의 상관관계(0.78), IQ와 mid_score가 양의 상관관계(0.59), mid_score와 final_score가 양의 상관관계(0.53)을 보이고 있음</li>
</ul>
<pre><code class="language-python">import matplotlib.pyplot as plt
# 한글이 안나올 경우 폰트 지정
plt.rc(&#39;font&#39;, family=&#39;Malgun Gothic&#39;)

# 범주형 변수에 대한 분석
klib.cat_plot(df)</code></pre>
<h4 id="👉-결과-5">👉 결과</h4>
<p> <img src="https://velog.velcdn.com/images/__zeroiszero/post/6fbcc6a7-ff46-4160-85b4-cb49ed3f0277/image.png" alt=""></p>
<pre><code class="language-python"># 결측치가 있는 변수의 분포 확인
klib.dist_plot(df.weight)
klib.dist_plot(df.IQ)
klib.dist_plot(df.mid_score)</code></pre>
<h4 id="👉-결과-6">👉 결과</h4>
<p> <img src="https://velog.velcdn.com/images/__zeroiszero/post/92f4f550-9a0c-483a-abe7-9d033fdedf9e/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/88730f56-8e75-47e9-bd8d-910fbe269c99/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/883756b4-ee4b-4446-8b70-25a7ef5b243c/image.png" alt=""></p>
<ul>
<li>weight는 특정한 패턴이 보이지 않음</li>
<li>IQ는 중간 영역대의 밀도가 낮아 중간영역대의 데이터가 누락되었음을 확인 가능</li>
<li>mid_score는 낮은 점수대의 데이터가 누락되었음을 확인 가능</li>
</ul>
<hr>
<h1 id="2-결측치-처리">2 결측치 처리</h1>
<hr>
<h2 id="21-결측치-처리방법-개요">2.1 결측치 처리방법 개요</h2>
<ul>
<li>제거(deletion)<ul>
<li>MCAR(완전 무작위 결측) 일때 사용 가능함</li>
<li>데이터의 손실이 발생 -&gt; 자유도 감소 -&gt; 통계적 검정력 저하</li>
<li>표본의 수가 충분하고 결측값이 10%-15% 이내일 때에는 결측값을 제거한 후 분석해도 결과에 크게 영향을 주지 않음</li>
</ul>
</li>
<li>대체(imputation)<ul>
<li>표본 평균과 같은 대표값으로 대체할 경우 -&gt; 대표값 데이터가 많아짐 -&gt; 잔차 변동이 줄어듬 -&gt; 잘못된 통계적 결론 유도</li>
<li>모수추정 시 편향(bias) 발생함</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/de1de0d4-1625-433c-8e1f-e1669a99c102/image.png" alt=""></p>
<hr>
<h2 id="22-결측치-제거deletion">2.2 결측치 제거(Deletion)</h2>
<ul>
<li><ol>
<li><strong>Listwise deletion</strong></li>
</ol>
<ul>
<li><strong>결측치가 존재하는 행(instance) 자체를 삭제</strong>하는 방식</li>
<li>데이터 표본의 숫자가 적은 경우 표본의 축소로 인한 검정력 감소</li>
</ul>
</li>
<li>2.** Pairwise deletion**<ul>
<li><strong>분석에 사용하는 속성의 결측치가 포함된 행만 제거</strong>하는 방식</li>
<li>MCAR일때만 가능함
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a50e3c63-2dc1-4c95-a7f8-b2efdc90f832/image.png" alt=""></li>
</ul>
</li>
</ul>
<pre><code class="language-python">import pandas as pd

# Listwise deletion
df_listwise = df.dropna()

# Pairwise deletion
df_pairwise = df.dropna(subset=[&#39;weight&#39;, &#39;mid_score&#39;])

print(f&#39;Original Data:\n {df}\n&#39;)
print(f&#39;Listwise deletion:\n {df_listwise}\n&#39;)
print(f&#39;Pairwise deletion:\n {df_pairwise}\n&#39;)</code></pre>
<h4 id="👉-결과-7">👉 결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/c38e477b-5de2-455e-9a44-12af9d7ab468/image.png" alt=""></p>
<hr>
<h2 id="23-결측치-대체imputation">2.3 결측치 대체(Imputation)</h2>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/c7208aa1-23f5-403b-bb8e-eb815a2e7069/image.png" alt=""></p>
<h3 id="23-1-single-imputation단순대체법">2.3-1 Single Imputation(단순대체법)</h3>
<ul>
<li><strong>결측치의 대체값으로 하나의 값을 선정하는 것</strong></li>
<li>mean, correlation, 회귀계수와 같은 파라미터 추정시 편향(bias) 발생가능성 높음</li>
<li>이러한 추정 편향으로 인해 아예 결측값을 제거하는 것보다 통계적 특성이 나빠질 수 있음</li>
</ul>
<h4 id="📝-단순대체법-종류">📝 단순대체법 종류</h4>
<ul>
<li><strong>Explicit Modeling</strong></li>
<li><strong>1. Mean imputation</strong><ul>
<li>데이터의 평균값(mean, median, mode)으로 결측값을 대체</li>
<li>평균 대체 -&gt; 표본오차 왜곡, 축소 -&gt; 부정확한 p-value -&gt; 검정력 약화</li>
</ul>
</li>
<li><strong>2. Regression imputation</strong><ul>
<li>회귀식을 만들어 예측된 값으로 결측값 대체</li>
<li>회귀 예측값 대체 -&gt; 잔차 축소, 왜곡 -&gt; R-squared 증가, 왜곡</li>
</ul>
</li>
<li><strong>3. Stochastic regression imputation</strong><ul>
<li>회귀 예측값으로 대체하는 것과 유사하나, random error term을 추가하여 예측값에 변동을 주는 방법</li>
<li>표본오차의 과소 추정 문제가 있음 </li>
</ul>
</li>
<li><strong>Implicit Modeling</strong></li>
<li><strong>1. Hot deck imputation</strong><ul>
<li>연구중인 자료에서 표본을 바탕으로 비슷한 규칙을 찾아 결측값을 대체</li>
<li>다른 변수에서 비슷한 값을 갖는 데이터 중에서 하나를 랜덤 샘플링하여 그 값을 복사</li>
<li>결측값이 존재하는 변수가 가질 수 있는 값의 범위가 한정되어 있을때 사용</li>
</ul>
</li>
<li><strong>2. Cold deck imputation</strong><ul>
<li>외부 출처에서 비슷한 연구를 찾아 결측값을 대체</li>
<li>Hot deck imputation과 유사하나, 어떠한 규칙 하(ex) k번째 샘플의 값을 취해오는 등..)에서 하나를 선정</li>
</ul>
</li>
</ul>
<h3 id="23-2-단순대체법-python-적용">2.3-2 단순대체법 Python 적용</h3>
<ul>
<li><strong>1. Mean imputation</strong><ul>
<li>scikit-learn의 SimpleImputer 클래스를 사용<ul>
<li>strategy : mean/mode/most_frequent</li>
<li>데이터가 실수 연속값인 경우에는 평균 또는 중앙값을 사용, 값의 분포가 대칭적이면 평균이 좋고, 값의 분포가 심하게 비대칭인 경우에는 중앙값이 적당함</li>
<li>데이터가 범주값이거나 정수값인 경우에는 최빈값을 사용함</li>
</ul>
</li>
</ul>
</li>
<li><strong>2. Regression/Stochastic regression imputation</strong><ul>
<li>scikit-learn의 LinearRegression 사용</li>
</ul>
</li>
<li><strong>3. Hot deck/Cold deck imputation</strong><ul>
<li>Pandas의 fillna()적용</li>
</ul>
</li>
</ul>
<pre><code class="language-python">from sklearn.impute import SimpleImputer

df_imputed = pd.DataFrame.copy(df)

# 110대가 결측인 IQ는 평균으로 대체
df_imputed[[&#39;IQ&#39;]] = SimpleImputer(strategy=&quot;mean&quot;).fit_transform(df[[&#39;IQ&#39;]])

# 비대칭 분포를 갖는 mid_score는 중앙값으로 대체
df_imputed[[&#39;mid_score&#39;]] = SimpleImputer(strategy=&quot;median&quot;).fit_transform(df[[&#39;mid_score&#39;]])

# 범주형 employed는 Hot deck으로 대체
df_imputed[&#39;employed&#39;].fillna(method=&#39;bfill&#39;, inplace=True) 

# height와 양의 상관관계가 있는 weight는 Stochastic regression으로 대체
from sklearn.linear_model import LinearRegression
import numpy as np
# 결측치가 있는 인덱스 검색
idx = df.weight.isnull() == True
# 학습을 위한 데이터 세트 분리
X_train, X_test, y_train = df[[&#39;height&#39;]][~idx], df[[&#39;height&#39;]][idx], df[[&#39;weight&#39;]][~idx]
# 선형회귀모형 인스탄스 생성 후 학습
lm = LinearRegression().fit(X_train, y_train)
# 예측값 + 변동값하여 결측치를 대체
df_imputed.loc[idx, &#39;weight&#39;] = lm.predict(X_test) + 5*np.random.rand(4,1)

df_imputed</code></pre>
<h4 id="👉-결과-8">👉 결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/c566f72d-e053-4c8e-a5af-5f1e8e5d52bd/image.png" alt=""></p>
<h3 id="23-3-다중대체법multiple-imputation">2.3-3 다중대체법(Multiple Imputation)</h3>
<ul>
<li><strong>결측치의 대체값을 여러 추정값을 종합하여 선정하는 것</strong></li>
<li><strong>Multiple Imputation 3단계</strong><ul>
<li><ol>
<li><strong>Imputation Phase</strong>: 가능한 대체 값의 분포에서 추출된 서로 다른 값으로 복수의 데이터 셋을 생성</li>
</ol>
</li>
<li><ol start="2">
<li><strong>Analysis Phase</strong>: 각 데이터 셋에 대하여 모수의 추정치와 표본오차 계산</li>
</ol>
</li>
<li><ol start="3">
<li><strong>Pooling Phase</strong>: 모든 데이터 셋의 추정치와 표본오차를 통합하여 하나의 대치값 생성
<img src="https://velog.velcdn.com/images/__zeroiszero/post/a23c45be-78ef-490b-b709-7c4d603f0d62/image.png" alt=""></li>
</ol>
</li>
</ul>
</li>
</ul>
<h4 id="✍-micemultiple-imputation-by-chained-equations">✍ MICE(Multiple Imputation by Chained Equations)</h4>
<ul>
<li>다중대체법의 한 종류
<img src="https://velog.velcdn.com/images/__zeroiszero/post/322156c9-90ef-4c9e-8ed3-4e03b76e7a56/image.png" alt=""></li>
</ul>
<pre><code class="language-python">import numpy as np
# scikit-learn에서 R의 MICE 패키지를 따라서 실험적으로 개발 중
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer

# 데이터 세트
X_train = [[33, np.nan, .153], [18, 12000, np.nan], [np.nan, 13542, .125]]
X_test = [[45, 10300, np.nan], [np.nan, 13430, .273], [15, np.nan, .165]]

# mice 인스탄스 생성
mice = IterativeImputer(max_iter=10, random_state=0)
mice.fit(X_train)

np.set_printoptions(precision=5, suppress=True)
print(&#39;X_train MICE: \n&#39;, mice.transform(X_train))
print(&#39;X_test MICE: \n&#39;, mice.transform(X_test))</code></pre>
<h4 id="👉-결과-9">👉 결과</h4>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/16c0af6f-9fcf-44c6-b411-7f031c2a98ef/image.png" alt=""></p>
<h4 id="✍-knn-imputation">✍ KNN Imputation</h4>
<ul>
<li>KNN(K-Nearest Neighbor)은 분석대상을 중심으로 가장 가까운 k개 요소(이웃)들 중에서 가장 많은 수의 집단으로 분류하는 지도학습 알고리즘</li>
<li>KNN Imputation은 결측치가 범주형이면 이웃 데이터 중 최빈값으로 대체하고 연속형이면 이웃 데이터들의 중앙값으로 대체하는 방법
<img src="https://velog.velcdn.com/images/__zeroiszero/post/5987e26f-4ebd-47ff-ad41-ba629f3b7304/image.png" alt=""></li>
</ul>
<pre><code class="language-python">import numpy as np
from sklearn.impute import KNNImputer

knn = KNNImputer(n_neighbors=2, weights=&quot;uniform&quot;)
knn.fit(X_train)

print(&#39;X_train KNN: \n&#39;, knn.transform(X_train))
print(&#39;X_test KNN: \n&#39;, knn.transform(X_test))</code></pre>
<h4 id="👉-결과-10">👉 결과</h4>
<p> <img src="https://velog.velcdn.com/images/__zeroiszero/post/03dcb437-da2b-4894-a353-948519cb8b4d/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PP-프로파일링(코드 실습)]]></title>
            <link>https://velog.io/@__zeroiszero/PP-%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EB%A7%81%EC%BD%94%EB%93%9C-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@__zeroiszero/PP-%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EB%A7%81%EC%BD%94%EB%93%9C-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Mon, 09 Oct 2023 00:03:56 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="3-데이터-프로파일링을-위한-파이썬-패키지">3 데이터 프로파일링을 위한 파이썬 패키지</h1>
<hr>
<h2 id="31-klib">3.1 klib</h2>
<ul>
<li>Pandas 데이터프레임을 기반으로 데이터전처리 및 프로파일링을 제공해주는 패키지</li>
<li>데이터 품질평가, 전처리, 관계 시각화를 목적으로 사용</li>
<li>속도가 매우 빠르며 다양한 시각화 기능을 제공</li>
</ul>
<p><strong>설치</strong></p>
<pre><code class="language-{python}">pip install klib
pip install pandas
pip install seaborn

import warnings

# hide warnings
warnings.filterwarnings(&quot;ignore&quot;)

import klib
import pandas as pd
import seaborn as sns

df = sns.load_dataset(&quot;titanic&quot;)
df.head()</code></pre>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/15339e8f-4618-458e-9c8c-0c6ce518042d/image.png" alt=""></p>
<pre><code class="language-{python}"># 결측치에 대한 프로파일링 플롯
klib.missingval_plot(df)</code></pre>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/de6d8590-b580-4b48-8520-b70ee5b44342/image.png" alt=""></p>
<pre><code class="language-{python}"># 양의 상관관계 플롯
klib.corr_plot(df, split=&#39;pos&#39;)
# 음의 상관관계 플롯
klib.corr_plot(df, split=&#39;neg&#39;)</code></pre>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/24123ba4-8193-4418-8838-2c6c2c44162c/image.png" alt=""></p>
<ul>
<li>위의 그림은 양의 상관관계 그래프</li>
<li>색상이 어두울수록 상관관계가 크다는 의미
<img src="https://velog.velcdn.com/images/__zeroiszero/post/5e386df3-2ee7-4a99-a794-cc148c8dda1b/image.png" alt=""></li>
<li>위의 그림은 음의 상관관계 그래프</li>
<li>마찬가지로 색상이 어두울수록 상관관계가 크다는 의미<pre><code class="language-{python}"># default representation of correlations with the feature column
klib.corr_plot(df, target=&#39;age&#39;) # age를 기준으로한 다른 피쳐들과의 상관계수를 나타낸 그래프</code></pre>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/bedf691c-92fc-44b4-a3f6-7f59d97010ee/image.png" alt=""></li>
<li>위의 그림을 보면 age와 adult_male은 양의 상관관계가 높고, pclass와는 음의 상관관계가 높다<pre><code class="language-{python}">klib.corr_plot(df, target=&#39;fare&#39;) # fare를 기준으로한 다른 피쳐들과의 상관계수를 나타낸 그래프</code></pre>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/878346cd-e17c-448b-b192-a67ac4a3cf75/image.png" alt=""></li>
<li>위의 그림을 보면 fare는 pclass와는 음의 상관관계가 높은 반면, survived과는 약한 양의 상관관계를 가짐<pre><code class="language-{python}"># default representation of a distribution plot, other settings include fill_range, histogram, ...
klib.dist_plot(df) # 히스토그램 그리기</code></pre>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/84494cb6-3830-45ad-ab3b-e8122a0f81cb/image.png" alt=""><pre><code class="language-{python}">df_cleaned = klib.data_cleaning(df) # 데이터 클렌징</code></pre>
</li>
<li><ul>
<li>↳ df_cleaned 결과**<pre><code class="language-{python}">Shape of cleaned data: (784, 15) - Remaining NAs: 692

</code></pre>
</li>
</ul>
</li>
</ul>
<p>Dropped rows: 107
     of which 107 duplicates. (Rows (first 150 shown): [47, 76, 77, 87, 95, 101, 121, 133, 173, 196, 198, 201, 213, 223, 241, 260, 274, 295, 300, 304, 313, 320, 324, 335, 343, 354, 355, 358, 359, 364, 368, 384, 409, 410, 413, 418, 420, 425, 428, 431, 454, 459, 464, 466, 470, 476, 481, 485, 488, 490, 494, 500, 511, 521, 522, 526, 531, 560, 563, 564, 568, 573, 588, 589, 598, 601, 612, 613, 614, 635, 636, 640, 641, 644, 646, 650, 656, 666, 674, 692, 696, 709, 732, 733, 734, 738, 739, 757, 758, 760, 773, 790, 792, 800, 808, 832, 837, 838, 844, 846, 859, 863, 870, 877, 878, 884, 886])</p>
<p>Dropped columns: 0
     of which 0 single valued.     Columns: []
Dropped missing values: 177
Reduced memory by at least: 0.06 MB (-75.0%)</p>
<pre><code>---------------------------------------------
## 3.2 ydata-profiling
- interactive한 프로파일링 기능을 통합한 패키지
- pandas profiling에서 최근 ydata-profiling으로 이름 변경
- 주요 특징
  - 컬럼 데이터타입 자동 감지, 경고 요약, 단변량&amp;다변량 분석, 시계열에 대한 다양한 통계정보 포함, 텍스트 분석, 파일 및 이미지 분석, 데이터 세트 비교, 유연한 출력 형식 등..
### 3.2-1 ydata-profiling 활용
**ydata-profiling 패키지 및 ipywidgets 설치하기**
```{python}
pip install ydata-profiling ipywidgets</code></pre><p><strong>필요한 패키지 import하기</strong></p>
<pre><code class="language-{python}">import numpy as np
import pandas as pd
from ydata_profiling import ProfileReport</code></pre>
<p><strong>테스트 데이터 생성하기</strong></p>
<pre><code class="language-{python}">df = pd.DataFrame(np.random.rand(100, 5), columns=[&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;])
print(df.head())</code></pre>
<p>** ↳ 테스트 데이터 생성 결과**</p>
<pre><code class="language-{python}">          a         b         c         d         e
0  0.995817  0.268284  0.563712  0.569891  0.489493
1  0.054562  0.586358  0.311612  0.794190  0.076927
2  0.801426  0.570937  0.747227  0.812121  0.881083
3  0.032467  0.155426  0.434115  0.641922  0.912143
4  0.498620  0.106867  0.099020  0.988647  0.054433
</code></pre>
<p><strong>프로파일링 리포트 생성</strong></p>
<pre><code class="language-{python}">profile = ProfileReport(df, title=&quot;Ydata Profiling Report&quot;)

#profile.to_widgets() # jupyter notebook에서 위젯으로 보기
profile.to_notebook_iframe() # HTML 보고서와 유사한 방식으로 셀에 직접 포함
profile.to_file(&quot;my_profiling_report.html&quot;) # HTML로 별도 저장</code></pre>
<p>** ↳ 리포트 생성 결과**
<strong>하..진짜 주피터노트북에서 자꾸 에러나서 아래부터는 colab으로 함 ㅠㅠ</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/0a7f7932-b097-43f9-9d40-c605c8277f78/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/407f5574-f962-400b-83c8-68342ec7331e/image.png" alt=""></p>
<ul>
<li>위와 같은 데이터들을 전반적으로 요약한 결과물들이 문서 형태로 한눈에 볼 수 있게 출력됨<h3 id="32-2-결측치가-있는-데이터titanic">3.2-2 결측치가 있는 데이터(titanic)</h3>
<pre><code class="language-{python}">import seaborn as sns
import pandas as pd
</code></pre>
</li>
</ul>
<h1 id="seborn-데이터-세트-로드">Seborn 데이터 세트 로드</h1>
<p>df_titanic = sns.load_dataset(&#39;titanic&#39;)
df_titanic.head()</p>
<pre><code>**↳ 결과**
 ![](https://velog.velcdn.com/images/__zeroiszero/post/5f39e637-f2cb-4e52-ac5f-7aa69202c7f4/image.png)
**위의 titanic 데이터에 대한 프로파일링 리포트 생성하기**
```{python}
# titanic 데이터세트는 시간이 오래 걸려 최소수준의 분석만 실행
profile = ProfileReport(df_titanic, title = &quot;Titanic 데이터에 대한 프로파일링 보고서&quot;, minimal=True)

profile.to_notebook_iframe()
profile.to_file(&quot;titanic_profiling_report.html&quot;) # HTML로 별도 저장</code></pre><p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/83ede06e-eb93-4e1d-8a04-94ab27d78c60/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/4a7263e2-3559-4e79-b1c0-2b511ac9669e/image.png" alt=""></p>
<h3 id="323-nlp를-위한-네이버-영화-리뷰-데이터">3.2.3 NLP를 위한 네이버 영화 리뷰 데이터</h3>
<ul>
<li>Github 페이지에서 ko_test.csv 다운로드 함</li>
<li>** Google Drive와 연결하여 데이터나 파일에 대한 접근허용해준다!!**<pre><code class="language-{python}">import pandas as pd
</code></pre>
</li>
</ul>
<p>movie_df = pd.read_csv(&#39;ko_test_label.csv&#39;, sep = &#39;,&#39;)
#print(movie_df.info())
#print(movie_df.shape)
print(movie_df.head(5))</p>
<pre><code>**↳ 결과**
![](https://velog.velcdn.com/images/__zeroiszero/post/c9eb6724-29db-40e0-b66a-9e311444b21d/image.png)
**위의 영화리뷰에 대한 프로파일링 리포트 생성하기**
```{python}
pf_movie = ProfileReport(movie_df, title=&quot;네이버 영화 리뷰 데이터에 대한 프로파일링 보고서&quot;)
# pf_movie.to_widgets() # jupyter notebook에서 위젯으로 보기
pf_movie.to_notebook_iframe()
pf_movie.to_file(&quot;review_profiling_report.html&quot;) # HTML로 별도 저장</code></pre><p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/53563d87-48f1-41d9-85cc-c7213210c66d/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/550bf11f-c4de-4412-ba4c-6f0ac301bfce/image.png" alt=""></p>
<hr>
<h2 id="33-pygwalker">3.3 PyGWalker</h2>
<ul>
<li>PyGWalker(“Pig Walker”로 발음)는 시각화를 통한 탐색적 데이터 분석을 위한 Python 라이브러리</li>
<li>판다스 데이터프레임을 시각적으로 보기 위한 <strong>Tableau</strong> 스타일 사용자 인터페이스로 제공</li>
<li>간단한 끌어서 놓기 작업으로 데이터를 분석하고 패턴을 시각화 가능함</li>
</ul>
<p><strong>PyGWalker 설치하기</strong></p>
<pre><code class="language-{python}">pip install &quot;pygwalker[notebook]&quot; --pre</code></pre>
<p><strong>필요한 패키지 import하기</strong></p>
<pre><code class="language-{python}">import pandas as pd
import pygwalker as pyg</code></pre>
<p><strong>Pandas 데이터프레임으로 PyGWalker 실행함</strong></p>
<pre><code class="language-{python}">import seaborn as sns
# Seborn 데이터 세트 로드
df_titanic = sns.load_dataset(&#39;titanic&#39;)

gwalker = pyg.walk(df_titanic).display_on_jupyter()</code></pre>
<p><strong>↳ 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/f391f2ef-b43d-498d-a687-9e51ae5bcbac/image.png" alt="">
<img src="https://velog.velcdn.com/images/__zeroiszero/post/e31275ab-d428-42c4-a2a9-90e1bab99101/image.png" alt=""></p>
<ul>
<li>위 사진과 같이 x축, y축별로 왼쪽에서 변수를 끌어다가 놓을 수 있음</li>
<li>파이썬으로는 일일히 코딩하기 힘들지만 PyGWalker를 사용하면 마우스로 X,Y축에 놓일 변수들만 클릭하면 됨</li>
<li>polars가 판다스보다 대용량 데이터를 처리할 수 있음</li>
</ul>
<p><strong>DataFrame을 polars로 변경하여 pygwalker 실행</strong></p>
<pre><code class="language-{python}">import polars as pl

titanic_pl = pl.from_pandas(df_titanic)
gwalker = pyg.walk(titanic_pl).display_on_jupyter()</code></pre>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/7ae746d0-cf28-4669-9ca6-bd8c26a4c573/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PP-프로파일링(이론)]]></title>
            <link>https://velog.io/@__zeroiszero/PP-%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EB%A7%81</link>
            <guid>https://velog.io/@__zeroiszero/PP-%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EB%A7%81</guid>
            <pubDate>Sun, 08 Oct 2023 09:16:08 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="1-탐색적-데이터-분석-개요">1 탐색적 데이터 분석 개요</h1>
<h2 id="11-탐색적-데이터-분석eda">1.1 탐색적 데이터 분석(EDA)</h2>
<ul>
<li>EDA(Exploratory Data Analysis)라고 함</li>
<li>수집한 데이터를 분석하기 전에 그래프나 통계적인 방법을 이용하여 다양한 각도에서 데이터의 특징을 파악하고 자료를 직관적으로 바라보는 분석 방법</li>
<li>EDA를 통하여 <strong>데이터전처리</strong>, <strong>피쳐 엔지니어링</strong> 방향을 확보할 수 있음 <h2 id="12-eda-프로세스">1.2 EDA 프로세스</h2>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/a818fb49-f768-4660-a466-c7197519b30c/image.png" alt=""></p>
<ul>
<li>Step1 : 데이터의 속성(변수, feature) 확인하기</li>
<li>Step2 : 각 피쳐별 단변량 데이터 분석</li>
<li>Step3 : 피쳐간 상관관계 분석</li>
<li>Step4 : 결측치 처리하기</li>
<li>Step5 : 이상치 처리하기</li>
<li>Step6 : 피쳐 엔지니어링을 통한 피쳐 선택, 추가, 삭제하기<h2 id="13-변수-분석">1.3 변수 분석</h2>
<h3 id="단변량-분석">단변량 분석</h3>
</li>
<li>변수 하나에 대하여 <strong>기술통계량(descriptive statistics)</strong> 확인<ul>
<li>대표값 : 데이터의 평균, 중위수, 최빈수</li>
<li>산포 : 표준편차, 분산, 범위, 사분위수</li>
<li>분포 : 왜도, 첨도</li>
<li>기타 : 신뢰구간, 데이터의 정규성</li>
</ul>
</li>
<li>히스토그램이나 Boxplot을 사용 -&gt; 평균, 최빈값, 중간값 등과 함께 각 변수들의 분포를 확인</li>
<li>범주형 변수의 경우 Boxplot을 사용하여 빈도 수 분포를 체크<h3 id="이변량-분석">이변량 분석</h3>
</li>
<li><strong>변수 2개</strong>간의 관계를 분석<ul>
<li>상관관계 분석(correlation analysis) : 두 개 이상의 변수 사이에 존재하는 상호 연관성의 존재 여부와 연관성의 강도를 측정하여 분석</li>
</ul>
</li>
<li>변수의 유형에 따라 적절한 시각화 및 분석 방법을 적용(ex) 산점도)<h3 id="다변량-분석">다변량 분석</h3>
</li>
<li>범주형 변수가 하나 이상 포함되어 있는 경우에는 <strong>변수를 범주에 따라 분리한 후 분석 방법에 따라 분석함</strong></li>
<li>모두 연속형 변수일때 -&gt; 연속형 변수를 Feature engineering을 통해 범주형 변수로 변환한 후 분석, 혹은 3차원 그래프를 그려서 시각적으로 확인<h2 id="14-그래프-분석">1.4 그래프 분석</h2>
</li>
<li>데이터의 종류에 따라 적절한 그래프를 선택해야함</li>
<li>다양한 그래프를 통하여 피쳐들의 특성을 파악하는것이 중요함
<img src="https://velog.velcdn.com/images/__zeroiszero/post/d4ccfef7-dc01-4710-a9e5-619e81d7d797/image.png" alt="">
(출처:<a href="https://lantsandlaminins.com/writing-guides/choosing-a-graph-type/">https://lantsandlaminins.com/writing-guides/choosing-a-graph-type/</a>)</li>
</ul>
<hr>
<h1 id="2-데이터-프로파일링">2 데이터 프로파일링</h1>
<h2 id="21-데이터-프로파일링">2.1 데이터 프로파일링</h2>
<h3 id="프로파일링profiling">프로파일링(profiling)</h3>
<ul>
<li>어떤 개인의 심리적, 행동적 특성을 분석함으로써 특정 상황이나 영역에서의 행동을 예상하는 것</li>
<li>사회인구학적 특성을 포함한 여러 변수에 의해 특정한 하위 그룹으로 분류하는 것<h3 id="데이터-프로파일링이란">데이터 프로파일링이란?</h3>
</li>
<li>EDA(탐색적 데이터 분석)를 수행하는 것</li>
<li><strong>데이터 내 값의 분포</strong>, <strong>변수 간의 관계</strong>, NULL과 같은 <strong>결측값(missing value) 존재 유무</strong> 등을 분석
<img src="https://velog.velcdn.com/images/__zeroiszero/post/05b1f8f1-c72a-406c-8b7a-4c4ef9164053/image.png" alt=""><h2 id="22-데이터-프로파일링의-단계">2.2 데이터 프로파일링의 단계</h2>
<h3 id="22-1-메타데이터-수집-및-분석">2.2-1 메타데이터 수집 및 분석</h3>
</li>
<li>실제 운영중인 데이터베이스의 테이블명, 컬럼명, 제약조건 등의 정보를 분석<ul>
<li>테이블 정의서, 컬럼 정의서와 같은 데이터 관리 문서의 정보 분석</li>
<li>추출된 테이블 및 컬럼에 대한 메타데이터와 데이터 관리 문서를 매핑하여 불일치 사항을 분석
<img src="https://velog.velcdn.com/images/__zeroiszero/post/896d137b-11da-4f5c-adb0-8d707d7c52fb/image.png" alt=""><h3 id="22-2-컬럼-속성-분석">2.2-2 컬럼 속성 분석</h3>
</li>
</ul>
</li>
<li>대상 컬럼의 비유효한 값을 확인</li>
<li>컬럼의 총 건수, 유일값 수, NULL값 수, 공백값 수, 최댓값, 최솟값, 최대빈도, 최소빈도 등 기초 집계값을 산출하여 값이 유효한 범위 내에 있는지 판단
<img src="https://velog.velcdn.com/images/__zeroiszero/post/237c9ac9-645b-42a7-9e22-10c50db48f69/image.png" alt=""><h3 id="22-3-결측치-분석">2.2-3 결측치 분석</h3>
</li>
<li>반드시 입력되어야 하는데 누락이 발생한 컬럼을 발견하는 절차 </li>
<li>결측치에는 NULL값, 공백값 또는 숫자 0 등이 해당</li>
<li>NULL 허용 컬럼일지라도 NULL과 공백이 섞여있는 경우와 총 건수와 NULL건수가 같아 미사용으로 추정되는 컬럼을 발견하는 일도 포함
<img src="https://velog.velcdn.com/images/__zeroiszero/post/7114dfca-eb8a-456e-9037-cb510f570b99/image.png" alt=""><h3 id="22-4-허용범위-분석">2.2-4 허용범위 분석</h3>
</li>
<li>값이 가져야 할 범위 내에 그 값이 있는지를 파악하는 절차</li>
<li>허용범위는 해당 속성의 도메인 유형에 따라 정해짐</li>
<li>아래 예시에서 MAGAZINE 테이블의 권, 호, 페이지 등의 컬럼은 0 이상의 값을 가져야 하지만 최솟값이 -999 등으로 이루어진 것을 봐서 NULL 대신 무의미한 값을 부여한 데이터일 가능성이 큼</li>
<li>해당값이 오류 데이터라면 NULL값을 부여해야 함
<img src="https://velog.velcdn.com/images/__zeroiszero/post/6bf880a8-f1b6-4695-9b1a-d648c66bd532/image.png" alt=""><h3 id="22-5-허용값-분석">2.2-5 허용값 분석</h3>
</li>
<li>해당 컬럼의 허용값 목록이나 집합에 포함되지 않는 값을 발견하는 절차</li>
<li>코드 매핑 정의서에 기술한 코드 성격의 컬럼이 분석 대상에 해당<ul>
<li>아래 예시에서 등록되지 않은 코드가 포함되어 있거나 의미는 유사하나 다른 값으로 혼재된 경우를 확인가능
<img src="https://velog.velcdn.com/images/__zeroiszero/post/c5855bd1-a38a-4483-9666-096a09cd4a91/image.png" alt=""><h3 id="22-6-패턴-분석">2.2-6 패턴 분석</h3>
</li>
</ul>
</li>
<li>해당 컬럼의 문자열 유형을 따르지 않는 오류 유형을 발견하는 절차</li>
<li>데이터를 집계할 때 문자일 경우C, 숫자일 경우9, 공백일 경우S를 반환하는 함수를 만들어 사용<ul>
<li>해당 컬럼의 데이터를 패턴화하여 SQL로 조회하면 비정상적인 형태를 보인 값을 오류로 추정할 수 있음
<img src="https://velog.velcdn.com/images/__zeroiszero/post/12123b8c-d6e5-40c8-84c2-b7c58731f610/image.png" alt=""><h3 id="22-7-날짜-유형-분석">2.2-7 날짜 유형 분석</h3>
</li>
</ul>
</li>
<li>대상 컬럼이 DBMS의 DATE관련 자료형을 가지면 날짜 패턴 및 유효성 검증은 문제가 없음<ul>
<li>하지만 문자형 데이터 타입에 날짜 데이터를 입력하면 아래 예시와 같은 사례가 발생할 수 있음</li>
<li>이는 패턴 검증을 통하여 쉽게 검증할 수 있음
<img src="https://velog.velcdn.com/images/__zeroiszero/post/78aa11cc-3c3d-448f-b130-37e5767b8e33/image.png" alt=""><h3 id="22-8-유일값-분석">2.2-8 유일값 분석</h3>
</li>
</ul>
</li>
<li>업무적 의미에서 유일해야 하는 컬럼에 중복이 발생하였는지를 파악하는 절차</li>
<li>DBMS의 제약조건으로 PK(Primary Key)가 설정된 컬럼이나 UNIQUE가 설정된 컬럼은 문제없음<ul>
<li>아래 예시처럼 CUSTOMER테이블의 EMAIL컬럼은 PK컬럼이 아니지만, 업무적으로 고객의 이메일은 유일해야 하는 경우 최대 빈도를 통하여 중복된 데이터를 확인할 수 있음
<img src="https://velog.velcdn.com/images/__zeroiszero/post/bed5460e-3c9b-4d8e-be2f-8af84c9cbdbb/image.png" alt=""><h3 id="22-9-구조-분석">2.2-9 구조 분석</h3>
</li>
</ul>
</li>
<li>구조 결함으로 인해 일관되지 못한 데이터를 발견하는 분석 기법</li>
<li>아래 예시에 ORDER테이블에 CUSTOMER테이블에는 존재하지 않는 데이터가 존재하여 데이터의 일관성이 없는 오류 데이터가 발생</li>
<li>ERD(Entity Relationship Diagram)등 설계 시에는 관계를 설정해두고 실제 데이터베이스에는 제약조건을 적용하지 않고 개발하는 경우 이러한 사례가 빈번하게 발생
<img src="https://velog.velcdn.com/images/__zeroiszero/post/3520cdc2-a514-4e73-bd9f-fb510b9b41f5/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Py-Pandas]]></title>
            <link>https://velog.io/@__zeroiszero/Py-Pandas</link>
            <guid>https://velog.io/@__zeroiszero/Py-Pandas</guid>
            <pubDate>Sun, 24 Sep 2023 19:05:20 GMT</pubDate>
            <description><![CDATA[<h1 id="1-pandas">1 Pandas</h1>
<h2 id="11-판다스pandas">1.1 판다스(Pandas)</h2>
<ul>
<li><p>Python Data Analysis Library의 약어</p>
</li>
<li><p>R의 data.frame을 벤치마킹하여 Python에서 사용할 수 있는 형태의 Dataframe을 제공해주는 라이브러리</p>
</li>
<li><p>Python을 활용해 데이터 분석을 하기 위해서 사용하는 필수적인 패키지
<img src="https://velog.velcdn.com/images/__zeroiszero/post/402df552-e17b-4248-a653-8434641537da/image.png" alt=""></p>
<h2 id="12-데이터프레임-구조-및-명칭">1.2 데이터프레임 구조 및 명칭</h2>
<p><img src="https://velog.velcdn.com/images/__zeroiszero/post/a93cf16f-ef88-4566-a007-ed895fbe1cb1/image.png" alt=""></p>
<h3 id="필요한-패키지-import-하기">필요한 패키지 import 하기</h3>
<pre><code class="language-python">  import numpy as np
  import pandas as pd</code></pre>
<h1 id="2-데이터프레임-다루기기초">2 데이터프레임 다루기(기초)</h1>
<h2 id="21-데이터프레임-생성하기">2.1 데이터프레임 생성하기</h2>
</li>
<li><p>pandas.DataFrame()</p>
<ul>
<li><p>data : dict, list, set, ndarray, lterable 또는 DataFrame</p>
</li>
<li><p>[index] : index명, 디폴트는 0, 1, 2..</p>
</li>
<li><p>[columns] : 컬럼명, 디폴트는 0, 1, 2..</p>
</li>
<li><p>[dtype] : 데이터 타입 지정 </p>
</li>
<li><p>[copy] : 입력으로부터 복사, True or False</p>
<h3 id="직접-데이터프레임-작성하기">직접 데이터프레임 작성하기</h3>
<pre><code class="language-python">my_df = pd.DataFrame(data=np.array([[1, 2, 3], [4, 5, 6]])
                   , index=range(1,3), columns=[&#39;A&#39;,&#39;B&#39;,&#39;C&#39;])
print(my_df)</code></pre>
<p>  결과</p>
<pre><code> A  B  C</code></pre><p>  1  1  2  3
  2  4  5  6</p>
<h3 id="2d-array를-데이터프레임으로-변환">2D array를 데이터프레임으로 변환</h3>
<pre><code class="language-python">my_2darray = np.array([[1, 2, 3], [4, 5, 6]])
print(pd.DataFrame(my_2darray))</code></pre>
<p>  결과</p>
<pre><code> 0  1  2</code></pre><p>  0  1  2  3
  1  4  5  6</p>
<h3 id="dictionary를-데이터프레임으로-변환">dictionary를 데이터프레임으로 변환</h3>
<pre><code class="language-python">my_dict = {&#39;a&#39;: [&#39;1&#39;, &#39;3&#39;], &#39;b&#39;: [&#39;1&#39;, &#39;2&#39;], &#39;c&#39;: [&#39;2&#39;, &#39;4&#39;]}
print(pd.DataFrame(my_dict))</code></pre>
<p>  결과</p>
<pre><code> a  b  c</code></pre><p>  0  1  1  2
  1  3  2  4</p>
<h3 id="series를-데이터프레임으로-변환">Series를 데이터프레임으로 변환</h3>
<pre><code class="language-python">my_series = pd.Series({&#39;United Kingdom&#39;:&#39;London&#39;, &#39;India&#39;:&#39;New Delhi&#39;
                 , &#39;United States&#39;:&#39;Washington&#39;, &#39;Belgium&#39;:&#39;Brussels&#39;})
print(pd.DataFrame(my_series))</code></pre>
<p>   결과</p>
<pre><code>                           0</code></pre><p>United Kingdom      London
India            New Delhi
United States   Washington
Belgium           Brussels</p>
<h3 id="외부-파일로-부터-불러오기">외부 파일로 부터 불러오기</h3>
<pre><code class="language-python">df = pd.read_csv(&#39;bank.csv&#39;, sep = &#39;,&#39;)
print(df.head(3)) # default=5</code></pre>
<p>  결과</p>
<pre><code>age;&quot;job&quot;;&quot;marital&quot;;&quot;education&quot;;&quot;default&quot;;&quot;balance&quot;;&quot;housing&quot;;&quot;loan&quot;;&quot;contact&quot;;&quot;day&quot;;&quot;month&quot;;&quot;duration&quot;;&quot;campaign&quot;;&quot;pdays&quot;;&quot;previous&quot;;&quot;poutcome&quot;;&quot;y&quot;</code></pre><p>  0  30;&quot;unemployed&quot;;&quot;married&quot;;&quot;primary&quot;;&quot;no&quot;;1787;...<br>  1  33;&quot;services&quot;;&quot;married&quot;;&quot;secondary&quot;;&quot;no&quot;;4789;...<br>  2  35;&quot;management&quot;;&quot;single&quot;;&quot;tertiary&quot;;&quot;no&quot;;1350;...       </p>
<h2 id="22-데이터프레임-살펴보기">2.2 데이터프레임 살펴보기</h2>
<h3 id="메타데이터-확인하기">메타데이터 확인하기</h3>
<pre><code class="language-python">my_df = pd.DataFrame(data=np.array([[1, 2, 3], [4, 5, 6]])
               , index=range(1,3), columns=[&#39;A&#39;,&#39;B&#39;,&#39;C&#39;])
my_df.info()</code></pre>
<p>  결과
  &lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;
  RangeIndex: 2 entries, 1 to 2
  Data columns (total 3 columns):
   #Column  Non-Null Count  Dtype</p>
<hr>
<p>   0   A       2 non-null      int32
   1   B       2 non-null      int32
   2   C       2 non-null      int32
  dtypes: int32(3)
  memory usage: 156.0 bytes</p>
<h3 id="출력-제한-걸기">출력 제한 걸기</h3>
<pre><code class="language-python">pd.options.display.max_rows = 20  # 최대 표시 행수
pd.set_option(&#39;display.min_rows&#39;, 5) # 최소 표시 행수

df = pd.read_csv(&#39;bank.csv&#39;, sep = &#39;,&#39;).iloc[:,0:7]
print(df)</code></pre>
<p>   결과</p>
<pre><code>     age           job  marital  education default  balance housing</code></pre><p>0       58    management  married   tertiary      no     2143     yes
1       44    technician   single  secondary      no       29     yes
...    ...           ...      ...        ...     ...      ...     ...
45209   57   blue-collar  married  secondary      no      668      no
45210   37  entrepreneur  married  secondary      no     2971      no</p>
</li>
</ul>
</li>
</ul>
<p>[45211 rows x 7 columns]</p>
<h3 id="데이터프레임의-형태">데이터프레임의 형태</h3>
<pre><code class="language-python">     df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}
                  , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
     print(df.shape) # 행과 열의 수
     print(len(df.index)) # 인덱스(행)의 갯수</code></pre>
<pre><code>    결과
    (3, 3)
    3</code></pre><h3 id="데이터프레임-데이터-확인하기">데이터프레임 데이터 확인하기</h3>
<pre><code class="language-python">    df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}
                  , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
    print(df)
    display(df) # HTML로 출력</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/1b4b0bca-c01e-4c98-bdc0-b053caf306b8/image.png" alt=""></p>
<h2 id="23-데이터-추가-하기와-삭제하기">2.3 데이터 추가 하기와 삭제하기</h2>
<h3 id="행-추가하기">행 추가하기</h3>
<pre><code class="language-python">    df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}
                  , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
    df.loc[&#39;4th&#39;] = [41, 42, 43]
    df.loc[&#39;8th&#39;] = [81, 82, 83]
    print(df)</code></pre>
<pre><code>    결과
          A   B   C
    1st  11  12  13
    2nd  21  22  23
    3rd  31  32  33
    4th  41  42  43
    8th  81  82  83</code></pre><h3 id="열-추가하기">열 추가하기</h3>
<pre><code class="language-python">    df[&#39;D&#39;] = [14, 24, 34, 44, 84]
    print(df)</code></pre>
<pre><code>    결과
          A   B   C   D
    1st  11  12  13  14
    2nd  21  22  23  24
    3rd  31  32  33  34
    4th  41  42  43  44
    8th  81  82  83  84</code></pre><h3 id="열-삭제하기">열 삭제하기</h3>
<pre><code class="language-python">    df.drop(&#39;D&#39;, axis = 1, inplace = True) #inplace는 삭제 후 다시 저장
    print(df)</code></pre>
<pre><code>    결과
          A   B   C
    1st  11  12  13
    2nd  21  22  23
    3rd  31  32  33
    4th  41  42  43
    8th  81  82  83</code></pre><h3 id="행-삭제하기">행 삭제하기</h3>
<pre><code class="language-python">    df.drop([&#39;4th&#39;,&#39;8th&#39;], axis = 0, inplace = True) # inplace는 삭제 후 다시 저장
    print(df)</code></pre>
<pre><code>    결과
          A   B   C
    1st  11  12  13
    2nd  21  22  23
    3rd  31  32  33</code></pre><h2 id="24-인덱싱과-슬라이싱">2.4 인덱싱과 슬라이싱</h2>
<h3 id="열선택-dfcolname-dfcolname-dfcolname1colname2colname3">열선택: df[‘colname’], df.colname, df[[‘colname1’,‘colname2’,‘colname3’]]</h3>
<pre><code class="language-python">    df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}
                  , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
    print(df[&#39;C&#39;])
    print(df[[&#39;A&#39;,&#39;C&#39;]])</code></pre>
<pre><code>    결과
    1st    13
    2nd    23
    3rd    33
    Name: C, dtype: int64
          A   C
    1st  11  13
    2nd  21  23
    3rd  31  33</code></pre><h3 id="인덱스-선택-dfloc-dfloc-dfloc-dfloc">인덱스 선택: df.loc[], df.loc[[]], df.loc[:], df.loc[:,:]</h3>
<pre><code class="language-python">    print(df.loc[&#39;1st&#39;]) # 행 선택
    print(df.loc[[&#39;1st&#39;,&#39;3rd&#39;]]) # 여러행 선택</code></pre>
<pre><code>    결과
    A    11
    B    12
    C    13
    Name: 1st, dtype: int64
          A   B   C
    1st  11  12  13
    3rd  31  32  33</code></pre><pre><code class="language-python">    print(df.loc[&#39;1st&#39;:&#39;2nd&#39;]) # 행 슬라이싱
    print(df.loc[:,&#39;B&#39;:&#39;C&#39;]) # 행열 슬라이싱</code></pre>
<pre><code>    결과
          A   B   C
    1st  11  12  13
    2nd  21  22  23
          B   C
    1st  12  13
    2nd  22  23
    3rd  32  33</code></pre><h3 id="절대위치선택-dfiloc-dfiloc-dfiloc-dfiloc">절대위치선택: df.iloc[], df.iloc[[]], df.iloc[:], df.iloc[:,:]</h3>
<pre><code class="language-python">    print(df.iloc[0]) # 행 선택
    print(df.iloc[[0,2]]) # 여러행 선택</code></pre>
<pre><code>    결과
    A    11
    B    12
    C    13
    Name: 1st, dtype: int64
          A   B   C
    1st  11  12  13
    3rd  31  32  33</code></pre><pre><code class="language-python">    print(df.iloc[0:3]) # 행 슬라이싱
    print(df.iloc[:,1:3]) # 행열 슬라이싱</code></pre>
<pre><code>    결과
          A   B   C
    1st  11  12  13
    2nd  21  22  23
    3rd  31  32  33
          B   C
    1st  12  13
    2nd  22  23
    3rd  32  33</code></pre><h2 id="25-탐색하여-슬라이싱">2.5 탐색하여 슬라이싱</h2>
<h3 id="dataframe의-변수를-이용하여-슬라이싱">Dataframe의 변수를 이용하여 슬라이싱</h3>
<pre><code class="language-python">    df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}
                  , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
    print(df[df.C&lt;30]) # 행선택</code></pre>
<pre><code>    결과
          A   B   C
    1st  11  12  13
    2nd  21  22  23</code></pre><pre><code class="language-python">    print(df.loc[lambda x: x.C&lt;30]) #행 선택</code></pre>
<pre><code>    결과
          A   B   C
    1st  11  12  13
    2nd  21  22  23</code></pre><pre><code class="language-python">    print(df.loc[df[&#39;C&#39;]&lt;30, [&#39;A&#39;,&#39;B&#39;]]) #행열 선택</code></pre>
<pre><code>    결과
          A   B
    1st  11  12
    2nd  21  22</code></pre><h1 id="3-데이터프레임-다루기중급">3 데이터프레임 다루기(중급)</h1>
<h2 id="31-데이터프레임-클래스">3.1 데이터프레임 클래스</h2>
<ul>
<li><p>Python의 모든 자료구조는 클래스(class)임</p>
<ul>
<li>클래스는 객체로서 변수와 메소드(함수)의 집합체</li>
</ul>
</li>
<li><p>따라서 데이터프레임 객체의 변수와 메소드는 직접 사용이 가능함</p>
<h3 id="데이터프레임의-변수와-메서드-보기">데이터프레임의 변수와 메서드 보기</h3>
<pre><code class="language-python">  df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}, 
                index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
  print(dir(df)[:20])</code></pre>
<pre><code>  결과
  [&#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;T&#39;, &#39;_AXIS_LEN&#39;, &#39;_AXIS_ORDERS&#39;, &#39;_AXIS_TO_AXIS_NUMBER&#39;, &#39;_HANDLED_TYPES&#39;, &#39;__abs__&#39;, &#39;__add__&#39;, &#39;__and__&#39;, &#39;__annotations__&#39;, &#39;__array__&#39;, &#39;__array_priority__&#39;, &#39;__array_ufunc__&#39;, &#39;__bool__&#39;, &#39;__class__&#39;, &#39;__contains__&#39;, &#39;__copy__&#39;, &#39;__dataframe__&#39;]</code></pre><h2 id="32-데이터프레임-변수">3.2 데이터프레임 변수</h2>
<h3 id="데이터프레임의-열">데이터프레임의 열</h3>
<pre><code class="language-python">  df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}, 
                index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
  print(df.A) # .컬럼명</code></pre>
<pre><code>  결과
  1st    11
  2nd    21
  3rd    31
  Name: A, dtype: int64</code></pre><h3 id="데이터프레임의-ttranspose-전치행렬">데이터프레임의 T(transpose, 전치행렬)</h3>
</li>
<li><p>전치행렬이 이미 클래스 내의 T변수에 저장이 되어 있으므로 별도로 계산할 필요없이 바로 사용하면 됨</p>
<pre><code class="language-python">  print(df.T) # .T transpose</code></pre>
<pre><code>  결과
     1st  2nd  3rd
  A   11   21   31
  B   12   22   32
  C   13   23   33</code></pre><h2 id="33-사칙연산">3.3 사칙연산</h2>
<pre><code class="language-python">  df1 = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}
                , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
  df2 = pd.DataFrame({&#39;A&#39;:[11,21,41], &#39;B&#39;:[12,22,42], &#39;E&#39;:[14,24,44]}
                    , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;4th&#39;])

  print(df1+df2)  # 각 원소별 매칭되는 것만 더하기</code></pre>
<pre><code>  결과
          A     B   C   E
  1st  22.0  24.0 NaN NaN
  2nd  42.0  44.0 NaN NaN
  3rd   NaN   NaN NaN NaN
  4th   NaN   NaN NaN NaN</code></pre><pre><code class="language-python">  print(df1.add(df2, fill_value=0)) # 값이 없는 것은 0으로 대체하여 각 원소별 더하기 </code></pre>
<pre><code>  결과
          A     B     C     E
  1st  22.0  24.0  13.0  14.0
  2nd  42.0  44.0  23.0  24.0
  3rd  31.0  32.0  33.0   NaN
  4th  41.0  42.0   NaN  44.0</code></pre><pre><code class="language-python">  print(df1.mul(df2, fill_value=1)) # 값이 없는 것은 1로 대체하여 각 원소별 더하기</code></pre>
<pre><code>  결과
           A      B     C     E
  1st  121.0  144.0  13.0  14.0
  2nd  441.0  484.0  23.0  24.0
  3rd   31.0   32.0  33.0   NaN
  4th   41.0   42.0   NaN  44.0</code></pre><h2 id="34-assign">3.4 Assign</h2>
</li>
<li><p>기존의 열을 이용하여 새로운 열을 생성</p>
<pre><code class="language-python">  df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}
                , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
  print(df)</code></pre>
<pre><code>  결과
        A   B   C
  1st  11  12  13
  2nd  21  22  23
  3rd  31  32  33</code></pre><h3 id="새로운-열-생성">새로운 열 생성</h3>
<pre><code class="language-python">  print(df.assign(A_plus_B = df.A+df.B))</code></pre>
<pre><code>  결과
        A   B   C  A_plus_B
  1st  11  12  13        23
  2nd  21  22  23        43
  3rd  31  32  33        63</code></pre><h3 id="새로운-열-생성callable">새로운 열 생성(callable)</h3>
<pre><code class="language-python">  import numpy as np
  print(df.assign(log_A = lambda x:np.log(x.A)))</code></pre>
<pre><code>  결과
        A   B   C     log_A
  1st  11  12  13  2.397895
  2nd  21  22  23  3.044522
  3rd  31  32  33  3.433987</code></pre><h2 id="35-열-수정">3.5 열 수정</h2>
<pre><code class="language-python">  df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}
                , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
  df.insert(loc=0, column=&#39;D&#39;, value=[14,24,34])  # 열 삽입, df자체가 변경됨
  df.insert(loc=2, column=&#39;E&#39;, value=5)  # 열 삽입
  print(df)             </code></pre>
<pre><code>  결과
        D   A  E   B   C
  1st  14  11  5  12  13
  2nd  24  21  5  22  23
  3rd  34  31  5  32  33</code></pre><pre><code class="language-python">  df = df.drop(columns = [&#39;D&#39;,&#39;E&#39;]) # 열 제거, df에 저장해 주어야 함
  print(df)</code></pre>
<pre><code>  결과
        A   B   C
  1st  11  12  13
  2nd  21  22  23
  3rd  31  32  33</code></pre><pre><code class="language-python">  df = df.rename(columns = {&#39;A&#39;:&#39;aaa&#39;}) # 열이름 변경
  print(df)</code></pre>
<pre><code>  결과
       aaa   B   C
  1st   11  12  13
  2nd   21  22  23
  3rd   31  32  33</code></pre><h2 id="36-값-수정">3.6 값 수정</h2>
<pre><code class="language-python">  df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[13,23,33]}
                , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
  print(df)</code></pre>
<pre><code>  결과
        A   B   C
  1st  11  12  13
  2nd  21  22  23
  3rd  31  32  33</code></pre><h3 id="위치지정-수정">위치지정 수정</h3>
<pre><code class="language-python">  df[&#39;2nd&#39;,&#39;A&#39;] = 201  # 잘못된 명령어
  print(df)</code></pre>
<pre><code>  결과
        A   B   C  (2nd, A)
  1st  11  12  13       201
  2nd  21  22  23       201
  3rd  31  32  33       201</code></pre><pre><code class="language-python">  df.loc[&#39;2nd&#39;,&#39;A&#39;] = 222
  print(df)</code></pre>
<pre><code>  결과
         A   B   C  (2nd, A)
  1st   11  12  13       201
  2nd  222  22  23       201
  3rd   31  32  33       201</code></pre><pre><code class="language-python">  df.iloc[:,3] = &#39;NA&#39;
  print(df)</code></pre>
<pre><code>  결과
         A   B   C (2nd, A)
  1st   11  12  13       NA
  2nd  222  22  23       NA
  3rd   31  32  33       NA</code></pre><h3 id="값을-찾아서-대체">값을 찾아서 대체</h3>
<pre><code class="language-python">  df = df.replace(&#39;NA&#39;, 1111)
  print(df)</code></pre>
<pre><code>  결과
         A   B   C  (2nd, A)
  1st   11  12  13      1111
  2nd  222  22  23      1111
  3rd   31  32  33      1111</code></pre><pre><code class="language-python">  df = df.replace({&#39;B&#39;:32}, 9999)
  print(df)</code></pre>
<pre><code>  결과
         A     B   C  (2nd, A)
  1st   11    12  13      1111
  2nd  222    22  23      1111
  3rd   31  9999  33      1111</code></pre><h2 id="37-데이터-정렬">3.7 데이터 정렬</h2>
<pre><code class="language-python">  df = pd.DataFrame({&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[33,32,31]}
                , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
  print(df)</code></pre>
<pre><code>  결과
        A   B   C
  1st  11  12  33
  2nd  21  22  32
  3rd  31  32  31</code></pre><h3 id="정렬">정렬</h3>
<pre><code class="language-python">  df = df.sort_values(by=&#39;A&#39;, ascending=False) # 값기준 정렬
  print(df)</code></pre>
<pre><code>  결과
        A   B   C
  3rd  31  32  31
  2nd  21  22  32
  1st  11  12  33</code></pre><pre><code class="language-python">  df = df.sort_index(axis=0)    # 행 index 정렬
  print(df)</code></pre>
<pre><code>  결과
        A   B   C
  1st  11  12  33
  2nd  21  22  32
  3rd  31  32  31</code></pre><h3 id="랭크">랭크</h3>
<pre><code class="language-python">  df_rank = df.rank(axis=0, method=&#39;average&#39;, ascending=False)   # 열기준, 평균순위, 역순
  print(df_rank)</code></pre>
<pre><code>  결과
         A    B    C
  1st  3.0  3.0  1.0
  2nd  2.0  2.0  2.0
  3rd  1.0  1.0  3.0</code></pre><h2 id="38-melt">3.8 Melt</h2>
</li>
<li><p>pandas.melt()를 이용하여 wide format 데이터를 column format으로 변경</p>
<ul>
<li>id_var: 식별자 변수</li>
<li>value_vars: 해체할 열</li>
<li>var_name: 변수에 사용할 열이름</li>
<li>value_name: 해체된 열에 사용할 열이름</li>
<li>col_level: multiindex인 경우 이 수준을 사용<pre><code class="language-python">df = pd.DataFrame({&#39;order&#39;: [&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;],&#39;A&#39;:[11,21,31], &#39;B&#39;:[12,22,32], &#39;C&#39;:[33,32,31]})
print(df)</code></pre>
  결과<pre><code>order   A   B   C</code></pre>  0   1st  11  12  33
  1   2nd  21  22  32
  2   3rd  31  32  31<pre><code class="language-python">df_melted = pd.melt(df, id_vars=[&#39;order&#39;], value_vars=[&#39;A&#39;,&#39;B&#39;,&#39;C&#39;], var_name=&#39;name&#39;, value_name=&#39;score&#39;)
print(df_melted)</code></pre>
  결과<pre><code>order name  score</code></pre>  0   1st    A     11
  1   2nd    A     21
  2   3rd    A     31
  3   1st    B     12
  4   2nd    B     22
  5   3rd    B     32
  6   1st    C     33
  7   2nd    C     32
  8   3rd    C     31<h2 id="39-통계-처리">3.9 통계 처리</h2>
<h3 id="산술통계량-계산">산술통계량 계산</h3>
</li>
</ul>
</li>
<li><p>axis=0: 열별, axis=1: 행별, ddof=1: 표본 자유도 반영</p>
<pre><code class="language-python">  print(df.count(axis=0)) # 데이터 갯수</code></pre>
<pre><code>  결과
  order    3
  A        3
  B        3
  C        3
  dtype: int64</code></pre></li>
<li><p>최근 파이썬 버전부터는 수치형이 아닌경우 오류가 발생        </p>
<pre><code class="language-python">  df_numeric = df[[&#39;A&#39;,&#39;B&#39;,&#39;C&#39;]]

  df_numeric.mean(axis=1) # 평균</code></pre>
<pre><code>  결과
  0    18.666667
  1    25.000000
  2    31.333333
  dtype: float64</code></pre><pre><code class="language-python">  df_numeric.max(axis=0) # 최대값</code></pre>
<pre><code>  결과
  A    31
  B    32
  C    33
  dtype: int64</code></pre><pre><code class="language-python">  df_numeric.var(axis=1, ddof=1) # 표본분산</code></pre>
<pre><code>  결과
  0    154.333333
  1     37.000000
  2      0.333333
  dtype: float64</code></pre><pre><code class="language-python">  df_numeric.corr() # 상관계수</code></pre>
</li>
<li><p><em>👉 결과*</em>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/d1b52c28-5b01-4e5d-9bf6-a534f5dff438/image.png" alt=""></p>
</li>
</ul>
<h3 id="기술통계량-요약">기술통계량 요약</h3>
<pre><code class="language-python">    df = pd.DataFrame({&#39;A&#39;:[11,21,31,41], &#39;B&#39;:[12,22,32,42], &#39;C&#39;:[13,23,33,43]}
                  , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;,&#39;4th&#39;])
    print(df.describe()) #기술통계량</code></pre>
<pre><code>    결과
                   A          B          C
    count   4.000000   4.000000   4.000000
    mean   26.000000  27.000000  28.000000
    std    12.909944  12.909944  12.909944
    min    11.000000  12.000000  13.000000
    25%    18.500000  19.500000  20.500000
    50%    26.000000  27.000000  28.000000
    75%    33.500000  34.500000  35.500000
    max    41.000000  42.000000  43.000000</code></pre><h3 id="샘플링">샘플링</h3>
<pre><code class="language-python">    print(df.sample(n=2))</code></pre>
<pre><code>    결과
          A   B   C
    1st  11  12  13
    2nd  21  22  23    </code></pre><pre><code class="language-python">    print(df.sample(frac=0.5))</code></pre>
<pre><code>    결과
          A   B   C
    2nd  21  22  23
    1st  11  12  13</code></pre><h2 id="310-데이터-정제">3.10 데이터 정제</h2>
<pre><code class="language-python">    df = pd.DataFrame({&#39;A&#39;:[11,21,31,None,31], &#39;B&#39;:[12,22,32,42,32], &#39;C&#39;:[13,None,33,43,33]}
                  , index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;,&#39;4th&#39;,&#39;7th&#39;])
    print(df)</code></pre>
<pre><code>    결과
            A   B     C
    1st  11.0  12  13.0
    2nd  21.0  22   NaN
    3rd  31.0  32  33.0
    4th   NaN  42  43.0
    7th  31.0  32  33.0</code></pre><h3 id="중복데이터-제거">중복데이터 제거</h3>
<pre><code class="language-python">    print(df.drop_duplicates())</code></pre>
<pre><code>    결과
            A   B     C
    1st  11.0  12  13.0
    2nd  21.0  22   NaN
    3rd  31.0  32  33.0
    4th   NaN  42  43.0</code></pre><h3 id="결측치-행-제거">결측치 행 제거</h3>
<ul>
<li><p>결측값 있는 행 제거 : df.dropna() or df.dropna(axis=0)</p>
</li>
<li><p>결측값 있는 열 제거 : df.dropna(axis=1)</p>
<pre><code class="language-python">  print(df.dropna())</code></pre>
<pre><code>  결과
          A   B     C
  1st  11.0  12  13.0
  3rd  31.0  32  33.0
  7th  31.0  32  33.0</code></pre><h3 id="결측치-대체">결측치 대체</h3>
<ul>
<li>결측값을 특정 값으로 채우기 : df.fillna(특정값)</li>
<li>결측값을 결측값의 앞 행의 값으로 채우기 : df.fillna(method=‘ffill’) or df.fillna(method=‘pad’)</li>
<li>결측값을 결측값의 뒷 행의 값으로 채우기 : df.fillna(method=‘bfill’) or df.fillna(method=‘backfill’)</li>
<li>결측값을 각 열의 평균 값으로 채우기 : df.fillna(df.mean())<pre><code class="language-python">print(df)</code></pre>
<pre><code>결과
        A   B     C
1st  11.0  12  13.0
2nd  21.0  22   NaN
3rd  31.0  32  33.0
4th   NaN  42  43.0
7th  31.0  32  33.0</code></pre><pre><code class="language-python">print(df.fillna(axis=1, method=&#39;ffill&#39;))</code></pre>
<pre><code>결과
        A     B     C
1st  11.0  12.0  13.0
2nd  21.0  22.0  22.0
3rd  31.0  32.0  33.0
4th   NaN  42.0  43.0
7th  31.0  32.0  33.0</code></pre><pre><code class="language-python">print(df.fillna(df.mean()))</code></pre>
<pre><code>결과
        A   B     C
1st  11.0  12  13.0
2nd  21.0  22  30.5
3rd  31.0  32  33.0
4th  23.5  42  43.0
7th  31.0  32  33.0</code></pre><h2 id="311-filter">3.11 filter</h2>
</li>
</ul>
</li>
<li><p>데이터를 필터링하는 유용한 함수</p>
</li>
<li><p>람다함수와 정규표현식(regex) 사용이 가능하여 데이터 전처리시 유용</p>
<pre><code class="language-python">  df = pd.DataFrame({&#39;abc&#39;:[1,4,7], &#39;bcd&#39;:[2,5,8], &#39;abd&#39;:[3,6,9]}, index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
  print(df)</code></pre>
<pre><code>  결과
       abc  bcd  abd
1st    1    2    3
2nd    4    5    6
3rd    7    8    9</code></pre><h3 id="컬럼명으로-선택">컬럼명으로 선택</h3>
<pre><code class="language-python">  print(df.filter(items=[&#39;abc&#39;, &#39;abd&#39;]))</code></pre>
<pre><code>  결과
       abc  abd
  1st    1    3
  2nd    4    6
  3rd    7    9</code></pre><h3 id="정규표현식으로-선택">정규표현식으로 선택</h3>
<pre><code class="language-python">  print(df.filter(regex=&#39;^ab&#39;, axis=1)) # 열이름이 ab로 시작하는 열 선택</code></pre>
<pre><code>  결과
       abc  abd
  1st    1    3
  2nd    4    6
  3rd    7    9</code></pre><h3 id="문자열-포함으로-선택">문자열 포함으로 선택</h3>
<pre><code class="language-python">  print(df.filter(like=&#39;d&#39;, axis=0)) # 인덱스명에 d가 포함된 행 선택</code></pre>
<pre><code>  결과
       abc  bcd  abd
  2nd    4    5    6
  3rd    7    8    9</code></pre><h2 id="312-query">3.12 Query</h2>
</li>
<li><p>조건에 부합하는 데이터를 추출할 때 가장 많이 사용</p>
</li>
<li><p>.loc[ ] 로 구현한 것보다 속도가 느림</p>
<pre><code class="language-python">  df = pd.DataFrame({&#39;abc&#39;:[1,4,7], &#39;bcd&#39;:[2,5,8], &#39;abd&#39;:[3,6,9]}, index=[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;])
  print(df)</code></pre>
<pre><code>  결과
       abc  bcd  abd
  1st    1    2    3
  2nd    4    5    6
  3rd    7    8    9</code></pre><h3 id="질의어로-선택">질의어로 선택</h3>
<pre><code class="language-python">  print(df.query(&#39;abc &gt; 3&#39;))</code></pre>
<pre><code>  결과
       abc  bcd  abd
  2nd    4    5    6
  3rd    7    8    9</code></pre><pre><code class="language-python">  print(df.query(&#39;(abc &gt; 3) &amp; (abd &lt; 9)&#39;))</code></pre>
<pre><code>  결과
       abc  bcd  abd
  2nd    4    5    6</code></pre><h3 id="외부-값함수-참조-"><strong>외부 값(함수) 참조 @</strong></h3>
<pre><code class="language-python">  abd_max = 9
  print(df.query(&#39;(abc &gt; 3) &amp; (abd &lt; @abd_max)&#39;))</code></pre>
<pre><code>  결과
       abc  bcd  abd
  2nd    4    5    6</code></pre><h2 id="313-groupby">3.13 Groupby</h2>
</li>
<li><p>범주별로 그룹을 만들어서 데이터를 처리하고 Series로 반환</p>
<pre><code class="language-python">  df = pd.DataFrame({&#39;scale&#39;:[&#39;small&#39;,&#39;large&#39;,&#39;small&#39;,&#39;large&#39;]
                 , &#39;location&#39;:[&#39;east&#39;,&#39;east&#39;,&#39;south&#39;,&#39;south&#39;], &#39;sales&#39;:[10,20,30,40]})
  print(df)</code></pre>
<pre><code>  결과
     scale location  sales
  0  small     east     10
  1  large     east     20
  2  small    south     30
  3  large    south     40</code></pre><h3 id="scale별로-그룹을-나누어-sales의-합계를-구함">scale별로 그룹을 나누어 sales의 합계를 구함</h3>
<pre><code class="language-python">  data_s = df.groupby(by=&#39;scale&#39;)[&#39;sales&#39;].sum()
  print(data_s)
  print(type(data_s))  # Series 데이터
  print(data_s.index)
  print(data_s.values)</code></pre>
<pre><code>  결과
  scale
  large    60
  small    40
  Name: sales, dtype: int64
  &lt;class &#39;pandas.core.series.Series&#39;&gt;
  Index([&#39;large&#39;, &#39;small&#39;], dtype=&#39;object&#39;, name=&#39;scale&#39;)
  [60 40]</code></pre><h3 id="location-scale별로-그룹을-나누어-sales의-평균을-구함">location-scale별로 그룹을 나누어 sales의 평균을 구함</h3>
<pre><code class="language-python">  data_sl = df.groupby(by=[&#39;location&#39;, &#39;scale&#39;])[&#39;sales&#39;].mean()
  print(data_sl)
  print(type(data_sl))  # Series 데이터
  print(data_sl.index)
  print(data_sl.values)</code></pre>
<pre><code>  결과
  location  scale
  east      large    20.0
            small    10.0
  south     large    40.0
            small    30.0
  Name: sales, dtype: float64
  &lt;class &#39;pandas.core.series.Series&#39;&gt;
  MultiIndex([( &#39;east&#39;, &#39;large&#39;),
              ( &#39;east&#39;, &#39;small&#39;),
              (&#39;south&#39;, &#39;large&#39;),
              (&#39;south&#39;, &#39;small&#39;)],
             names=[&#39;location&#39;, &#39;scale&#39;])
  [20. 10. 40. 30.]</code></pre><h3 id="location-scale별로-그룹을-나누어-sales의-평균을-구하여-데이터프레임으로-반환">location-scale별로 그룹을 나누어 sales의 평균을 구하여 데이터프레임으로 반환</h3>
<pre><code class="language-python">  data_sl = df.groupby(by=[&#39;location&#39;, &#39;scale&#39;])[[&#39;sales&#39;]].mean()
  print(data_sl)
  print(type(data_sl))  # Series 데이터
  print(data_sl.index)
  print(data_sl.values)</code></pre>
<pre><code>  결과
                  sales
location scale       
east     large   20.0
         small   10.0
south    large   40.0
         small   30.0
&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;
MultiIndex([( &#39;east&#39;, &#39;large&#39;),
            ( &#39;east&#39;, &#39;small&#39;),
            (&#39;south&#39;, &#39;large&#39;),
            (&#39;south&#39;, &#39;small&#39;)],
           names=[&#39;location&#39;, &#39;scale&#39;])
[[20.]
 [10.]
 [40.]
 [30.]]</code></pre><h2 id="314-apply">3.14 Apply</h2>
</li>
<li><p>객체(함수)를 반복하여 적용</p>
</li>
<li><p>파이썬 내장함수 map과 유사</p>
<pre><code class="language-python">  df = pd.DataFrame({&#39;scale&#39;:[&#39;small&#39;,&#39;large&#39;,&#39;small&#39;,&#39;large&#39;]
                 , &#39;location&#39;:[&#39;east&#39;,&#39;east&#39;,&#39;south&#39;,&#39;south&#39;], &#39;sales&#39;:[10,20,30,40]})
  print(df)</code></pre>
<pre><code>  결과
     scale location  sales
  0  small     east     10
  1  large     east     20
  2  small    south     30
  3  large    south     40</code></pre><h3 id="map-적용">map 적용</h3>
<pre><code class="language-python">  print(list(map(lambda x: x**2, df.sales)))</code></pre>
<pre><code>  결과
  [100, 400, 900, 1600]</code></pre><h3 id="apply-적용">apply 적용</h3>
<pre><code class="language-python">  print(df.sales.apply(lambda x: x**2))</code></pre>
<pre><code>  결과
  0     100
  1     400
  2     900
  3    1600
  Name: sales, dtype: int64</code></pre><h2 id="315-join">3.15 Join</h2>
<pre><code class="language-python">  df1 = pd.DataFrame({&#39;id&#39;:[&#39;1st&#39;,&#39;2nd&#39;,&#39;3rd&#39;], &#39;name&#39;: [&#39;홍길동&#39;, &#39;임꺽정&#39;, &#39;김홍익&#39;]})
  df2 = pd.DataFrame({&#39;id&#39;:[&#39;2nd&#39;,&#39;3rd&#39;,&#39;4th&#39;], &#39;address&#39;: [&#39;서울&#39;, &#39;강원도&#39;, &#39;경기도&#39;]})
  print(df1)
  print(df2)</code></pre>
<pre><code>  결과
      id name
  0  1st  홍길동
  1  2nd  임꺽정
  2  3rd  김홍익
      id address
  0  2nd      서울
  1  3rd     강원도
  2  4th     경기도</code></pre><h3 id="합치기concat---axis--0-행으로-합침-axis--1-열로-합침">합치기(Concat) -&gt; axis = 0: 행으로 합침, axis = 1: 열로 합침</h3>
<pre><code class="language-python">  concat_row = pd.concat([df1,df2], axis = 0)
  concat_col = pd.concat([df1,df2], axis = 1)

  print(&#39;행으로 합침: \n&#39;, concat_row)
  print(&#39;열로 합침: \n&#39;, concat_col)</code></pre>
<pre><code>  결과
  행으로 합침: </code></pre><p>   id name address
  0  1st  홍길동     NaN
  1  2nd  임꺽정     NaN
  2  3rd  김홍익     NaN
  0  2nd  NaN      서울
  1  3rd  NaN     강원도
  2  4th  NaN     경기도
  열로 합침: </p>
<pre><code>   id name   id address</code></pre><p>  0  1st  홍길동  2nd      서울
  1  2nd  임꺽정  3rd     강원도
  2  3rd  김홍익  4th     경기도</p>
<h3 id="조인join">조인(Join)</h3>
</li>
<li><p>내부 결합(Inner Join): 두 개의 테이블 키가 일치하는 데이터만 추출</p>
</li>
<li><p>외부 결합(Outer Join): 두 개의 테이블 키와 관련된 모든 데이터 추출</p>
<pre><code class="language-python">  inner_join = pd.merge(df1, df2, on=&#39;id&#39;, how=&#39;inner&#39;)
  outer_join = pd.merge(df1, df2, on=&#39;id&#39;, how=&#39;outer&#39;)
  print(&#39;inner: \n&#39;, inner_join)
  print(&#39;outer: \n&#39;, outer_join)</code></pre>
<pre><code>  결과
  inner: </code></pre><p>   id name address
  0  2nd  임꺽정      서울
  1  3rd  김홍익     강원도
  outer: </p>
<pre><code>   id name address</code></pre><p>  0  1st  홍길동     NaN
  1  2nd  임꺽정      서울
  2  3rd  김홍익     강원도
  3  4th  NaN     경기도</p>
</li>
<li><p>좌 결합(Left Join): 왼쪽 테이블 키와 일치하는 데이터 추출</p>
</li>
<li><p>우 결합(Right Join): 오른쪽 테이블 키와 일치하는 데이터 추출</p>
<pre><code class="language-python">  left_join = pd.merge(df1, df2, on=&#39;id&#39;, how=&#39;left&#39;)
  right_join = pd.merge(df1, df2, on=&#39;id&#39;, how=&#39;right&#39;)
  print(&#39;left: \n&#39;, left_join)
  print(&#39;right: \n&#39;, right_join)</code></pre>
<pre><code>  결과
  left: </code></pre><p>   id name address
  0  1st  홍길동     NaN
  1  2nd  임꺽정      서울
  2  3rd  김홍익     강원도
  right: </p>
<pre><code>   id name address</code></pre><p>  0  2nd  임꺽정      서울
  1  3rd  김홍익     강원도
  2  4th  NaN     경기도</p>
<h1 id="4-데이터프레임-다루기고급">4 데이터프레임 다루기(고급)</h1>
<h2 id="41-메서드-결합">4.1 메서드 결합</h2>
<pre><code class="language-python">  df = pd.DataFrame({&#39;name&#39;:[&#39;Kim&#39;,&#39;Lee&#39;,&#39;Park&#39;,&#39;Kim&#39;,&#39;Lee&#39;,&#39;Kim&#39;]
                 , &#39;sex&#39;:[&#39;M&#39;,&#39;F&#39;,&#39;F&#39;,&#39;M&#39;,&#39;F&#39;,&#39;M&#39;]
                 , &#39;age&#39;:[20,25,30,20,25,20]
                 , &#39;class&#39;:[&#39;DS&#39;,&#39;DS&#39;,&#39;DS&#39;,&#39;PP&#39;,&#39;PP&#39;,&#39;DV&#39;]})
  print(df)</code></pre>
<pre><code>  결과
     name sex  age class
  0   Kim   M   20    DS
  1   Lee   F   25    DS
  2  Park   F   30    DS
  3   Kim   M   20    PP
  4   Lee   F   25    PP
  5   Kim   M   20    DV</code></pre><h3 id="class-별-수강학생수">class 별 수강학생수</h3>
<pre><code class="language-python">  df.groupby(by=&#39;class&#39;)[&#39;name&#39;].count()</code></pre>
<pre><code>  결과
  class</code></pre><p>  DS    3
  DV    1
  PP    2
  Name: name, dtype: int64</p>
<h3 id="학생별-수강교과목의-갯수">학생별 수강교과목의 갯수</h3>
<pre><code class="language-python">  df.groupby(by=[&#39;name&#39;,&#39;sex&#39;,&#39;age&#39;])[&#39;class&#39;].count()</code></pre>
<pre><code>  결과
  name  sex  age</code></pre><p>  Kim   M    20     3
  Lee   F    25     2
  Park  F    30     1
  Name: class, dtype: int64</p>
<h3 id="학생별-수강교과목이-2개-이상인-데이터만-필터링">학생별 수강교과목이 2개 이상인 데이터만 필터링</h3>
<pre><code class="language-python">  df.groupby(by=[&#39;name&#39;,&#39;sex&#39;,&#39;age&#39;]).filter(lambda x: len(x)&gt;=2)</code></pre>
</li>
<li><p><em>👉 결과*</em>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/987ef537-34d1-4832-aa86-4daed30aed88/image.png" alt=""></p>
</li>
</ul>
<h3 id="2-class-이상-수강하는-학생의-이름">2 class 이상 수강하는 학생의 이름</h3>
<pre><code class="language-python">    df.groupby(by=[&#39;name&#39;,&#39;sex&#39;,&#39;age&#39;]).filter(lambda x: len(x)&gt;=2)[&#39;name&#39;].unique()</code></pre>
<pre><code>    결과
    array([&#39;Kim&#39;, &#39;Lee&#39;], dtype=object)</code></pre><h3 id="2-class-이상-수강하는-학생의-평균-나이">2 class 이상 수강하는 학생의 평균 나이</h3>
<pre><code class="language-python">     (df
       .groupby(by=[&#39;name&#39;,&#39;sex&#39;,&#39;age&#39;])
       .filter(lambda x: len(x)&gt;=2)[[&#39;name&#39;,&#39;age&#39;]]
       .drop_duplicates()[&#39;age&#39;]
       .mean())</code></pre>
<pre><code>    결과
    22.5</code></pre><h2 id="42-pandas-그래프">4.2 Pandas 그래프</h2>
<ul>
<li><p>판다스는 Matplotlib 라이브러리의 기능을 일부 내장하고 있어 간단한 그래프를 그릴 수 있음</p>
</li>
<li><p>판다스에서 제공하는 plot(kind=＇옵션’) 메소드를 이용하여 그림</p>
<ul>
<li><p>‘line’ : line plot (default)</p>
</li>
<li><p>‘bar’ : vertical bar plot</p>
<ul>
<li>‘barh’ : horizontal bar plot</li>
</ul>
</li>
<li><p>‘hist’ : histogram</p>
</li>
<li><p>‘box’ : boxplot</p>
</li>
<li><p>‘kde’ : Kernel Density Estimation plot</p>
</li>
<li><p>‘density’ : same as ‘kde’</p>
</li>
<li><p>‘area’ : area plot</p>
</li>
<li><p>‘pie’ : pie plot</p>
</li>
<li><p>scatter’ : scatter plot (DataFrame only)</p>
</li>
<li><p>‘hexbin’ : hexbin plot (DataFrame only)</p>
<pre><code class="language-python">import pandas as pd
import matplotlib.pyplot as plt

df1 = pd.DataFrame(np.random.rand(5))
print(df1.head())

df2 = pd.DataFrame(np.random.rand(5))
print(df2.head())</code></pre>
<p>  결과</p>
<pre><code>        0</code></pre><p>  0  0.603505
  1  0.638853
  2  0.686185
  3  0.773065
  4  0.742881</p>
<pre><code>        0</code></pre><p>  0  0.401318
  1  0.021973
  2  0.496399
  3  0.966737
  4  0.949217</p>
<pre><code class="language-python">df1.plot()
df2.plot()
plt.title(&quot;랜덤 넘버 df1&quot;)
plt.rc(&#39;font&#39;, family=&#39;gulim&#39;)  
plt.show()</code></pre>
</li>
</ul>
</li>
<li><p><em>👉 결과1*</em><br><img src="https://velog.velcdn.com/images/__zeroiszero/post/1f53faa1-890d-4174-870d-4a96a4769950/image.png" alt=""></p>
</li>
</ul>
<p><strong>👉 결과2</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/923def80-01fe-48ef-a85a-3b73be2bdcd5/image.png" alt=""></p>
<pre><code class="language-python">    df = pd.concat([df1,df2], axis=1)
    df.columns = [&#39;df1&#39;, &#39;df2&#39;]
    print(df.head())
    df.plot()</code></pre>
<p><strong>👉 결과</strong><br><img src="https://velog.velcdn.com/images/__zeroiszero/post/75b6a9b6-75ee-4eb5-889e-0f09a39ff814/image.png" alt=""></p>
<pre><code class="language-python">    df.plot(kind=&#39;barh&#39;)</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/12d5ec79-0333-4c3c-9310-cd32ff050bdd/image.png" alt=""></p>
<pre><code class="language-python">    df.plot(kind=&#39;area&#39;)</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/d350b7ae-8117-46aa-aa59-1243b8614de0/image.png" alt="image"></p>
<pre><code class="language-python">    df.plot(kind=&#39;scatter&#39;, x=&#39;df1&#39;, y=&#39;df2&#39;)</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/f0859959-8a94-4f56-9d44-c45460dd39b4/image.png" alt="image"></p>
<h1 id="5-다양한-그래프-그려보기">5 다양한 그래프 그려보기</h1>
<ul>
<li><p>아래 그래프가 출력될 수 있도록 코드를 작성해보자</p>
<pre><code class="language-python">  import matplotlib.pyplot as plt

  fig, ax = plt.subplots()

  fruits = [&#39;apple&#39;, &#39;blueberry&#39;, &#39;cherry&#39;, &#39;orange&#39;]
  counts = [40, 100, 30, 55]
  bar_labels = [&#39;red&#39;, &#39;blue&#39;, &#39;_red&#39;, &#39;orange&#39;]
  bar_colors = [&#39;tab:red&#39;, &#39;tab:blue&#39;, &#39;tab:red&#39;, &#39;tab:orange&#39;]

  ax.bar(fruits, counts, label=bar_labels, color=bar_colors)

  ax.set_ylabel(&#39;fruit supply&#39;)
  ax.set_title(&#39;Fruit supply by kind and color&#39;)
  ax.legend(title=&#39;Fruit color&#39;)

  plt.show()</code></pre>
</li>
<li><p><em>👉 결과*</em>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/7b5dd168-9faa-44c5-9693-cd009c79e156/image.png" alt="image"></p>
</li>
</ul>
<pre><code class="language-python">    import matplotlib.pyplot as plt

    data = {&#39;apple&#39;: 10, &#39;orange&#39;: 15, &#39;lemon&#39;: 5, &#39;lime&#39;: 20}
    names = list(data.keys())
    values = list(data.values())

    fig, axs = plt.subplots(1, 3, figsize=(9, 3), sharey=True)
    axs[0].bar(names, values)
    axs[1].scatter(names, values)
    axs[2].plot(names, values)
    fig.suptitle(&#39;Categorical Plotting&#39;)</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/cd09bef8-27f7-494a-8f4f-8f1771343be0/image.png" alt="image"></p>
<pre><code class="language-python">    import numpy as np
    import matplotlib.pyplot as plt

    # Fixing random state for reproducibility
    np.random.seed(19680801)

    dt = 0.01
    t = np.arange(0, 30, dt)
    nse1 = np.random.randn(len(t))                 # white noise 1
    nse2 = np.random.randn(len(t))                 # white noise 2

    # Two signals with a coherent part at 10 Hz and a random part
    s1 = np.sin(2 * np.pi * 10 * t) + nse1
    s2 = np.sin(2 * np.pi * 10 * t) + nse2

    fig, axs = plt.subplots(2, 1)
    axs[0].plot(t, s1, t, s2)
    axs[0].set_xlim(0, 2)
    axs[0].set_xlabel(&#39;Time&#39;)
    axs[0].set_ylabel(&#39;s1 and s2&#39;)
    axs[0].grid(True)

    cxy, f = axs[1].cohere(s1, s2, 256, 1. / dt)
    axs[1].set_ylabel(&#39;Coherence&#39;)

    fig.tight_layout()
    plt.show()</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/6e8b312f-1aed-4484-82dc-bb9a1db78405/image.png" alt="image"></p>
<pre><code class="language-python">    import matplotlib.pyplot as plt
    import pandas as pd

    ts = pd.Series(np.random.randn(1000), index=pd.date_range(&quot;1/1/2000&quot;, periods=1000))
    ts = ts.cumsum()
    ts.plot()</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/0684ae77-192b-4c62-bf38-baf72b79870c/image.png" alt="image"></p>
<pre><code class="language-python">    df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list(&quot;ABCD&quot;))
    df = df.cumsum()
    plt.figure()
    df.plot()</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/f3ba7c0b-bb36-470c-bc39-d5cc020bcd01/image.png" alt="image"></p>
<pre><code class="language-python">    df2 = pd.DataFrame(np.random.rand(10, 4), columns=[&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;])
    df2.plot.bar()</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/8ade06b9-7102-463c-93ea-7d4f1f27e427/image.png" alt="image"></p>
<pre><code class="language-python">    df2.plot.bar(stacked=True)</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/e1e82343-b5ab-445a-b8f5-c03c6fab6d8f/image.png" alt="image"></p>
<pre><code class="language-python">    df2.plot.barh(stacked=True)</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/3431d37c-e07d-4b73-9184-1e6ff61751b7/image.png" alt="image"></p>
<pre><code class="language-python">    df4 = pd.DataFrame(
    {
        &quot;a&quot;: np.random.randn(1000) + 1,
        &quot;b&quot;: np.random.randn(1000),
        &quot;c&quot;: np.random.randn(1000) - 1,
    },
    columns=[&quot;a&quot;, &quot;b&quot;, &quot;c&quot;],
)
    plt.figure()
    df4.plot.hist(alpha=0.5)</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/26e12079-c0c5-4aee-aff1-2926eea04402/image.png" alt="image"></p>
<pre><code class="language-python">    df = pd.DataFrame(np.random.rand(10, 5), columns=[&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;, &quot;E&quot;])
    df.plot.box()</code></pre>
<p><strong>👉 결과</strong>
<img src="https://velog.velcdn.com/images/__zeroiszero/post/6cfcbc14-059b-46b7-909d-6c2e35272ccf/image.png" alt="image"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Py-Numpy]]></title>
            <link>https://velog.io/@__zeroiszero/Py-Numpy</link>
            <guid>https://velog.io/@__zeroiszero/Py-Numpy</guid>
            <pubDate>Sun, 24 Sep 2023 16:44:38 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="1-numpy-다루기">1 Numpy 다루기</h1>
<hr>
<ul>
<li>배열(array)는 벡터(1D) 또는 행렬(2D이상)<ul>
<li>List와 유사하나 List는 이종의 자료형이 가능하고, 수치 연산의 형태가 상이함</li>
<li>원소의 개수를 바꿀 수 없음</li>
</ul>
</li>
<li>Numpy는 배열 연산과 관련된 편리한 기능을 제공<ul>
<li>적은 메모리 사용으로 연산속도가 빠름</li>
<li>벡터화 연산, 배열 인덱싱들을 통한 질의가 가능함</li>
</ul>
</li>
<li>파이썬에서는 기본적으로 배열 자료형을 제공하지 않기 때문에 배열을 다루기 위해서는 numpy를 이용함<h2 id="11-배열array-만들기">1.1 배열(Array) 만들기</h2>
<h3 id="값을-이용하여-배열-만들기">값을 이용하여 배열 만들기</h3>
</li>
<li>배열을 생성하고 유형 확인하기<pre><code class="language-python">import numpy as np
</code></pre>
</li>
</ul>
<p>a = np.array([[1, 2, 3], [4, 5, 6]]) # 입력한 데이터 유형에 따라 자동으로 dtype이 설정됨
print(a)
print(a.shape)
print(a.dtype)</p>
<pre><code>    결과
    [[1 2 3]
     [4 5 6]]
    (2, 3)
    int32
``` python
    a = np.array([[1.0, 2, 3], [4, 5, 6]]) # 입력한 데이터 유형에 따라 자동으로 dtype이 설정됨
    print(a)
    print(a.shape)
    print(a.dtype)</code></pre><pre><code>    결과
    [[1. 2. 3.]
     [4. 5. 6.]]
    (2, 3)
    float64</code></pre><ul>
<li>배열의 유형을 변경하기<pre><code class="language-python">  a = a.astype(np.int32) # dtype을 변경할 수 있음
  print(a)
  print(a.dtype)</code></pre>
<pre><code>  결과
  [[1 2 3]
   [4 5 6]]
  int32</code></pre></li>
<li>유형을 지정하여 생성하기<pre><code class="language-python">  a = np.array([[1.2, 2.5, 3.7], [4, 5, 6]], dtype=np.int32) # 데이터는 반올림하지 않고 절삭함
  print(a)
  print(a.shape)
  print(a.dtype)</code></pre>
<pre><code>  결과
  [[1 2 3]
   [4 5 6]]
  (2, 3)
  int32</code></pre></li>
<li>배열의 크기를 확인하기<pre><code class="language-python">  print(a.shape) # (행의 크기, 열의 크기)를 튜플로 반환
  print(a.size) # 데이터의 갯수를 값으로 반환
  print(len(a)) # inatance(행)의 갯수를 값으로 반환</code></pre>
<pre><code>  결과
  (2, 3)
  6
  2</code></pre><h3 id="등간격의-배열-만들기">등간격의 배열 만들기</h3>
</li>
<li>arrange(처음값, 마지막 값, 간격) : 처음값부터 (마지막 값-1)까지 간격(default=1)으로 정수 생성<pre><code class="language-python">   np.arange(0,10,2) # 0부터 10까지 2씩 증가하는 1차원 배열 생성</code></pre>
<pre><code>  결과
  array([0, 2, 4, 6, 8])</code></pre><pre><code class="language-python">  np.arange(0,10)</code></pre>
<pre><code>  결과
  array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])</code></pre><pre><code class="language-python">  np.arange(0,10.8,0.7)</code></pre>
<pre><code>  결과
  array([ 0. ,  0.7,  1.4,  2.1,  2.8,  3.5,  4.2,  4.9,  5.6,  6.3,  7. ,
  7.7,  8.4,  9.1,  9.8, 10.5])</code></pre><pre><code class="language-python">  np.arange(10,0,-1)</code></pre>
<pre><code>  결과
  array([10,  9,  8,  7,  6,  5,  4,  3,  2,  1])</code></pre><pre><code class="language-python">  np.arange(10) # 시작값 디폴트 0, 증가값 디폴트 1</code></pre>
<pre><code>  결과
  array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])</code></pre></li>
<li>linspace(시작값, 마지막값, 갯수) : 시작값(포함)부터 마지막값(포함)까지 등간격으로 갯수(default=50)만큼 값 생성<pre><code class="language-python">  np.linspace(0,10,10)</code></pre>
<pre><code>  결과
  array([ 0.        ,  1.11111111,  2.22222222,  3.33333333,  4.44444444,
  5.55555556,  6.66666667,  7.77777778,  8.88888889, 10.        ])</code></pre><pre><code class="language-python">  np.linspace(5,-5,9)</code></pre>
<pre><code>  결과
  array([ 5.  ,  3.75,  2.5 ,  1.25,  0.  , -1.25, -2.5 , -3.75, -5.  ])</code></pre><h3 id="empty-zeros-ones-배열-만들기">empty, zeros, ones 배열 만들기</h3>
</li>
<li>empty(빈배열) : 현재 메모리에 있는 값 그대로 빈 공간만 생성<pre><code class="language-python">  e = np.empty([3,3])
  print(e)</code></pre>
<pre><code>  결과
  [[ 5.    3.75  2.5 ]
   [ 1.25  0.   -1.25]
   [-2.5  -3.75 -5.  ]]</code></pre></li>
<li>zeros(영배열) : 모든 원소가 0인 배열 생성<pre><code class="language-python">  z = np.zeros([3,3], dtype=np.int32)  # dtype의 디폴트는 float64
  print(z)</code></pre>
<pre><code>  결과
  [[0 0 0]
   [0 0 0]
   [0 0 0]]</code></pre></li>
<li>ones(1배열) : 모든 원소가 1인 배열 생성<pre><code class="language-python">  o = np.ones([3,3])
  print(o)</code></pre>
<pre><code>  결과
  [[1. 1. 1.]
   [1. 1. 1.]
   [1. 1. 1.]]</code></pre><h3 id="랜덤-배열-만들기">랜덤 배열 만들기</h3>
</li>
<li>seed는 랜덤값을 생성할 때, 시작점을 의미</li>
<li>seed를 지정해 주지 않으면, 매번 실행할 때마다 값이 변경됨<ul>
<li>테스트할 때마다 값이 변경되므로 비교 평가가 불가함</li>
<li>따라서 seed를 지정해서 실험을 하고, 실제로 실행할 경우에는 이를 해제함<pre><code class="language-python">np.random.seed(0)  </code></pre>
</li>
</ul>
</li>
<li>random.randint(): 지정한 값 사이의 정수를 랜덤으로 생성<pre><code class="language-python">  np.random.randint(10) # 0에서 (10-1)사이의 랜덤 정수 생성</code></pre>
<pre><code>  결과
  7</code></pre><pre><code class="language-python">  np.random.randint(0,10,15) #0에서 (10-1)사이의 랜덤 정수 15개 생성</code></pre>
<pre><code>  결과
  array([8, 0, 8, 5, 9, 3, 7, 1, 8, 2, 6, 1, 6, 2, 7])</code></pre></li>
<li>random.rand(): 0 이상 1 미만의 임의의 값을 생성<pre><code class="language-python">  np.random.rand(10) # 10개의 랜덤값을 가진 어레이 생성</code></pre>
<pre><code>  결과
  array([0.35433176, 0.75517944, 0.15649   , 0.05942972, 0.22688245,
 0.72483354, 0.64809509, 0.77758691, 0.34826044, 0.54150907])</code></pre><pre><code class="language-python">  np.random.rand(2,5) # 랜덤 행렬 생성</code></pre>
<pre><code>  결과
  array([[0.08217991, 0.29054503, 0.45048709, 0.27329039, 0.37529013],
 [0.53922297, 0.40800884, 0.26610577, 0.51821411, 0.95936814]])</code></pre></li>
</ul>
<hr>
<h2 id="12-실습">1.2 실습</h2>
<pre><code class="language-python">    a = np.array([[1,2,3],[4,5,6]]) # 2차원 배열 생성
    print(a)  </code></pre>
<pre><code>    결과
    [[1 2 3]
     [4 5 6]]</code></pre><pre><code class="language-python">     np.arange(10).reshape(2,5) # 1부터 10까지 1차원 배열 생성 후 2 by 5로 변환</code></pre>
<pre><code>    결과
    array([[0, 1, 2, 3, 4],
              [5, 6, 7, 8, 9]])</code></pre><pre><code class="language-python">    np.arange(2,3,0.1)  # 2이상 3미만 0.1간격 배열생성</code></pre>
<pre><code>    결과
    array([2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9])</code></pre><pre><code class="language-python">    np.linspace(1.0,4.0,6) # 1.0이상 4.0이하 등간격 6원소 배열생성</code></pre>
<pre><code>    결과
    array([1. , 1.6, 2.2, 2.8, 3.4, 4. ])</code></pre><pre><code class="language-python">    np.zeros((2,2),int) # 2 by 2 정수 영행렬 생성</code></pre>
<pre><code>    결과
    array([[0, 0],
              [0, 0]])</code></pre><pre><code class="language-python">    np.zeros((2,2),float) # 2by2 float 0행렬</code></pre>
<pre><code>    결과
    array([[0., 0.],
           [0., 0.]])</code></pre><pre><code class="language-python">    np.ones((2,2)) # 2by2 float 1행렬</code></pre>
<pre><code>    결과
    array([[1., 1.],
           [1., 1.]])</code></pre><pre><code class="language-python">    np.full((2,2), 7) # 2by2 행렬을 7로 채움</code></pre>
<pre><code>    결과
    array([[7, 7],
           [7, 7]])</code></pre><pre><code class="language-python">    np.eye(2) # 2by2 eigen 행렬</code></pre>
<pre><code>    결과
    array([[1., 0.],
           [0., 1.]])</code></pre><pre><code class="language-python">    np.random.random((2,2)) # 2by2 random 생성</code></pre>
<pre><code>    결과
    array([[0.42961291, 0.6709883 ],
           [0.71483539, 0.01489149]])</code></pre><hr>
<h2 id="13-배열-다루기">1.3 배열 다루기</h2>
<h3 id="배열-모양-바꾸기">배열 모양 바꾸기</h3>
<ul>
<li>배열 풀기 -&gt; 열벡터로 변환<pre><code class="language-python">  a = np.array([[1,2,3],[4,5,6]]) # 2차원 배열 생성
  print(f&#39;{a = }&#39;)
  print(f&#39;{a.reshape(-1) = }&#39;) # 1차원 배열로 변환
  print(f&#39;{a = }&#39;) # 원본은 변하지 않음</code></pre>
<pre><code>  결과
  a = array([[1, 2, 3],
             [4, 5, 6]])
  a.reshape(-1) = array([1, 2, 3, 4, 5, 6])
  a = array([[1, 2, 3],
             [4, 5, 6]])</code></pre></li>
<li>배열은 변경 후 별도의 저장을 하지 않으면, 변경되지 않음<pre><code class="language-python">  a_61 = a.reshape(-1) 
  print(f&#39;{a_61 = }&#39;)
  print(f&#39;{a_61.shape = }&#39;)
  print(f&#39;{a = }&#39;) # 원본은 변하지 않음</code></pre>
<pre><code>  결과
  a_61 = array([1, 2, 3, 4, 5, 6])
  a_61.shape = (6,)
  a = array([[1, 2, 3],
                [4, 5, 6]])</code></pre></li>
<li>배열의 모양을 바꾸기 -&gt; 열벡터로 변환 후 재배정함<pre><code class="language-python">  a_32 = a.reshape(3,2)
  print(a_32)</code></pre>
<pre><code>  결과
  [[1 2]
   [3 4]
   [5 6]]</code></pre></li>
</ul>
<hr>
<h1 id="2-인덱싱과-슬라이싱">2 인덱싱과 슬라이싱</h1>
<hr>
<h2 id="21-인덱싱indexing">2.1 인덱싱(Indexing)</h2>
<ul>
<li>배열에서 원소를 찾는 것<ul>
<li>인덱스는 0부터 시작<ul>
<li>맨 뒤는 -1<pre><code class="language-python">a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])</code></pre>
<pre><code class="language-python">print(&#39;a = \n&#39;, a)
print(f&#39;{a[2,2] = }&#39;) # 인덱스 2행, 인덱스 2열 원소
print(f&#39;{a[(2,2)] = }&#39;) # 인덱스 2행, 인덱스 2열 원소
print(f&#39;{a[1,2] = }&#39;) # 인덱스 1행, 인덱스 2열 원소
print(f&#39;{a[-1,-1] = }&#39;) # 마지막행, 마지막열 원소</code></pre>
결과
a = 
 [[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
a[2,2] = 11
a[(2,2)] = 11
a[1,2] = 7
a[-1,-1] = 12</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="22-슬라이싱slicing">2.2 슬라이싱(Slicing)</h2>
<ul>
<li>배열에서 부분집합을 가져오는 것<ul>
<li>i:j -&gt; i에서 (j-1)까지<pre><code class="language-python">print(&#39;a = \n&#39;, a)
print(f&#39;{a[1,0:1] = }&#39;) # 슬라이싱은 부분을 취하는 것이므로 원본과 같은 어레이가 반환됨
print(f&#39;{a[1,:] = }&#39;) # 인덱스 1행, 모든열
print(f&#39;{a[:,1] = }&#39;) # 모든행, 인덱스 1열</code></pre>
  결과
  a = 
   [[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]]
  a[1,0:1] = array([5])
  a[1,:] = array([5, 6, 7, 8])
  a[:,1] = array([ 2,  6, 10])<pre><code class="language-python">print(f&#39;{a[:2,:] = }&#39;) # 인덱스 0부터 인덱스 2미만행, 모든열</code></pre>
  결과
  a[:2,:] = array([[1, 2, 3, 4],<pre><code>                  [5, 6, 7, 8]])</code></pre><pre><code class="language-python">print(f&#39;{a[:2,1:3] = }&#39;) # 인덱스 0부터 인덱스 2미만행,  인덱스 1부터 3미만 열
print(f&#39;{a[:,0:3:2] = }&#39;) # 모든행, 0부터 3미만 2간격 모든열
print(f&#39;{a[:,-1:-4:-2]= }&#39;) # 모든행, 마지막열부터 -4미만 -2간격 모든열</code></pre>
  결과
  a[:2,1:3] = array([[2, 3],<pre><code>                    [6, 7]])</code></pre>  a[:,0:3:2] = array([[ 1,  3],<pre><code>                  [ 5,  7],
                  [ 9, 11]])</code></pre>  a[:,-1:-4:-2]= array([[ 4,  2],<pre><code>                       [ 8,  6],
                       [12, 10]])</code></pre><pre><code class="language-python">print(f&#39;{a[:,[3,0,2,1]] = }&#39;) # 모든행, 3,0,2,1열 순서로
print(f&#39;{a[[0,1,2],[0,1,2]] = }&#39;) # [0,0],[1,1],[1,2] 원소</code></pre>
  결과
  a[:,[3,0,2,1]] = array([[ 4,  1,  3,  2],<pre><code>     [ 8,  5,  7,  6],
     [12,  9, 11, 10]])</code></pre>  a[[0,1,2],[0,1,2]] = array([ 1,  6, 11])<pre><code class="language-python">print(f&#39;{a = }&#39;)
a[0,0] = 100  # 인덱스 0행, 인덱스 0열 원소를 100으로 변경
print(f&#39;{a = }&#39;)</code></pre>
  결과
  a = array([[ 1,  2,  3,  4],<pre><code>         [ 5,  6,  7,  8],
         [ 9, 10, 11, 12]])</code></pre>  a = array([[100,   2,   3,   4],<pre><code>         [  5,   6,   7,   8],
         [  9,  10,  11,  12]])</code></pre></li>
</ul>
</li>
</ul>
<hr>
<h1 id="3-얕은-복사shallow-copy와-깊은-복사deep-copy">3 얕은 복사(shallow copy)와 깊은 복사(deep copy)</h1>
<hr>
<h2 id="31-mutable과-immutable">3.1 mutable과 immutable</h2>
<ul>
<li>mutable : 배열에서 원소의 수정 가능한 자료형<ul>
<li>리스트(List), 집합(Set), 딕셔너리(Dictionary)</li>
</ul>
</li>
<li>immutable : 배열에서 원소의 수정이 불가능한 자료형<ul>
<li>문자열(String), 튜플(Tuple), Boolean, Number<h3 id="mutable-동작원리">mutable 동작원리</h3>
<pre><code class="language-python">ls = [1,2,3] # 리스트 생성
arr = np.array(ls)  # 리스트로 배열 생성
print(f&#39;{ls = }&#39;)
print(f&#39;{arr = }&#39;)
print(f&#39;{id(ls) = }&#39;) # 리스트의 주소 확인
print(f&#39;{id(arr) = }&#39;) # 배열의 주소 확인, ls와 arr은 완전히 다른 객체</code></pre>
  결과
  ls = [1, 2, 3]
  arr = array([1, 2, 3])
  id(ls) = 2448791471360
  id(arr) = 2448738516496</li>
</ul>
</li>
<li>변수의 값을 변경하더라도 변수의 주소는 동일하고 배열의 값만 바뀜<pre><code class="language-python">  ls[0] = 10
  arr[0] = 100
  print(f&#39;{ls = }&#39;)
  print(f&#39;{arr = }&#39;)
  print(f&#39;{id(ls) = }&#39;) # 리스트의 주소 확인
  print(f&#39;{id(arr) = }&#39;) # 배열의 주소 확인</code></pre>
<pre><code>  결과
  ls = [10, 2, 3]
  arr = array([100,   2,   3])
  id(ls) = 2448791471360
  id(arr) = 2448738516496</code></pre></li>
<li>다른 배열을 할당하면, 주소가 바뀜<pre><code class="language-python">  ls = [4,5,6] # 리스트에 다른 값 배정
  print(f&#39;{ls = }&#39;)
  print(f&#39;{arr = }&#39;)
  print(f&#39;{id(ls) = }&#39;) # 리스트의 주소 확인
  print(f&#39;{id(arr) = }&#39;) # 배열의 주소 확인</code></pre>
<pre><code>  결과
  ls = [4, 5, 6]
  arr = array([100,   2,   3])
  id(ls) = 2448791484224
  id(arr) = 2448738516496</code></pre><pre><code class="language-python">  arr = np.array([4,5,6])  # 다른 배열 배정
  print(f&#39;{ls = }&#39;)
  print(f&#39;{arr = }&#39;)
  print(f&#39;{id(ls) = }&#39;) # 리스트의 주소 확인
  print(f&#39;{id(arr) = }&#39;) # 배열의 주소 확인</code></pre>
<pre><code>  결과
  ls = [4, 5, 6]
  arr = array([4, 5, 6])
  id(ls) = 2448791484224
  id(arr) = 2448791602448</code></pre></li>
</ul>
<hr>
<h2 id="32-얕은-복사shallow-copy">3.2 얕은 복사(shallow copy)</h2>
<ul>
<li><p>다른 변수로 복사하면 주소는 동일함</p>
<pre><code class="language-python">  arr = np.array([1,2,3])  # 배열 배정
  print(f&#39;{arr = }&#39;)
  print(f&#39;{id(arr) = }&#39;) # 배열의 주소 확인

  arr_shallow_copied = arr

  print(f&#39;{arr_shallow_copied = }&#39;)
  print(f&#39;{id(arr_shallow_copied) = }&#39;) # 배열의 주소 확인, arr과 동일 주소</code></pre>
<pre><code>  결과
  arr = array([1, 2, 3])
  id(arr) = 2448791602256
  arr_shallow_copied = array([1, 2, 3])
  id(arr_shallow_copied) = 2448791602256</code></pre></li>
<li><p>두 변수는 동일한 주소를 가지고 있으므로, 하나의 값을 변경하면 다른 하나도 변경됨</p>
<pre><code class="language-python">  arr[0] = 500
  arr_shallow_copied[2] = 1000

  print(f&#39;{arr = }&#39;) # 원본 복사본 모두 변경됨
  print(f&#39;{arr_shallow_copied = }&#39;) # 원본 복사본 모두 변경됨</code></pre>
<pre><code>  결과
  arr = array([ 500,    2, 1000])
  arr_shallow_copied = array([ 500,    2, 1000])</code></pre></li>
</ul>
<hr>
<h2 id="33-깊은-복사deep-copy">3.3 깊은 복사(deep copy)</h2>
<ul>
<li><p>이러한 현상을 해소하기 위해서는 deep copy를 해야함</p>
<pre><code class="language-python">  arr = np.array([1,2,3])  # 배열 배정
  print(f&#39;{arr = }&#39;)
  print(f&#39;{id(arr) = }&#39;) # 배열의 주소 확인

  import copy
  arr_deep_copied = copy.deepcopy(arr)
  arr_copied = arr.copy()  # copy() 메소드를 사용하여 복사, 파이썬 내장함수, 1차원 배열만 가능

  print(f&#39;{arr_deep_copied = }&#39;)
  print(f&#39;{id(arr_deep_copied) = }&#39;) # 배열의 주소 확인, arr과 다른 주소

  print(f&#39;{arr_copied = }&#39;)
  print(f&#39;{id(arr_copied) = }&#39;) # 배열의 주소 확인, arr과 다른 주소</code></pre>
<pre><code>  결과
  arr = array([1, 2, 3])
  id(arr) = 2448791602832
  arr_deep_copied = array([1, 2, 3])
  id(arr_deep_copied) = 2448791602448
  arr_copied = array([1, 2, 3])
  id(arr_copied) = 2448791603024</code></pre><pre><code class="language-python">  arr[0] = 500
  arr_deep_copied[2] = 1000

  print(f&#39;{arr = }&#39;) # 각각의 값만 변경됨
  print(f&#39;{arr_deep_copied = }&#39;) # 각각의 값만 변경됨</code></pre>
<pre><code>  결과
  arr = array([500,   2,   3])
  arr_deep_copied = array([   1,    2, 1000])</code></pre></li>
</ul>
<hr>
<h1 id="4-배열-연산하기">4 배열 연산하기</h1>
<hr>
<h2 id="41-사칙연산">4.1 사칙연산</h2>
<pre><code class="language-python">    a = np.arange(9).reshape(3, 3)
    a</code></pre>
<pre><code>    결과
    array([[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]])</code></pre><ul>
<li>배열과 수치의 연산<pre><code class="language-python">  a+3</code></pre>
<pre><code>  결과
  array([[ 3,  4,  5],
         [ 6,  7,  8],
         [ 9, 10, 11]])</code></pre><pre><code class="language-python">  a+3.0</code></pre>
<pre><code>  결과
  array([[ 3.,  4.,  5.],
         [ 6.,  7.,  8.],
         [ 9., 10., 11.]])</code></pre><pre><code class="language-python">  a*3</code></pre>
<pre><code>  결과
  array([[ 0,  3,  6],
         [ 9, 12, 15],
         [18, 21, 24]])</code></pre><pre><code class="language-python">  a/3</code></pre>
<pre><code>  결과
  array([[0.        , 0.33333333, 0.66666667],
         [1.        , 1.33333333, 1.66666667],
         [2.        , 2.33333333, 2.66666667]])</code></pre><pre><code class="language-python">  a**2</code></pre>
<pre><code>  결과
  array([[ 0,  1,  4],
         [ 9, 16, 25],
         [36, 49, 64]])</code></pre></li>
<li>배열과 벡터의 연산(브로드캐스팅 : shape가 다른 배열 간에도 자동반복하여 연산이 가능하게 하는 것)<pre><code class="language-python">  a = np.arange(9).reshape(3, 3)
  b = np.array([100, 200, 300])
  print(f&#39;{a = }&#39;)
  print(f&#39;{b = }&#39;)</code></pre>
<pre><code>  결과
  a = array([[0, 1, 2],
             [3, 4, 5],
             [6, 7, 8]])
  b = array([100, 200, 300])</code></pre><pre><code class="language-python">  a+b  # 각 행마다 벡터를 원소끼리 더함</code></pre>
<pre><code>  결과
  array([[100, 201, 302],
         [103, 204, 305],
         [106, 207, 308]])</code></pre><pre><code class="language-python">  a*b  # 각 행마다 벡터를 원소끼리 곱함</code></pre>
<pre><code>  결과
  array([[   0,  200,  600],
         [ 300,  800, 1500],
         [ 600, 1400, 2400]])</code></pre></li>
<li>배열과 배열의 연산<pre><code class="language-python">  a = np.arange(9).reshape(3, 3)
  print(f&#39;{a = }&#39;)
  c = np.arange(0,90,10).reshape(3, 3)
  print(f&#39;{c = }&#39;)</code></pre>
<pre><code>  결과
  a = array([[0, 1, 2],
             [3, 4, 5],
             [6, 7, 8]])
  c = array([[ 0, 10, 20],
             [30, 40, 50],
             [60, 70, 80]])</code></pre><pre><code class="language-python">  a+c  # 동일 위치의 원소끼리 더함</code></pre>
<pre><code>  결과
  array([[ 0, 11, 22],
         [33, 44, 55],
         [66, 77, 88]])</code></pre><pre><code class="language-python">  a*c  # 동일 위치의 원소끼리 곱함</code></pre>
<pre><code>  결과
  array([[  0,  10,  40],
         [ 90, 160, 250],
         [360, 490, 640]])</code></pre></li>
</ul>
<hr>
<h2 id="42-메서드를-이용한-연산">4.2 메서드를 이용한 연산</h2>
<ul>
<li>배열은 일종의 클래스 오브젝트로서 자체 변수와 메서드를 가지고 있음<pre><code class="language-python">  a = np.arange(9).reshape(3, 3)
  a</code></pre>
<pre><code>  결과
  array([[0, 1, 2],
         [3, 4, 5],
         [6, 7, 8]])</code></pre><pre><code class="language-python">  a.sum() # 모든 원소의 합</code></pre>
<pre><code>  결과
  36</code></pre><pre><code class="language-python">  a.sum(axis=0)  # 열별 합</code></pre>
<pre><code>  결과
  array([ 9, 12, 15])</code></pre><pre><code class="language-python">  a.sum(axis=1)  # 행별 합</code></pre>
<pre><code>  결과
  array([ 3, 12, 21])</code></pre><pre><code class="language-python">   print(f&#39;{a.min()= }, {a.max()= }, {a.mean()= }, {a.std()= }, {a.var()= }&#39;)</code></pre>
<pre><code>  결과
  a.min()= 0, a.max()= 8, a.mean()= 4.0, a.std()= 2.581988897471611, a.var()= 6.666666666666667</code></pre></li>
</ul>
<hr>
<h2 id="43-numpy-함수를-이용한-연산">4.3 numpy 함수를 이용한 연산</h2>
<pre><code class="language-python">    print(&#39;a = \n&#39;, a)
    print(&#39;c = \n&#39;, c)</code></pre>
<pre><code>    결과
    a = 
     [[0 1 2]
     [3 4 5]
     [6 7 8]]
    c = 
     [[ 0 10 20]
     [30 40 50]
     [60 70 80]]</code></pre><pre><code class="language-python">    np.sqrt(a) # 원소별 연산</code></pre>
<pre><code>    결과
    array([[0.        , 1.        , 1.41421356],
           [1.73205081, 2.        , 2.23606798],
           [2.44948974, 2.64575131, 2.82842712]])</code></pre><pre><code class="language-python">    np.dot(a, c.transpose()) # 행렬 연산</code></pre>
<pre><code>    결과
    array([[  50,  140,  230],
           [ 140,  500,  860],
           [ 230,  860, 1490]])</code></pre><pre><code class="language-python">    np.dot(a, c.T) # 행렬 연산</code></pre>
<pre><code>    결과
    array([[  50,  140,  230],
           [ 140,  500,  860],
           [ 230,  860, 1490]])</code></pre><h2 id="43-1-기타-유용한-배열-연산">4.3-1 기타 유용한 배열 연산</h2>
<h3 id="찾기-및-추출">찾기 및 추출</h3>
<pre><code class="language-python">    a = np.arange(9).reshape(3, 3)
    print(&#39;a = \n&#39;, a)</code></pre>
<pre><code>    결과
    a = 
       [[0 1 2]
       [3 4 5]
       [6 7 8]]</code></pre><pre><code class="language-python">    a&gt;5 # a의 원소 중 5보다 큰 것</code></pre>
<pre><code>    결과
    array([[False, False, False],
           [False, False, False],
           [ True,  True,  True]])</code></pre><pre><code class="language-python">    a[a&gt;5] # a의 원소 중 5보다 큰 것만 뽑아냄</code></pre>
<pre><code>    결과
    array([6, 7, 8])</code></pre><pre><code class="language-python">    (a&gt;3)&amp;(a&lt;=7) # a의 원소 중 3보다 크고 7보다 작거나 같은 것</code></pre>
<pre><code>    결과
    array([[False, False, False],
           [False,  True,  True],
           [ True,  True, False]])</code></pre><pre><code class="language-python">    a[(a&gt;3)&amp;(a&lt;=7)] # a의 원소 중 3보다 크고 7보다 작거나 같은 것만 뽑아냄</code></pre>
<pre><code>    결과
    array([4, 5, 6, 7])</code></pre><h2 id="44-기타-함수">4.4 기타 함수</h2>
<pre><code class="language-python">    np.empty_like(a)   # a와 동일한 shape를 가지며 비어있는 행렬 생성</code></pre>
<pre><code>    결과
    array([[        0,         1,         0],
           [  5570652,      1544,         0],
           [      768,       181, 572533794]])</code></pre><pre><code class="language-python">    np.tile(a, (3, 2)) # a 를 3행 2열로 쌓음</code></pre>
<pre><code>    결과
    array([[0, 1, 2, 0, 1, 2],
           [3, 4, 5, 3, 4, 5],
           [6, 7, 8, 6, 7, 8],
           [0, 1, 2, 0, 1, 2],
           [3, 4, 5, 3, 4, 5],
           [6, 7, 8, 6, 7, 8],
           [0, 1, 2, 0, 1, 2],
           [3, 4, 5, 3, 4, 5],
           [6, 7, 8, 6, 7, 8]])</code></pre><pre><code class="language-python">    a = np.arange(6).reshape(2, 3)
    b = np.arange(0,60,10).reshape(2, 3)
    print(&#39;a = \n&#39;, a)
    print(&#39;b = \n&#39;, b)</code></pre>
<pre><code>    결과
    a = 
     [[0 1 2]
     [3 4 5]]
    b = 
     [[ 0 10 20]
     [30 40 50]]</code></pre><pre><code class="language-python">    np.vstack((a,b)) # 수직으로 쌓음</code></pre>
<pre><code>    결과
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 0, 10, 20],
           [30, 40, 50]])</code></pre><pre><code class="language-python">    np.hstack((a,b)) # 수평으로 쌓음</code></pre>
<pre><code>    결과
    array([[ 0,  1,  2,  0, 10, 20],
           [ 3,  4,  5, 30, 40, 50]])</code></pre><pre><code class="language-python">    np.concatenate((a,b), axis=0) # 수직으로 쌓음</code></pre>
<pre><code>    결과
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 0, 10, 20],
           [30, 40, 50]])</code></pre><pre><code class="language-python">    np.concatenate((a,b), axis=1) # 수평으로 쌓음</code></pre>
<pre><code>    결과
    array([[ 0,  1,  2,  0, 10, 20],
              [ 3,  4,  5, 30, 40, 50]])</code></pre><pre><code class="language-python">    np.concatenate((a,b), axis=None) # 1차원 배열로 쌓음</code></pre>
<pre><code>    결과
    array([ 0,  1,  2,  3,  4,  5,  0, 10, 20, 30, 40, 50])</code></pre><pre><code class="language-python">    np.r_[a,b] # 수직으로 쌓음</code></pre>
<pre><code>    결과
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 0, 10, 20],
           [30, 40, 50]])</code></pre><pre><code class="language-python">    np.c_[a,b] # 수평으로 쌓음    </code></pre>
<pre><code>    결과
    array([[ 0,  1,  2,  0, 10, 20],
              [ 3,  4,  5, 30, 40, 50]])</code></pre><pre><code class="language-python">    np.ravel(a, order=&#39;C&#39;) # 1차원 배열로 변환 (C: row 우선 디폴트, F: column 우선)</code></pre>
<pre><code>    결과
    array([0, 1, 2, 3, 4, 5])</code></pre><pre><code class="language-python">    np.ravel(a, order=&#39;F&#39;) # 1차원 배열로 변환 (C: row 우선 디폴트, F: column 우선)</code></pre>
<pre><code>    결과
    array([0, 3, 1, 4, 2, 5])</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Py-파이썬 기초]]></title>
            <link>https://velog.io/@__zeroiszero/1-%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@__zeroiszero/1-%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Sun, 24 Sep 2023 14:59:19 GMT</pubDate>
            <description><![CDATA[<hr>
<h1 id="1-파이썬의-기본-자료구조">1 파이썬의 기본 자료구조</h1>
<hr>
<h2 id="11-데이터의-유형type">1.1 데이터의 유형(type)</h2>
<ul>
<li>수치형(Number) : 수치형 데이터, int, float, complex<blockquote>
<p> 123, 123.45, (123+45j)</p>
</blockquote>
</li>
<li>문자열(String) : 문자 또는 문자의 집합<blockquote>
<p>&#39;abc&#39;, &quot;abc&quot;</p>
</blockquote>
</li>
<li>리스트(List) : 다양한 타입의 데이터 목록<blockquote>
<p>[&#39;abc&#39;, 123]</p>
</blockquote>
</li>
<li>튜플(Tuple) : 다양한 타입의 데이터 목록, 리스트와 유사하나 원소의 변경이 불가<blockquote>
<p>(&#39;abc&#39;, 123)</p>
</blockquote>
</li>
<li>딕셔너리(Dictionary) : key:value 조합의 데이터<blockquote>
<p>{&#39;name&#39;:&#39;Youngeun&#39;, &#39;id&#39;:0831}</p>
</blockquote>
<h4 id="변수에-데이터를-배정assignment하고-유형-확인">변수에 데이터를 배정(assignment)하고 유형 확인</h4>
<pre><code class="language-python">x_value=12345
print(f&#39;{x_value=}\n{type(x_value)=}&#39;)</code></pre>
<strong>👉 결과</strong>
x_value = 12345
type(x_value) = &lt;class &#39;int&#39;&gt;</li>
</ul>
<pre><code class="language-python">x_str = &#39;abcde&#39; 
print(f&#39;{x_str = }\n{type(x_str) = }&#39;)</code></pre>
<p><strong>👉 결과</strong>
x_str = &#39;abcde&#39;
type(x_str) = &lt;class &#39;str&#39;&gt;</p>
<pre><code class="language-python">x_list = [x_str, x_value] 
print(f&#39;{x_list = }\n{type(x_list) = }&#39;)</code></pre>
<p><strong>👉 결과</strong>
x_list = [&#39;abcde&#39;, 12345]
type(x_list) = &lt;class &#39;list&#39;&gt;</p>
<pre><code class="language-python">x_tuple = (x_str, x_value)
print(f&#39;{x_tuple=}\n{type(x_tuple)=}&#39;)</code></pre>
<p><strong>👉 결과</strong>
x_tuple=(&#39;abcde&#39;, 12345)
type(x_tuple)=&lt;class &#39;tuple&#39;&gt;</p>
<pre><code class="language-python">x_dict = {&#39;name&#39;: &#39;Youngeun&#39;, &#39;id&#39;:83100}
print(f&#39;{x_dict=}\n{type(x_dict)=}&#39;)</code></pre>
<p><strong>👉 결과</strong>
x_dict={&#39;name&#39;: &#39;Youngeun&#39;, &#39;id&#39;: 83100}
type(x_dict) = &lt;class &#39;dict&#39;&gt;</p>
<hr>
<h2 id="12-mutable과-immutable">1.2 mutable과 immutable</h2>
<ul>
<li>mutable : 배열에서 원소의 수정 가능한 자료형<ul>
<li>리스트(List), 딕셔너리(Ditionary)</li>
</ul>
</li>
<li>immutable : 배열에서 원소의 수정이 불가능한 자료형<ul>
<li>문자열(String), 튜플(Tuple)<h3 id="mutable-리스트list">mutable: 리스트(List)</h3>
<pre><code class="language-python">print(f&#39;Before: {x_list = }&#39;)
x_list[1] = &#39;fghij&#39;  # 인덱스 1 원소를 &#39;fghij&#39;로 변경
print(f&#39;After : {x_list = }&#39;)</code></pre>
</li>
</ul>
</li>
<li><em>👉 결과*</em>
Before: x_list = [&#39;abcde&#39;, 12345]
After : x_list = [&#39;abcde&#39;, &#39;fghij&#39;]        </li>
</ul>
<h3 id="mutable-딕셔너리dictionary">mutable: 딕셔너리(Dictionary)</h3>
<pre><code class="language-python">print(f&#39;Before: {x_dict = }&#39;)
x_dict[&#39;name&#39;] = &#39;Gildong Hong&#39;  # 인덱스 1 원소를 &#39;fghij&#39;로 변경
print(f&#39;After : {x_dict = }&#39;)</code></pre>
<p><strong>👉 결과</strong><br>Before: x_dict = {&#39;name&#39;: &#39;Youngeun&#39;, &#39;id&#39;: 83100}
After : x_dict = {&#39;name&#39;: &#39;Gildong Hong&#39;, &#39;id&#39;: 83100}</p>
<h3 id="immutable-문자열---원소-바꾸기-불가능">immutable: 문자열 -&gt; 원소 바꾸기 불가능</h3>
<pre><code class="language-python">print(f&#39;Before: {x_str = }&#39;)
x_str[1] = &#39;2&#39;  # 인덱스 1 원소를 &#39;2&#39;로 변경
print(f&#39;After : {x_str = }&#39;)</code></pre>
<p><strong>👉 결과</strong>
Before: x_str = &#39;abcde&#39;</p>
<p>TypeError: &#39;str&#39; object does not support item assignment</p>
<h3 id="immutable-튜플---원소-바꾸기-불가능">immutable: 튜플 -&gt; 원소 바꾸기 불가능</h3>
<pre><code class="language-python">print(f&#39;Before: {x_tuple = }&#39;)
x_tuple[1] = &#39;fghij&#39;  # 인덱스 1 원소를 &#39;fghij&#39;로 변경
print(f&#39;After : {x_tuple = }&#39;)</code></pre>
<p><strong>👉 결과</strong>
Before: x_tuple = (&#39;abcde&#39;, 12345)</p>
<p>TypeError: &#39;tuple&#39; object does not support item assignment</p>
<hr>
<h1 id="2-인덱싱과-슬라이싱">2 인덱싱과 슬라이싱</h1>
<hr>
<h2 id="21-인덱싱indexing">2.1 인덱싱(Indexing)</h2>
<ul>
<li>배열에서 원소를 찾는 것<pre><code>- 인덱스는 0부터 시작하여 1씩 증가
- 맨뒤 원소의 인덱스는 -1</code></pre></li>
<li>인덱싱한 결과는 원소의 유형을 따른다</li>
</ul>
<h3 id="인덱싱indexing">인덱싱(Indexing)</h3>
<pre><code class="language-python">x_dict[&#39;name&#39;]</code></pre>
<p><strong>👉 결과</strong>
&#39;Gildong Hong&#39;</p>
<pre><code class="language-python">print(f&#39;{x_str = } \t\t==&gt; {x_str[0] = }&#39;) # 0은 첫원소의 인덱스
print(f&#39;{x_str = } \t\t==&gt; {x_str[3] = }&#39;)
print(f&#39;{x_list = } \t==&gt; {x_list[0] = }&#39;)
print(f&#39;{x_tuple = } \t==&gt; {x_tuple[-1] = }&#39;) # -1은 마지막 원소의 인덱스
print(f&#39;{x_dict = } \t==&gt; {x_dict[&quot;name&quot;] = }&#39;) # dictionary는 key로 인덱싱</code></pre>
<p><strong>👉 결과</strong>
x_str = &#39;abcde&#39;         ==&gt; x_str[0] = &#39;a&#39;
x_str = &#39;abcde&#39;         ==&gt; x_str[3] = &#39;d&#39;
x_list = [&#39;abcde&#39;, &#39;fghij&#39;]     ==&gt; x_list[0] = &#39;abcde&#39;
x_tuple = (&#39;abcde&#39;, 12345)     ==&gt; x_tuple[-1] = 12345
x_dict = {&#39;name&#39;: &#39;Gildong Hong&#39;, &#39;id&#39;: 83100}     ==&gt; x_dict[&quot;name&quot;] = &#39;Gildong Hong&#39;</p>
<hr>
<h2 id="22-슬라이싱slicing">2.2 슬라이싱(Slicing)</h2>
<ul>
<li>배열에서 부분집합을 가져오는 것<pre><code>- i:j -&gt; 인덱스 i에서 (j-1)까지
- i: -&gt; 인덱스 i에서 마지막까지
-  :j -&gt; 인덱스 처음부터 (j-1)까지
-  : -&gt; 인덱스 처음부터 끝까지</code></pre></li>
<li>슬라이싱한 결과는 원래의 type과 동일함</li>
</ul>
<h3 id="슬라이싱slicing">슬라이싱(Slicing)</h3>
<pre><code class="language-python">print(f&#39;{x_str = } \t\t==&gt; {x_str[2:] = }&#39;)
print(f&#39;{x_list = } \t==&gt; {x_list[0:1] = }&#39;)
print(f&#39;{x_tuple = } \t==&gt; {x_tuple[0:1] = }&#39;)</code></pre>
<p><strong>👉 결과</strong>
x_str = &#39;abcde&#39;         ==&gt; x_str[2:] = &#39;cde&#39;
x_list = [&#39;abcde&#39;, &#39;fghij&#39;]     ==&gt; x_list[0:1] = [&#39;abcde&#39;]
x_tuple = (&#39;abcde&#39;, 12345)     ==&gt; x_tuple[0:1] = (&#39;abcde&#39;,)</p>
<hr>
<h1 id="3-제어문">3 제어문</h1>
<hr>
<h2 id="31-분기문if-else">3.1 분기문(if-else)</h2>
<ul>
<li>조건의 만족 여부에 따라 코드의 실행 경로를 변경하는 문장<pre><code>  - 조건은 True 또는 False로 구분되는 문장
  - 파이썬은 indent로 문단을 구분함</code></pre><pre><code class="language-python">if (조건 1):
  (실행문 1)
elif (조건 2): # 생략 및 추가 기능
  (실행문 2)
else:          # 생략 가능
  (실행문 3)</code></pre>
</li>
</ul>
<h3 id="if-else">if-else</h3>
<pre><code class="language-python">money = 1000
if money &lt;= 500:
  print(&#39;걸어간다.&#39;)
else:
  print(&#39;택시탄다.&#39;)</code></pre>
<p><strong>👉 결과</strong><br>택시탄다.</p>
<h3 id="if-elif-else">if-elif-else</h3>
<pre><code class="language-python">money = 1000
if money &lt;= 500:
  print(&#39;걸어간다.&#39;)
elif money &lt;= 2500:
  print(&#39;버스탄다.&#39;)
else:
  print(&#39;택시탄다.&#39;)</code></pre>
<p><strong>👉 결과</strong>
버스탄다.</p>
<hr>
<h2 id="32-반복문while-for">3.2 반복문(while, for)</h2>
<ul>
<li>조건을 만족하는 동안 코드블럭을 반복수행하는 문장</li>
<li>파이썬은 indent로 문단을 구분함 (cf) C에서는 {}로 구분)</li>
</ul>
<h3 id="while문">while문</h3>
<pre><code class="language-python">조건변수 = 초기값
while (조건):
    조건변수 업데이트    (실행문)</code></pre>
<pre><code class="language-python">n=0
while n &lt; 5:
  n = n+1
  print(&quot;n=&quot;, n)</code></pre>
<p><strong>👉 결과</strong><br>n= 1
n= 2
n= 3
n= 4
n= 5</p>
<h3 id="for문">for문</h3>
<pre><code class="language-python">for 변수 in (유한한 변수의 값들):
    (실행문)</code></pre>
<pre><code class="language-python">for n in range(0,6):
    print(&quot;n=&quot;, n)</code></pre>
<p><strong>👉 결과</strong><br>n= 0
n= 1
n= 2
n= 3
n= 4
n= 5</p>
<pre><code class="language-python">for item in x_list:
  print(f&#39;{item = }&#39;)</code></pre>
<p><strong>👉 결과</strong><br>item = &#39;abcde&#39;
item = &#39;fghij&#39;</p>
<pre><code class="language-python">x = [10,20,30,40,50]
for method in [len, max, sum]:
    print(f&#39;{method(x) = }&#39;)</code></pre>
<p><strong>👉 결과</strong><br>method(x) = 5
method(x) = 50
method(x) = 150</p>
<h3 id="enumerate-함수를-이용한-for문">enumerate() 함수를 이용한 for문</h3>
<ul>
<li>for문에서 인덱스를 사용하고자 할 때 사용<pre><code class="language-python">for item in enumerate([&#39;a&#39;,&#39;b&#39;,&#39;c&#39;,&#39;d&#39;,&#39;e&#39;]):
 print(f&#39;{item = }&#39;)</code></pre>
</li>
<li><em>👉 결과*</em><br>item = (0, &#39;a&#39;)
item = (1, &#39;b&#39;)
item = (2, &#39;c&#39;)
item = (3, &#39;d&#39;)
item = (4, &#39;e&#39;)</li>
</ul>
<pre><code class="language-python">for i, item in enumerate([&#39;a&#39;,&#39;b&#39;,&#39;c&#39;,&#39;d&#39;,&#39;e&#39;]):
    print(f&#39;{i = }, {item = }&#39;)</code></pre>
<p><strong>👉 결과</strong><br>i = 0, item = &#39;a&#39;
i = 1, item = &#39;b&#39;
i = 2, item = &#39;c&#39;
i = 3, item = &#39;d&#39;
i = 4, item = &#39;e&#39;</p>
<hr>
<h2 id="33-함수">3.3 함수</h2>
<ul>
<li>인수(arguments)를 입력으로 받아 실행문(코드블럭)을 실행하고 출력(return)하는 하나의 실행 모듈</li>
<li>return은 튜플로 반환됨</li>
<li>매개변수(parameter)는 함수에 입력으로 전달된 값을 받는 변수를 의미하고 인수(arguments)는 함수를 호출할 때 전달하는 입력 값을 의미함</li>
</ul>
<pre><code class="language-python">def 함수명(매개변수):
    (실행문)
    return 변수</code></pre>
<h3 id="함수-정의">함수 정의</h3>
<pre><code class="language-python">def minus(a,b): # a,b는 parameters
  result = a-b
  return result</code></pre>
<h3 id="함수의-활용">함수의 활용</h3>
<pre><code class="language-python">a = minus(3,7) # 3,7은 arguments
print(a)</code></pre>
<p><strong>👉 결과</strong><br>-4</p>
<hr>
<h2 id="34-람다함수익명함수">3.4 람다함수(익명함수)</h2>
<ul>
<li>일반함수를 가볍게 만들어 사용하기 위한 함수<h3 id="람다함수-정의">람다함수 정의</h3>
</li>
<li>람다 표현식(lambda expression) = 익명함수(anonymous function)</li>
</ul>
<pre><code class="language-python">lambda 인자 : 표현식</code></pre>
<pre><code class="language-python">lambda x : x+1</code></pre>
<p><strong>👉 결과</strong><br>&lt;function <strong>main</strong>.<lambda>(x)&gt;</p>
<ul>
<li>함수명을 지정하여 재사용 가능함</li>
</ul>
<pre><code class="language-python">add_ten = lambda x: x + 10  </code></pre>
<ul>
<li><p>람다함수의 사용</p>
<pre><code class="language-python">print((lambda x: x+1)(10))
print(add_ten(10))</code></pre>
</li>
<li><p><em>👉 결과*</em><br>11
20</p>
</li>
<li><p>람다 표현식 안에서는 새 변수를 만들 수 없으나 밖의 변수는 사용가능함</p>
<pre><code class="language-python">y = 100
(lambda x: x+y+1)(10)</code></pre>
</li>
<li><p><em>👉 결과*</em><br>111</p>
</li>
</ul>
<h3 id="람다함수를-인자로-활용">람다함수를 인자로 활용</h3>
<ul>
<li>map 함수에 적용</li>
</ul>
<pre><code class="language-python">list(map(lambda x: x + 10, [1, 2, 3]))</code></pre>
<p><strong>👉 결과</strong><br>[11, 12, 13]</p>
<ul>
<li>람다 표현식에 조건부 표현식 사용</li>
</ul>
<pre><code class="language-python">a = range(10)
list(map(lambda x: &#39;str&#39;+str(x) if x % 3 == 0 else x, a))</code></pre>
<p><strong>👉 결과</strong><br>[&#39;str0&#39;, 1, 2, &#39;str3&#39;, 4, 5, &#39;str6&#39;, 7, 8, &#39;str9&#39;]</p>
<ul>
<li>람다 표현식에 복잡한 조건부 표현식 사용</li>
</ul>
<pre><code class="language-python">a = range(10)
list(map(lambda x: &#39;str&#39;+str(x) if x % 3 == 0 else float(x) if x % 3 == 1 else x, a))</code></pre>
<p><strong>👉 결과</strong><br>[&#39;str0&#39;, 1.0, 2, &#39;str3&#39;, 4.0, 5, &#39;str6&#39;, 7.0, 8, &#39;str9&#39;]</p>
<ul>
<li>람다 표현식에 인자 여러개 넣기</li>
</ul>
<pre><code class="language-python">a = range(10)
b = [100]*10     # 브로드캐스팅은 안됨
list(map(lambda x, y: x if x % 3 == 0 else x + y, a, b))</code></pre>
<p><strong>👉 결과</strong><br>[0, 101, 102, 3, 104, 105, 6, 107, 108, 9] </p>
<hr>
<h1 id="4-모듈과-패키지">4 모듈과 패키지</h1>
<hr>
<h2 id="41-모듈">4.1 모듈</h2>
<ul>
<li>함수나 변수 또는 클래스 들을 모아 놓은 파이썬 파일(.py)</li>
<li>다른 파이썬 프로그램에서 불러와(import) 사용할 수 있음</li>
</ul>
<h3 id="모듈-만들기my_modulepy">모듈 만들기(my_module.py)</h3>
<pre><code class="language-python">my_var = &#39;my_var&#39;
def my_func():
    return &#39;my_func&#39;
def _my_private_func():
    return &#39;my_private_func&#39;</code></pre>
<h3 id="모듈-불러오기">모듈 불러오기</h3>
<pre><code class="language-python">import my_module as mm

print(mm.my_var)
print(mm.my_func())
print(mm._my_private_func())</code></pre>
<p><strong>👉 결과</strong><br>my_var
my_func
my_private_func</p>
<hr>
<h2 id="42-패키지">4.2 패키지</h2>
<ul>
<li>모듈과 패키지들의 구조화된 collection으로 선행 연구자가 만들어서 배포한 것</li>
<li>Numpy, Pandas, Matplotlib, Seaborn 등<pre><code class="language-python">import numpy
import matplotlib.pyplot as plt
</code></pre>
</li>
</ul>
<p>print(numpy.sum([1,2,3,4,5]))
plt.plot([10,20,30,40], [1,4,9,16], &#39;rs--&#39;, [10,20,30,40], [11,24,9,6], &#39;g^-&#39;)
plt.show()</p>
<pre><code>**👉 결과**  
![](https://velog.velcdn.com/images/__zeroiszero/post/78a75ec9-4651-4638-882d-f8c7ee2dbedd/image.png)


-----------------------------------------------
# 5 데이터 불러오기와 저장하기
-----------------------------------------------
## 5.1 Pandas를 이용한 csv 데이터 불러오기
### csv 데이터 불러와서 확인하기

``` python
import pandas as pd

df = pd.read_csv(&#39;bank.csv&#39;, sep = &#39;,&#39;)
print(df.head(3)) # default=5
print(df.tail(2)) # default=5</code></pre><p><strong>👉 결과(모양 깨짐)</strong>                  age;&quot;job&quot;;&quot;marital&quot;;&quot;education&quot;;&quot;default&quot;;&quot;balance&quot;;&quot;housing&quot;;&quot;loan&quot;;&quot;contact&quot;;&quot;day&quot;;&quot;month&quot;;&quot;duration&quot;;&quot;campaign&quot;;&quot;pdays&quot;;&quot;previous&quot;;&quot;poutcome&quot;;&quot;y&quot;
      0  30;&quot;unemployed&quot;;&quot;married&quot;;&quot;primary&quot;;&quot;no&quot;;1787;...<br>      1  33;&quot;services&quot;;&quot;married&quot;;&quot;secondary&quot;;&quot;no&quot;;4789;...<br>      2  35;&quot;management&quot;;&quot;single&quot;;&quot;tertiary&quot;;&quot;no&quot;;1350;...<br>           age;&quot;job&quot;;&quot;marital&quot;;&quot;education&quot;;&quot;default&quot;;&quot;balance&quot;;&quot;housing&quot;;&quot;loan&quot;;&quot;contact&quot;;&quot;day&quot;;&quot;month&quot;;&quot;duration&quot;;&quot;campaign&quot;;&quot;pdays&quot;;&quot;previous&quot;;&quot;poutcome&quot;;&quot;y&quot;
      4519  28;&quot;blue-collar&quot;;&quot;married&quot;;&quot;secondary&quot;;&quot;no&quot;;11...<br>      4520  44;&quot;entrepreneur&quot;;&quot;single&quot;;&quot;tertiary&quot;;&quot;no&quot;;113...   </p>
<h3 id="csv-파일로-저장하기">csv 파일로 저장하기</h3>
<pre><code class="language-python">df.to_csv(&#39;data/bank_new.csv&#39;, index=False)</code></pre>
<hr>
<h2 id="52-raw-string을-이용하여-출력하기">5.2 raw string을 이용하여 출력하기</h2>
<ul>
<li>string 앞에 r을 표기</li>
<li>모든 escape 문자를 그대로 출력하기</li>
</ul>
<pre><code class="language-python">string = &quot;Hello!!!\tPython world.\n My name is Youngeun&quot;
rstring = r&quot;Hello!!!\tPython world.\n My name is Youngeun&quot;

print(string)
print(rstring)</code></pre>
<p><strong>👉 결과</strong><br>Hello!!!    Python world.
My name is Youngeun
Hello!!!\tPython world.\n My name is Youngeun</p>
<hr>
<h2 id="53-f-string을-이용하여-출력하기">5.3 f-string을 이용하여 출력하기</h2>
<ul>
<li>formatted string literals</li>
<li>파이썬 3.6부터 format, %(서식지정자)와 같은 문자열 포매팅 방법 대신에 f-string이 가능함</li>
</ul>
<h3 id="문자열--앞에-f를-붙이고-문자열-내에-를-이용하여-값을-지정">문자열 &quot; 앞에 f를 붙이고, 문자열 내에 {}를 이용하여 값을 지정</h3>
<pre><code class="language-python">names = [&#39;홍익&#39;, &#39;파이썬&#39;, &#39;스트링&#39;]
num_ints = [10, 20, 30]
num_float = 4321.12345678

# 변수 지정
print(f&#39;{names}의 나이는 {num_ints}이다.&#39;)
# 변수를 인덱싱, 슬라이싱하여 지정
print(f&#39;{names[0]}의 나이는 {num_ints[:2]}이다.&#39;)
# {}내 연산 가능
print(f&#39;{names[0]}의 나이는 {num_ints[0] + num_ints[1]}이다.&#39;)
# 변수로 사용
for name, age in zip(names, num_ints):
    print(f&#39;{name}의 나이는 {age}이다.&#39;)</code></pre>
<p><strong>👉 결과</strong><br>[&#39;홍익&#39;, &#39;파이썬&#39;, &#39;스트링&#39;]의 나이는 [10, 20, 30]이다.
홍익의 나이는 [10, 20]이다.
홍익의 나이는 30이다.
홍익의 나이는 10이다.
파이썬의 나이는 20이다.
스트링의 나이는 30이다.</p>
<h2 id="53-1-글자수-정렬-소숫점-자리수">5.3-1 글자수, 정렬, 소숫점 자리수</h2>
<h3 id="글자수를-지정하여-문자열을-정렬">글자수를 지정하여 문자열을 정렬</h3>
<ul>
<li>f-string의 중괄호{} 안에서 : 구분자를 이용함</li>
<li>구분자 왼쪽은 문자나 숫자를, 오른쪽에는 정렬 기호와 숫자, 서식 지정자를 사용함<ul>
<li>정렬기호 : 없음 -&gt; 왼쪽, ^ -&gt; 가운데, &gt; -&gt; 오른쪽</li>
<li>서식지정자 : 문자열 -&gt; s, 정수 -&gt; d, 실수 -&gt; f<h3 id="소수점-자릿수-지정">소수점 자릿수 지정</h3>
</li>
</ul>
</li>
<li>: 구분자 오른편에. 자릿수 f를 사용함<pre><code class="language-python"># 자리수와 정렬 지정
print(f&#39;{names[0]:10s}의 나이는 {num_ints[0]:&gt;10d}이다.&#39;)
print(f&#39;{names[1]:&gt;10s}의 나이는 {num_ints[0]:^10d}이다.&#39;)
</code></pre>
</li>
</ul>
<h1 id="소숫점-자리수-지정">소숫점 자리수 지정</h1>
<p>print(f&#39;{names[2]:&gt;10s}의 숫자는 {num_float:^10.2f}이다.&#39;)</p>
<p>```
<strong>👉 결과</strong><br>홍익        의 나이는         10이다.
       파이썬의 나이는     10    이다.
       스트링의 숫자는  4321.12  이다.</p>
]]></description>
        </item>
    </channel>
</rss>