{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "rQ8UhzFpgRra" }, "source": [ "# 데이터 준비\n", "\n", "[원본 노트북 출처: *Data Science: Introduction to Machine Learning for Data Science Python and Machine Learning Studio by Lee Stott*](https://github.com/leestott/intro-Datascience/blob/master/Course%20Materials/4-Cleaning_and_Manipulating-Reference.ipynb)\n", "\n", "## `DataFrame` 정보 탐색\n", "\n", "> **학습 목표:** 이 절의 끝까지 학습하면 pandas DataFrame에 저장된 데이터에 대한 일반적인 정보를 찾는 데 익숙해질 것입니다.\n", "\n", "데이터를 pandas에 로드하면 대부분의 경우 `DataFrame` 형태로 저장됩니다. 하지만 `DataFrame`에 있는 데이터 세트가 60,000개의 행과 400개의 열로 구성되어 있다면, 어디서부터 작업을 시작해야 할지 막막할 수 있습니다. 다행히도 pandas는 `DataFrame`의 전체적인 정보를 빠르게 확인할 수 있는 편리한 도구를 제공하며, 첫 몇 행과 마지막 몇 행도 쉽게 볼 수 있습니다.\n", "\n", "이 기능을 탐색하기 위해 Python의 scikit-learn 라이브러리를 가져오고, 모든 데이터 과학자가 수백 번은 봤을 유명한 데이터 세트를 사용할 것입니다. 이는 영국 생물학자 로널드 피셔가 1936년 논문 \"분류 문제에서 다중 측정값의 사용\"에서 사용한 *Iris* 데이터 세트입니다.\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true, "id": "hB1RofhdgRrp", "trusted": false }, "outputs": [], "source": [ "import pandas as pd\n", "from sklearn.datasets import load_iris\n", "\n", "iris = load_iris()\n", "iris_df = pd.DataFrame(data=iris['data'], columns=iris['feature_names'])" ] }, { "cell_type": "markdown", "metadata": { "id": "AGA0A_Y8hMdz" }, "source": [ "### `DataFrame.shape`\n", "우리는 Iris 데이터셋을 변수 `iris_df`에 로드했습니다. 데이터를 분석하기 전에, 우리가 가진 데이터 포인트의 수와 데이터셋의 전체 크기를 아는 것이 중요합니다. 우리가 다루고 있는 데이터의 규모를 확인하는 것은 유용합니다.\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "LOe5jQohhulf", "outputId": "fb0577ac-3b4a-4623-cb41-20e1b264b3e9" }, "outputs": [ { "data": { "text/plain": [ "(150, 4)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.shape" ] }, { "cell_type": "markdown", "metadata": { "id": "smE7AGzOhxk2" }, "source": [ "우리는 150개의 행과 4개의 열로 구성된 데이터를 다루고 있습니다. 각 행은 하나의 데이터 포인트를 나타내며, 각 열은 데이터 프레임과 연관된 하나의 특징을 나타냅니다. 즉, 총 150개의 데이터 포인트가 있으며, 각각 4개의 특징을 포함하고 있습니다.\n", "\n", "여기서 `shape`는 데이터 프레임의 속성(attribute)이지 함수가 아니기 때문에 괄호로 끝나지 않습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "d3AZKs0PinGP" }, "source": [ "### `DataFrame.columns`\n", "이제 데이터의 4개 열로 넘어가 보겠습니다. 각각의 열은 정확히 무엇을 나타낼까요? `columns` 속성은 데이터프레임에서 열의 이름을 알려줍니다.\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "YPGh_ziji-CY", "outputId": "74e7a43a-77cc-4c80-da56-7f50767c37a0" }, "outputs": [ { "data": { "text/plain": [ "Index(['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)',\n", " 'petal width (cm)'],\n", " dtype='object')" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.columns" ] }, { "cell_type": "markdown", "metadata": { "id": "TsobcU_VjCC_" }, "source": [ "우리가 볼 수 있듯이, 네(4) 개의 열이 있습니다. `columns` 속성은 열의 이름을 알려주며 기본적으로 다른 정보는 제공하지 않습니다. 이 속성은 데이터셋이 포함하는 특징을 식별하고자 할 때 중요성을 갖습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "2UTlvkjmgRrs" }, "source": [ "### `DataFrame.info`\n", "`shape` 속성이 제공하는 데이터 양과 `columns` 속성이 제공하는 특징 또는 열 이름은 데이터셋에 대해 일부 정보를 알려줍니다. 이제 데이터셋을 더 깊이 탐구하고 싶을 것입니다. `DataFrame.info()` 함수는 이를 위해 매우 유용합니다.\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "dHHRyG0_gRrt", "outputId": "d8fb0c40-4f18-4e19-da48-c8db77d1d3a5", "trusted": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 150 entries, 0 to 149\n", "Data columns (total 4 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 sepal length (cm) 150 non-null float64\n", " 1 sepal width (cm) 150 non-null float64\n", " 2 petal length (cm) 150 non-null float64\n", " 3 petal width (cm) 150 non-null float64\n", "dtypes: float64(4)\n", "memory usage: 4.8 KB\n" ] } ], "source": [ "iris_df.info()" ] }, { "cell_type": "markdown", "metadata": { "id": "1XgVMpvigRru" }, "source": [ "여기에서 몇 가지 관찰을 할 수 있습니다:\n", "1. 각 열의 데이터 유형: 이 데이터셋에서는 모든 데이터가 64비트 부동소수점 숫자로 저장되어 있습니다.\n", "2. 비-Null 값의 개수: Null 값을 처리하는 것은 데이터 준비 과정에서 중요한 단계입니다. 이는 노트북에서 나중에 다룰 예정입니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "IYlyxbpWFEF4" }, "source": [ "### DataFrame.describe()\n", "데이터셋에 수많은 숫자 데이터가 있다고 가정해봅시다. 평균, 중앙값, 사분위수 등과 같은 단변량 통계 계산은 각 열별로 개별적으로 수행할 수 있습니다. `DataFrame.describe()` 함수는 데이터셋의 숫자 열에 대한 통계 요약을 제공합니다.\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 297 }, "id": "tWV-CMstFIRA", "outputId": "4fc49941-bc13-4b0c-a412-cb39e7d3f289" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
count150.000000150.000000150.000000150.000000
mean5.8433333.0573333.7580001.199333
std0.8280660.4358661.7652980.762238
min4.3000002.0000001.0000000.100000
25%5.1000002.8000001.6000000.300000
50%5.8000003.0000004.3500001.300000
75%6.4000003.3000005.1000001.800000
max7.9000004.4000006.9000002.500000
\n", "
" ], "text/plain": [ " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n", "count 150.000000 150.000000 150.000000 150.000000\n", "mean 5.843333 3.057333 3.758000 1.199333\n", "std 0.828066 0.435866 1.765298 0.762238\n", "min 4.300000 2.000000 1.000000 0.100000\n", "25% 5.100000 2.800000 1.600000 0.300000\n", "50% 5.800000 3.000000 4.350000 1.300000\n", "75% 6.400000 3.300000 5.100000 1.800000\n", "max 7.900000 4.400000 6.900000 2.500000" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.describe()" ] }, { "cell_type": "markdown", "metadata": { "id": "zjjtW5hPGMuM" }, "source": [ "위의 출력은 각 열의 총 데이터 포인트 수, 평균, 표준 편차, 최소값, 하위 사분위수(25%), 중앙값(50%), 상위 사분위수(75%) 및 최대값을 보여줍니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "-lviAu99gRrv" }, "source": [ "### `DataFrame.head`\n", "위의 모든 함수와 속성을 통해 데이터셋에 대한 전반적인 개요를 파악했습니다. 데이터 포인트가 몇 개인지, 특징이 몇 개인지, 각 특징의 데이터 타입은 무엇인지, 그리고 각 특징에 비어 있지 않은 값이 몇 개인지 알게 되었습니다.\n", "\n", "이제 실제 데이터를 살펴볼 차례입니다. `DataFrame`의 첫 몇 행(첫 몇 개의 데이터 포인트)이 어떻게 생겼는지 확인해봅시다:\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "DZMJZh0OgRrw", "outputId": "d9393ee5-c106-4797-f815-218f17160e00", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
45.03.61.40.2
\n", "
" ], "text/plain": [ " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n", "0 5.1 3.5 1.4 0.2\n", "1 4.9 3.0 1.4 0.2\n", "2 4.7 3.2 1.3 0.2\n", "3 4.6 3.1 1.5 0.2\n", "4 5.0 3.6 1.4 0.2" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.head()" ] }, { "cell_type": "markdown", "metadata": { "id": "EBHEimZuEFQK" }, "source": [ "여기 출력에서 데이터셋의 다섯(5) 개 항목을 볼 수 있습니다. 왼쪽의 인덱스를 보면 이것이 첫 다섯 행임을 알 수 있습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "oj7GkrTdgRry" }, "source": [ "### 연습 문제:\n", "\n", "위 예제에서 알 수 있듯이, 기본적으로 `DataFrame.head`는 `DataFrame`의 처음 다섯 행을 반환합니다. 아래 코드 셀에서 다섯 행보다 더 많은 행을 표시하는 방법을 찾아볼 수 있겠습니까?\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true, "id": "EKRmRFFegRrz", "trusted": false }, "outputs": [], "source": [ "# Hint: Consult the documentation by using iris_df.head?" ] }, { "cell_type": "markdown", "metadata": { "id": "BJ_cpZqNgRr1" }, "source": [ "### `DataFrame.tail`\n", "데이터를 보는 또 다른 방법은 시작이 아닌 끝에서부터 보는 것입니다. `DataFrame.head`의 반대는 `DataFrame.tail`로, `DataFrame`의 마지막 다섯 행을 반환합니다:\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 0 }, "id": "heanjfGWgRr2", "outputId": "6ae09a21-fe09-4110-b0d7-1a1fbf34d7f3", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
1456.73.05.22.3
1466.32.55.01.9
1476.53.05.22.0
1486.23.45.42.3
1495.93.05.11.8
\n", "
" ], "text/plain": [ " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n", "145 6.7 3.0 5.2 2.3\n", "146 6.3 2.5 5.0 1.9\n", "147 6.5 3.0 5.2 2.0\n", "148 6.2 3.4 5.4 2.3\n", "149 5.9 3.0 5.1 1.8" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris_df.tail()" ] }, { "cell_type": "markdown", "metadata": { "id": "31kBWfyLgRr3" }, "source": [ "데이터셋에서 이상값을 찾을 때, 특히 정렬된 데이터셋을 다룰 때 `DataFrame`의 처음 몇 행이나 마지막 몇 행을 쉽게 확인할 수 있는 기능은 매우 유용합니다.\n", "\n", "위에서 코드 예제를 통해 보여준 모든 함수와 속성은 데이터를 살펴보고 이해하는 데 도움을 줍니다.\n", "\n", "> **핵심 요점:** `DataFrame`의 정보에 대한 메타데이터나 처음과 마지막 몇 개의 값을 확인하는 것만으로도, 다루고 있는 데이터의 크기, 형태, 그리고 내용을 즉각적으로 파악할 수 있습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "TvurZyLSDxq_" }, "source": [ "### 누락된 데이터\n", "누락된 데이터에 대해 알아봅시다. 누락된 데이터는 일부 열에 값이 저장되지 않았을 때 발생합니다.\n", "\n", "예를 들어, 누군가 자신의 체중에 대해 민감하여 설문조사에서 체중 항목을 작성하지 않는다고 가정해봅시다. 그러면 해당 사람의 체중 값은 누락되게 됩니다.\n", "\n", "대부분의 경우, 실제 데이터셋에서는 누락된 값이 발생합니다.\n", "\n", "**Pandas가 누락된 데이터를 처리하는 방법**\n", "\n", "Pandas는 누락된 값을 두 가지 방식으로 처리합니다. 첫 번째는 이전 섹션에서 본 적이 있는 `NaN`(Not a Number)입니다. 이는 실제로 IEEE 부동소수점 사양의 일부로, 누락된 부동소수점 값을 나타내기 위해 사용되는 특별한 값입니다.\n", "\n", "부동소수점 외의 누락된 값에 대해서는 pandas가 Python의 `None` 객체를 사용합니다. 두 가지 다른 종류의 값이 본질적으로 동일한 의미를 전달하는 것처럼 보일 수 있지만, 이러한 설계 선택에는 합리적인 프로그래밍 이유가 있습니다. 실제로 이러한 접근 방식은 대부분의 경우에 대해 pandas가 적절한 절충안을 제공할 수 있도록 합니다. 그럼에도 불구하고, `None`과 `NaN` 모두 사용 방법과 관련하여 주의해야 할 제한 사항이 있습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "lOHqUlZFgRr5" }, "source": [ "### `None`: 비-부동 소수점 누락 데이터\n", "`None`은 Python에서 비롯되었기 때문에 데이터 유형이 `'object'`가 아닌 NumPy와 pandas 배열에서는 사용할 수 없습니다. NumPy 배열(그리고 pandas의 데이터 구조)은 오직 한 가지 유형의 데이터만 포함할 수 있다는 점을 기억하세요. 이것이 대규모 데이터와 계산 작업에서 엄청난 성능을 제공하는 이유이지만, 동시에 유연성을 제한하는 요인이기도 합니다. 이러한 배열은 \"최소 공통 분모\"로 업캐스트해야 하며, 배열 내 모든 것을 포함할 수 있는 데이터 유형으로 변환됩니다. 배열에 `None`이 포함되어 있다면, 이는 Python 객체를 다루고 있다는 것을 의미합니다.\n", "\n", "이를 실제로 확인하려면 다음 예제 배열을 살펴보세요 (`dtype`를 주목하세요):\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "QIoNdY4ngRr7", "outputId": "92779f18-62f4-4a03-eca2-e9a101604336", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "array([2, None, 6, 8], dtype=object)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "\n", "example1 = np.array([2, None, 6, 8])\n", "example1" ] }, { "cell_type": "markdown", "metadata": { "id": "pdlgPNbhgRr7" }, "source": [ "업캐스트 데이터 타입의 현실은 두 가지 부작용을 동반합니다. 첫째, 연산이 컴파일된 NumPy 코드가 아닌, 해석된 Python 코드 수준에서 수행됩니다. 기본적으로 이는 `Series`나 `DataFrame`에 `None`이 포함된 경우, 해당 연산이 더 느려진다는 것을 의미합니다. 이러한 성능 저하를 눈치채지 못할 수도 있지만, 대규모 데이터셋에서는 문제가 될 수 있습니다.\n", "\n", "두 번째 부작용은 첫 번째에서 비롯됩니다. `None`이 본질적으로 `Series`나 `DataFrame`을 일반 Python의 세계로 끌어들이기 때문에, `sum()`이나 `min()`과 같은 NumPy/pandas 집계 함수를 `None` 값을 포함한 배열에 사용하면 일반적으로 오류가 발생합니다:\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 292 }, "id": "gWbx-KB9gRr8", "outputId": "ecba710a-22ec-41d5-a39c-11f67e645b50", "trusted": false }, "outputs": [ { "ename": "TypeError", "evalue": "ignored", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mexample1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/numpy/core/_methods.py\u001b[0m in \u001b[0;36m_sum\u001b[0;34m(a, axis, dtype, out, keepdims, initial, where)\u001b[0m\n\u001b[1;32m 45\u001b[0m def _sum(a, axis=None, dtype=None, out=None, keepdims=False,\n\u001b[1;32m 46\u001b[0m initial=_NoValue, where=True):\n\u001b[0;32m---> 47\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mumr_sum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkeepdims\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minitial\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwhere\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 48\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 49\u001b[0m def _prod(a, axis=None, dtype=None, out=None, keepdims=False,\n", "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'int' and 'NoneType'" ] } ], "source": [ "example1.sum()" ] }, { "cell_type": "markdown", "metadata": { "id": "LcEwO8UogRr9" }, "source": [] }, { "cell_type": "markdown", "metadata": { "id": "pWvVHvETgRr9" }, "source": [ "### `NaN`: 부재한 실수 값\n", "\n", "`None`과는 달리, NumPy(그리고 pandas)는 빠르고 벡터화된 연산 및 ufunc을 위해 `NaN`을 지원합니다. 문제는 `NaN`에 대해 수행된 모든 산술 연산이 항상 `NaN`을 결과로 낸다는 점입니다. 예를 들어:\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "rcFYfMG9gRr9", "outputId": "699e81b7-5c11-4b46-df1d-06071768690f", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "nan" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.nan + 1" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "BW3zQD2-gRr-", "outputId": "4525b6c4-495d-4f7b-a979-efce1dae9bd0", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "nan" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.nan * 0" ] }, { "cell_type": "markdown", "metadata": { "id": "fU5IPRcCgRr-" }, "source": [ "좋은 소식: `NaN`이 포함된 배열에서 실행되는 집계는 오류를 발생시키지 않습니다. 나쁜 소식: 결과가 일관되게 유용하지는 않습니다:\n" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "LCInVgSSgRr_", "outputId": "fa06495a-0930-4867-87c5-6023031ea8b5", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "(nan, nan, nan)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example2 = np.array([2, np.nan, 6, 8]) \n", "example2.sum(), example2.min(), example2.max()" ] }, { "cell_type": "markdown", "metadata": { "id": "nhlnNJT7gRr_" }, "source": [ "### 운동:\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true, "id": "yan3QRaOgRr_", "trusted": false }, "outputs": [], "source": [ "# What happens if you add np.nan and None together?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "_iDvIRC8gRsA" }, "source": [ "`NaN`은 부동 소수점 값이 누락된 경우에만 사용됩니다. 정수, 문자열 또는 불리언에는 `NaN`에 해당하는 값이 없습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "kj6EKdsAgRsA" }, "source": [ "### `NaN`과 `None`: pandas에서의 null 값\n", "\n", "`NaN`과 `None`이 약간 다르게 작동할 수는 있지만, pandas는 이 둘을 서로 교환하여 처리할 수 있도록 설계되었습니다. 이를 이해하기 위해 정수로 이루어진 `Series`를 살펴보세요:\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Nji-KGdNgRsA", "outputId": "36aa14d2-8efa-4bfd-c0ed-682991288822", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "0 1\n", "1 2\n", "2 3\n", "dtype: int64" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "int_series = pd.Series([1, 2, 3], dtype=int)\n", "int_series" ] }, { "cell_type": "markdown", "metadata": { "id": "WklCzqb8gRsB" }, "source": [ "### 운동:\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": true, "id": "Cy-gqX5-gRsB", "trusted": false }, "outputs": [], "source": [ "# Now set an element of int_series equal to None.\n", "# How does that element show up in the Series?\n", "# What is the dtype of the Series?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "WjMQwltNgRsB" }, "source": [ "데이터 유형의 동질성을 유지하기 위해 `Series`와 `DataFrame`에서 데이터 유형을 업캐스팅하는 과정에서 pandas는 결측값을 `None`과 `NaN` 사이에서 자유롭게 전환합니다. 이러한 설계 특징 때문에 pandas에서 `None`과 `NaN`을 \"null\"의 두 가지 다른 형태로 생각하는 것이 유용할 수 있습니다. 실제로, pandas에서 결측값을 처리하기 위해 사용하는 핵심 메서드 중 일부는 이러한 아이디어를 이름에 반영하고 있습니다:\n", "\n", "- `isnull()`: 결측값을 나타내는 Boolean 마스크를 생성\n", "- `notnull()`: `isnull()`의 반대\n", "- `dropna()`: 필터링된 데이터 버전을 반환\n", "- `fillna()`: 결측값을 채우거나 대체한 데이터 복사본을 반환\n", "\n", "이 메서드들은 익숙해지고 숙달해야 할 중요한 기능들입니다. 이제 각각을 좀 더 깊이 살펴보겠습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "Yh5ifd9FgRsB" }, "source": [ "### 결측값 감지하기\n", "\n", "결측값의 중요성을 이해했으니, 이를 처리하기 전에 데이터셋에서 결측값을 감지해야 합니다. \n", "`isnull()`과 `notnull()`은 결측 데이터를 감지하기 위한 주요 메서드입니다. 두 메서드 모두 데이터에 대해 Boolean 마스크를 반환합니다.\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": true, "id": "e-vFp5lvgRsC", "trusted": false }, "outputs": [], "source": [ "example3 = pd.Series([0, np.nan, '', None])" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "1XdaJJ7PgRsC", "outputId": "92fc363a-1874-471f-846d-f4f9ce1f51d0", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "0 False\n", "1 True\n", "2 False\n", "3 True\n", "dtype: bool" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example3.isnull()" ] }, { "cell_type": "markdown", "metadata": { "id": "PaSZ0SQygRsC" }, "source": [ "출력 내용을 자세히 살펴보세요. 놀라운 점이 있나요? `0`은 산술적으로는 null이지만, 여전히 완벽한 정수이며 pandas는 이를 정수로 처리합니다. `''`는 조금 더 미묘합니다. Section 1에서 빈 문자열 값을 나타내기 위해 사용했지만, pandas 관점에서는 여전히 문자열 객체이며 null을 나타내는 것이 아닙니다.\n", "\n", "이제 방향을 바꿔서 이러한 메서드들을 실제로 사용하는 방식에 더 가깝게 사용해 보겠습니다. Boolean 마스크를 직접 ``Series`` 또는 ``DataFrame`` 인덱스로 사용할 수 있으며, 이는 누락된 값(또는 존재하는 값)을 분리하여 작업할 때 유용할 수 있습니다.\n", "\n", "누락된 값의 총 개수를 알고 싶다면, `isnull()` 메서드로 생성된 마스크에 대해 단순히 합계를 구하면 됩니다.\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "JCcQVoPkHDUv", "outputId": "001daa72-54f8-4bd5-842a-4df627a79d4d" }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example3.isnull().sum()" ] }, { "cell_type": "markdown", "metadata": { "id": "PlBqEo3mgRsC" }, "source": [ "### 운동:\n" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": true, "id": "ggDVf5uygRsD", "trusted": false }, "outputs": [], "source": [ "# Try running example3[example3.notnull()].\n", "# Before you do so, what do you expect to see?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "D_jWN7mHgRsD" }, "source": [ "**핵심 요점**: `isnull()` 및 `notnull()` 메서드는 DataFrame에서 사용할 때 유사한 결과를 생성합니다. 이 메서드들은 결과와 해당 결과의 인덱스를 보여주며, 데이터를 다룰 때 큰 도움이 됩니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "BvnoojWsgRr4" }, "source": [ "### 결측 데이터 처리하기\n", "\n", "> **학습 목표:** 이 절을 마치면 DataFrame에서 null 값을 대체하거나 제거하는 방법과 시기를 알게 됩니다.\n", "\n", "머신 러닝 모델은 결측 데이터를 자체적으로 처리할 수 없습니다. 따라서 데이터를 모델에 전달하기 전에 이러한 결측 값을 처리해야 합니다.\n", "\n", "결측 데이터를 처리하는 방식은 미묘한 트레이드오프를 포함하며, 최종 분석 결과와 실제 결과에 영향을 미칠 수 있습니다.\n", "\n", "결측 데이터를 처리하는 주요 방법은 두 가지입니다:\n", "\n", "1. 결측 값을 포함한 행을 삭제하기\n", "2. 결측 값을 다른 값으로 대체하기\n", "\n", "이 두 가지 방법과 각각의 장단점에 대해 자세히 논의해 보겠습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "3VaYC1TvgRsD" }, "source": [ "### 결측값 제거하기\n", "\n", "모델에 전달하는 데이터의 양은 성능에 직접적인 영향을 미칩니다. 결측값을 제거한다는 것은 데이터 포인트의 수를 줄이고, 따라서 데이터셋의 크기를 줄이는 것을 의미합니다. 데이터셋이 상당히 클 경우, 결측값이 있는 행을 제거하는 것이 권장됩니다.\n", "\n", "또 다른 경우로는 특정 행이나 열에 결측값이 너무 많을 때가 있습니다. 이 경우, 해당 행이나 열은 대부분의 데이터가 누락되어 있어 분석에 큰 가치를 더하지 못하기 때문에 제거될 수 있습니다.\n", "\n", "결측값을 식별하는 것을 넘어, pandas는 `Series`와 `DataFrame`에서 결측값을 제거할 수 있는 편리한 방법을 제공합니다. 이를 실제로 확인하기 위해 `example3`로 돌아가 봅시다. `DataFrame.dropna()` 함수는 결측값이 있는 행을 제거하는 데 도움을 줍니다.\n" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "7uIvS097gRsD", "outputId": "c13fc117-4ca1-4145-a0aa-42ac89e6e218", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "0 0\n", "2 \n", "dtype: object" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example3 = example3.dropna()\n", "example3" ] }, { "cell_type": "markdown", "metadata": { "id": "hil2cr64gRsD" }, "source": [ "이것은 `example3[example3.notnull()]`의 출력과 같아 보입니다. 여기서 차이점은 마스크된 값만 인덱싱하는 대신, `dropna`가 `Series` `example3`에서 누락된 값을 제거했다는 점입니다.\n", "\n", "DataFrame은 두 개의 차원을 가지므로 데이터를 제거하는 데 더 많은 옵션을 제공합니다.\n" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "an-l74sPgRsE", "outputId": "340876a0-63ad-40f6-bd54-6240cdae50ab", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
01.0NaN7
12.05.08
2NaN6.09
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 1.0 NaN 7\n", "1 2.0 5.0 8\n", "2 NaN 6.0 9" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4 = pd.DataFrame([[1, np.nan, 7], \n", " [2, 5, 8], \n", " [np.nan, 6, 9]])\n", "example4" ] }, { "cell_type": "markdown", "metadata": { "id": "66wwdHZrgRsE" }, "source": [ "(판다스가 `NaN` 값을 처리하기 위해 두 개의 열을 부동소수점(float)으로 업캐스트한 것을 눈치채셨나요?)\n", "\n", "`DataFrame`에서 단일 값을 삭제할 수는 없으므로 전체 행이나 열을 삭제해야 합니다. 수행하려는 작업에 따라 둘 중 하나를 선택해야 하며, 판다스는 이를 위해 두 가지 옵션을 제공합니다. 데이터 과학에서는 일반적으로 열이 변수를 나타내고 행이 관측치를 나타내기 때문에, 데이터를 삭제할 때 행을 삭제하는 경우가 더 많습니다. `dropna()`의 기본 설정은 null 값을 포함하는 모든 행을 삭제하는 것입니다:\n" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 80 }, "id": "jAVU24RXgRsE", "outputId": "0b5e5aee-7187-4d3f-b583-a44136ae5f80", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
12.05.08
\n", "
" ], "text/plain": [ " 0 1 2\n", "1 2.0 5.0 8" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.dropna()" ] }, { "cell_type": "markdown", "metadata": { "id": "TrQRBuTDgRsE" }, "source": [ "필요한 경우 열에서 NA 값을 제거할 수 있습니다. 이를 위해 `axis=1`을 사용하세요:\n" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "GrBhxu9GgRsE", "outputId": "ff4001f3-2e61-4509-d60e-0093d1068437", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
2
07
18
29
\n", "
" ], "text/plain": [ " 2\n", "0 7\n", "1 8\n", "2 9" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.dropna(axis='columns')" ] }, { "cell_type": "markdown", "metadata": { "id": "KWXiKTfMgRsF" }, "source": [ "데이터가 적은 경우, 특히 작은 데이터셋에서는 유지하고 싶은 데이터를 많이 잃을 수 있습니다. 그렇다면 null 값이 몇 개 있거나 심지어 모두 null 값인 행이나 열만 삭제하고 싶다면 어떻게 해야 할까요? `dropna`의 `how`와 `thresh` 매개변수를 사용하여 이를 설정할 수 있습니다.\n", "\n", "기본적으로 `how='any'`로 설정되어 있습니다 (직접 확인하거나 메서드의 다른 매개변수를 보고 싶다면 코드 셀에서 `example4.dropna?`를 실행해 보세요). 대신 `how='all'`을 지정하여 모든 값이 null인 행이나 열만 삭제하도록 설정할 수도 있습니다. 다음 연습에서 이 동작을 확인하기 위해 예제 `DataFrame`을 확장해 보겠습니다.\n" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "Bcf_JWTsgRsF", "outputId": "72e0b1b8-52fa-4923-98ce-b6fbed6e44b1", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
01.0NaN7NaN
12.05.08NaN
2NaN6.09NaN
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "0 1.0 NaN 7 NaN\n", "1 2.0 5.0 8 NaN\n", "2 NaN 6.0 9 NaN" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4[3] = np.nan\n", "example4" ] }, { "cell_type": "markdown", "metadata": { "id": "pNZer7q9JPNC" }, "source": [ "> 주요 요점:\n", "1. 데이터셋이 충분히 클 경우에만 null 값을 제거하는 것이 좋은 선택입니다.\n", "2. 대부분의 데이터가 누락된 전체 행이나 열은 삭제할 수 있습니다.\n", "3. `DataFrame.dropna(axis=)` 메서드는 null 값을 제거하는 데 유용합니다. `axis` 인자는 행을 삭제할지 열을 삭제할지를 나타냅니다.\n", "4. `how` 인자도 사용할 수 있습니다. 기본값은 `any`로 설정되어 있어, null 값이 하나라도 포함된 행/열만 삭제합니다. 이를 `all`로 설정하면 모든 값이 null인 행/열만 삭제하도록 지정할 수 있습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "oXXSfQFHgRsF" }, "source": [ "### 운동:\n" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": true, "id": "ExUwQRxpgRsF", "trusted": false }, "outputs": [], "source": [ "# How might you go about dropping just column 3?\n", "# Hint: remember that you will need to supply both the axis parameter and the how parameter.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "38kwAihWgRsG" }, "source": [ "`thresh` 매개변수는 더 세밀한 제어를 제공합니다. 행 또는 열이 유지되기 위해 가져야 하는 *null이 아닌* 값의 수를 설정합니다.\n" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 80 }, "id": "M9dCNMaagRsG", "outputId": "8093713a-54d2-4e54-c73f-4eea315cb6f2", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
12.05.08NaN
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "1 2.0 5.0 8 NaN" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.dropna(axis='rows', thresh=3)" ] }, { "cell_type": "markdown", "metadata": { "id": "fmSFnzZegRsG" }, "source": [ "여기서 첫 번째와 마지막 행은 삭제되었습니다. 왜냐하면 해당 행들은 비null 값이 두 개만 포함하고 있기 때문입니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "mCcxLGyUgRsG" }, "source": [ "### 누락된 값 채우기\n", "\n", "때로는 누락된 값을 유효할 수 있는 값으로 채우는 것이 합리적일 수 있습니다. 누락된 값을 채우는 몇 가지 방법이 있습니다. 첫 번째는 데이터셋이 기반하고 있는 주제에 대한 도메인 지식(전문 지식)을 활용하여 누락된 값을 대략적으로 추정하는 것입니다.\n", "\n", "`isnull`을 사용하여 직접 누락된 값을 채울 수도 있지만, 채워야 할 값이 많을 경우 이는 번거로울 수 있습니다. 데이터 과학에서 이러한 작업이 매우 흔하기 때문에 pandas는 `fillna`를 제공합니다. 이 함수는 누락된 값을 사용자가 선택한 값으로 대체한 `Series` 또는 `DataFrame`의 복사본을 반환합니다. 실제로 어떻게 작동하는지 보기 위해 또 다른 예제 `Series`를 만들어 보겠습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "CE8S7louLezV" }, "source": [ "### 범주형 데이터(비수치형)\n", "먼저 비수치형 데이터를 살펴보겠습니다. 데이터셋에는 범주형 데이터를 가진 열이 있습니다. 예를 들어, 성별, 참 또는 거짓 등이 있습니다.\n", "\n", "이러한 경우 대부분, 누락된 값을 해당 열의 `최빈값(mode)`으로 대체합니다. 예를 들어, 데이터 포인트가 100개 있고, 그중 90개가 참(True), 8개가 거짓(False), 2개가 응답하지 않았다고 가정해봅시다. 이 경우, 전체 열을 고려하여 누락된 2개를 참(True)으로 채울 수 있습니다.\n", "\n", "여기에서도 도메인 지식을 활용할 수 있습니다. 최빈값으로 채우는 예를 살펴보겠습니다.\n" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "MY5faq4yLdpQ", "outputId": "19ab472e-1eed-4de8-f8a7-db2a3af3cb1a" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
012True
134None
256False
378True
4910True
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 1 2 True\n", "1 3 4 None\n", "2 5 6 False\n", "3 7 8 True\n", "4 9 10 True" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mode = pd.DataFrame([[1,2,\"True\"],\n", " [3,4,None],\n", " [5,6,\"False\"],\n", " [7,8,\"True\"],\n", " [9,10,\"True\"]])\n", "\n", "fill_with_mode" ] }, { "cell_type": "markdown", "metadata": { "id": "MLAoMQOfNPlA" }, "source": [] }, { "cell_type": "code", "execution_count": 29, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "WKy-9Y2tN5jv", "outputId": "8da9fa16-e08c-447e-dea1-d4b1db2feebf" }, "outputs": [ { "data": { "text/plain": [ "True 3\n", "False 1\n", "Name: 2, dtype: int64" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mode[2].value_counts()" ] }, { "cell_type": "markdown", "metadata": { "id": "6iNz_zG_OKrx" }, "source": [] }, { "cell_type": "code", "execution_count": 30, "metadata": { "id": "TxPKteRvNPOs" }, "outputs": [], "source": [ "fill_with_mode[2].fillna('True',inplace=True)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "tvas7c9_OPWE", "outputId": "ec3c8e44-d644-475e-9e22-c65101965850" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
012True
134True
256False
378True
4910True
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 1 2 True\n", "1 3 4 True\n", "2 5 6 False\n", "3 7 8 True\n", "4 9 10 True" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mode" ] }, { "cell_type": "markdown", "metadata": { "id": "SktitLxxOR16" }, "source": [ "우리가 볼 수 있듯이, null 값이 대체되었습니다. 말할 필요도 없이, 우리는 `'True'` 대신에 어떤 것이든 쓸 수 있었고 그것이 대체되었을 것입니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "heYe1I0dOmQ_" }, "source": [ "### 숫자 데이터\n", "이제 숫자 데이터로 넘어가 보겠습니다. 여기에서는 결측값을 대체하는 두 가지 일반적인 방법이 있습니다:\n", "\n", "1. 행의 중앙값으로 대체하기\n", "2. 행의 평균값으로 대체하기\n", "\n", "데이터가 이상치로 인해 왜곡된 경우에는 중앙값으로 대체합니다. 이는 중앙값이 이상치에 강건하기 때문입니다.\n", "\n", "데이터가 정규화된 경우에는 평균값을 사용할 수 있습니다. 이 경우 평균값과 중앙값이 거의 비슷하기 때문입니다.\n", "\n", "먼저, 정규 분포를 따르는 열을 선택하고 해당 열의 평균값으로 결측값을 채워 보겠습니다.\n" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "09HM_2feOj5Y", "outputId": "7e309013-9acb-411c-9b06-4de795bbeeff" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
0-2.001
1-1.023
2NaN45
31.067
42.089
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 -2.0 0 1\n", "1 -1.0 2 3\n", "2 NaN 4 5\n", "3 1.0 6 7\n", "4 2.0 8 9" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mean = pd.DataFrame([[-2,0,1],\n", " [-1,2,3],\n", " [np.nan,4,5],\n", " [1,6,7],\n", " [2,8,9]])\n", "\n", "fill_with_mean" ] }, { "cell_type": "markdown", "metadata": { "id": "ka7-wNfzSxbx" }, "source": [ "열의 평균은\n" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "XYtYEf5BSxFL", "outputId": "68a78d18-f0e5-4a9a-a959-2c3676a57c70" }, "outputs": [ { "data": { "text/plain": [ "0.0" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.mean(fill_with_mean[0])" ] }, { "cell_type": "markdown", "metadata": { "id": "oBSRGxKRS39K" }, "source": [] }, { "cell_type": "code", "execution_count": 34, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "FzncQLmuS5jh", "outputId": "00f74fff-01f4-4024-c261-796f50f01d2e" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
0-2.001
1-1.023
20.045
31.067
42.089
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 -2.0 0 1\n", "1 -1.0 2 3\n", "2 0.0 4 5\n", "3 1.0 6 7\n", "4 2.0 8 9" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_mean[0].fillna(np.mean(fill_with_mean[0]),inplace=True)\n", "fill_with_mean" ] }, { "cell_type": "markdown", "metadata": { "id": "CwpVFCrPTC5z" }, "source": [ "누락된 값이 평균으로 대체된 것을 볼 수 있습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "jIvF13a1i00Z" }, "source": [ "이제 다른 데이터프레임을 시도해보고, 이번에는 None 값을 해당 열의 중앙값으로 대체하겠습니다.\n" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "DA59Bqo3jBYZ", "outputId": "85dae6ec-7394-4c36-fda0-e04769ec4a32" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
0-20.01
1-12.03
20NaN5
316.07
428.09
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 -2 0.0 1\n", "1 -1 2.0 3\n", "2 0 NaN 5\n", "3 1 6.0 7\n", "4 2 8.0 9" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_median = pd.DataFrame([[-2,0,1],\n", " [-1,2,3],\n", " [0,np.nan,5],\n", " [1,6,7],\n", " [2,8,9]])\n", "\n", "fill_with_median" ] }, { "cell_type": "markdown", "metadata": { "id": "mM1GpXYmjHnc" }, "source": [ "두 번째 열의 중앙값은\n" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "uiDy5v3xjHHX", "outputId": "564b6b74-2004-4486-90d4-b39330a64b88" }, "outputs": [ { "data": { "text/plain": [ "4.0" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_median[1].median()" ] }, { "cell_type": "markdown", "metadata": { "id": "z9PLF75Jj_1s" }, "source": [] }, { "cell_type": "code", "execution_count": 37, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "lFKbOxCMkBbg", "outputId": "a8bd18fb-2765-47d4-e5fe-e965f57ed1f4" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
0-20.01
1-12.03
204.05
316.07
428.09
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 -2 0.0 1\n", "1 -1 2.0 3\n", "2 0 4.0 5\n", "3 1 6.0 7\n", "4 2 8.0 9" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fill_with_median[1].fillna(fill_with_median[1].median(),inplace=True)\n", "fill_with_median" ] }, { "cell_type": "markdown", "metadata": { "id": "8JtQ53GSkKWC" }, "source": [ "NaN 값이 열의 중앙값으로 대체된 것을 볼 수 있습니다.\n" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "0ybtWLDdgRsG", "outputId": "b8c238ef-6024-4ee2-be2b-aa1f0fcac61d", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "a 1.0\n", "b NaN\n", "c 2.0\n", "d NaN\n", "e 3.0\n", "dtype: float64" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example5 = pd.Series([1, np.nan, 2, None, 3], index=list('abcde'))\n", "example5" ] }, { "cell_type": "markdown", "metadata": { "id": "yrsigxRggRsH" }, "source": [ "null 항목을 모두 하나의 값, 예를 들어 `0`으로 채울 수 있습니다.\n" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "KXMIPsQdgRsH", "outputId": "aeedfa0a-a421-4c2f-cb0d-183ce8f0c91d", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "a 1.0\n", "b 0.0\n", "c 2.0\n", "d 0.0\n", "e 3.0\n", "dtype: float64" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example5.fillna(0)" ] }, { "cell_type": "markdown", "metadata": { "id": "RRlI5f_hkfKe" }, "source": [ "> 주요 요점:\n", "1. 누락된 값을 채우는 작업은 데이터가 적거나 누락된 데이터를 채울 전략이 있을 때 수행해야 합니다.\n", "2. 도메인 지식을 활용하여 누락된 값을 근사치로 채울 수 있습니다.\n", "3. 범주형 데이터의 경우, 대부분 누락된 값은 해당 열의 최빈값으로 대체됩니다.\n", "4. 수치형 데이터의 경우, 누락된 값은 일반적으로 평균(정규화된 데이터셋의 경우) 또는 열의 중앙값으로 채워집니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "FI9MmqFJgRsH" }, "source": [ "### 운동:\n" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": true, "id": "af-ezpXdgRsH", "trusted": false }, "outputs": [], "source": [ "# What happens if you try to fill null values with a string, like ''?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "kq3hw1kLgRsI" }, "source": [] }, { "cell_type": "code", "execution_count": 41, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "vO3BuNrggRsI", "outputId": "e2bc591b-0b48-4e88-ee65-754f2737c196", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "a 1.0\n", "b 1.0\n", "c 2.0\n", "d 2.0\n", "e 3.0\n", "dtype: float64" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example5.fillna(method='ffill')" ] }, { "cell_type": "markdown", "metadata": { "id": "nDXeYuHzgRsI" }, "source": [ "다음 유효 값을 뒤로 전파하여 null을 채우기 위해 **백필**할 수도 있습니다:\n" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "4M5onHcEgRsI", "outputId": "8f32b185-40dd-4a9f-bd85-54d6b6a414fe", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "a 1.0\n", "b 2.0\n", "c 2.0\n", "d 3.0\n", "e 3.0\n", "dtype: float64" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example5.fillna(method='bfill')" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "id": "MbBzTom5gRsI" }, "source": [ "데이터프레임에서도 동일하게 작동하지만, null 값을 채울 축(`axis`)을 지정할 수도 있습니다.\n" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "aRpIvo4ZgRsI", "outputId": "905a980a-a808-4eca-d0ba-224bd7d85955", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
01.0NaN7NaN
12.05.08NaN
2NaN6.09NaN
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "0 1.0 NaN 7 NaN\n", "1 2.0 5.0 8 NaN\n", "2 NaN 6.0 9 NaN" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "VM1qtACAgRsI", "outputId": "71f2ad28-9b4e-4ff4-f5c3-e731eb489ade", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
01.01.07.07.0
12.05.08.08.0
2NaN6.09.09.0
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "0 1.0 1.0 7.0 7.0\n", "1 2.0 5.0 8.0 8.0\n", "2 NaN 6.0 9.0 9.0" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.fillna(method='ffill', axis=1)" ] }, { "cell_type": "markdown", "metadata": { "id": "ZeMc-I1EgRsI" }, "source": [ "이전 값이 전진 채우기에 사용할 수 없을 때, null 값이 그대로 유지됩니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "eeAoOU0RgRsJ" }, "source": [ "### 운동:\n" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": true, "id": "e8S-CjW8gRsJ", "trusted": false }, "outputs": [], "source": [ "# What output does example4.fillna(method='bfill', axis=1) produce?\n", "# What about example4.fillna(method='ffill') or example4.fillna(method='bfill')?\n", "# Can you think of a longer code snippet to write that can fill all of the null values in example4?\n" ] }, { "cell_type": "markdown", "metadata": { "id": "YHgy0lIrgRsJ" }, "source": [ "당신은 `fillna`를 사용하는 방법에 대해 창의적으로 접근할 수 있습니다. 예를 들어, `example4`를 다시 살펴보되, 이번에는 `DataFrame`의 모든 값의 평균으로 누락된 값을 채워봅시다:\n" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "OtYVErEygRsJ", "outputId": "708b1e67-45ca-44bf-a5ee-8b2de09ece73", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0123
01.05.57NaN
12.05.08NaN
21.56.09NaN
\n", "
" ], "text/plain": [ " 0 1 2 3\n", "0 1.0 5.5 7 NaN\n", "1 2.0 5.0 8 NaN\n", "2 1.5 6.0 9 NaN" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example4.fillna(example4.mean())" ] }, { "cell_type": "markdown", "metadata": { "id": "zpMvCkLSgRsJ" }, "source": [ "3열은 여전히 값이 없는 상태입니다: 기본 방향은 행 단위로 값을 채우는 것입니다.\n", "\n", "> **핵심 요점:** 데이터셋에서 누락된 값을 처리하는 방법은 여러 가지가 있습니다. 어떤 특정 전략을 사용할지(값을 제거하거나, 대체하거나, 또는 어떻게 대체할지)는 해당 데이터의 특성에 따라 결정되어야 합니다. 데이터셋을 다루고 상호작용할수록 누락된 값을 처리하는 방법에 대한 감각이 더욱 발전할 것입니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "bauDnESIl9FH" }, "source": [ "### 범주형 데이터 인코딩\n", "\n", "머신러닝 모델은 숫자와 모든 형태의 숫자 데이터만 처리할 수 있습니다. 모델은 '예'와 '아니오'의 차이를 이해할 수 없지만, 0과 1의 차이는 구분할 수 있습니다. 따라서 누락된 값을 채운 후, 모델이 이해할 수 있도록 범주형 데이터를 숫자 형태로 인코딩해야 합니다.\n", "\n", "인코딩은 두 가지 방법으로 수행할 수 있습니다. 다음에서 이를 논의하겠습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "uDq9SxB7mu5i" }, "source": [ "**레이블 인코딩**\n", "\n", "레이블 인코딩은 각 범주를 숫자로 변환하는 방식입니다. 예를 들어, 항공사 승객 데이터셋이 있고, 해당 데이터셋에 ['business class', 'economy class', 'first class']와 같은 클래스가 포함된 열이 있다고 가정해봅시다. 이 열에 레이블 인코딩을 적용하면 [0, 1, 2]로 변환됩니다. 코드 예제를 통해 이를 살펴보겠습니다. 앞으로의 노트북에서 `scikit-learn`을 학습할 예정이므로 여기서는 사용하지 않겠습니다.\n" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 235 }, "id": "1vGz7uZyoWHL", "outputId": "9e252855-d193-4103-a54d-028ea7787b34" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
IDclass
010business class
120first class
230economy class
340economy class
450economy class
560business class
\n", "
" ], "text/plain": [ " ID class\n", "0 10 business class\n", "1 20 first class\n", "2 30 economy class\n", "3 40 economy class\n", "4 50 economy class\n", "5 60 business class" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "label = pd.DataFrame([\n", " [10,'business class'],\n", " [20,'first class'],\n", " [30, 'economy class'],\n", " [40, 'economy class'],\n", " [50, 'economy class'],\n", " [60, 'business class']\n", "],columns=['ID','class'])\n", "label" ] }, { "cell_type": "markdown", "metadata": { "id": "IDHnkwTYov-h" }, "source": [ "1열에 대해 라벨 인코딩을 수행하려면, 각 클래스에서 숫자로의 매핑을 먼저 설명한 후 교체해야 합니다.\n" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 235 }, "id": "ZC5URJG3o1ES", "outputId": "aab0f1e7-e0f3-4c14-8459-9f9168c85437" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
IDclass
0100
1202
2301
3401
4501
5600
\n", "
" ], "text/plain": [ " ID class\n", "0 10 0\n", "1 20 2\n", "2 30 1\n", "3 40 1\n", "4 50 1\n", "5 60 0" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class_labels = {'business class':0,'economy class':1,'first class':2}\n", "label['class'] = label['class'].replace(class_labels)\n", "label" ] }, { "cell_type": "markdown", "metadata": { "id": "ftnF-TyapOPt" }, "source": [ "우리가 예상했던 결과와 일치하는 것을 볼 수 있습니다. 그렇다면, 라벨 인코딩은 언제 사용해야 할까요? 라벨 인코딩은 다음과 같은 경우에 사용됩니다:\n", "1. 카테고리의 수가 많을 때\n", "2. 카테고리가 순서대로 정렬되어 있을 때\n" ] }, { "cell_type": "markdown", "metadata": { "id": "eQPAPVwsqWT7" }, "source": [ "**원-핫 인코딩**\n", "\n", "원-핫 인코딩은 또 다른 유형의 인코딩 방식입니다. 이 방식에서는 열의 각 카테고리가 별도의 열로 추가되며, 각 데이터 포인트는 해당 카테고리를 포함하는지 여부에 따라 0 또는 1을 받게 됩니다. 따라서 서로 다른 카테고리가 n개 있다면, 데이터프레임에 n개의 열이 추가됩니다.\n", "\n", "예를 들어, 같은 비행기 클래스 예제를 사용해 보겠습니다. 카테고리는 ['business class', 'economy class', 'first class']였습니다. 원-핫 인코딩을 수행하면, 데이터셋에 다음 세 개의 열이 추가됩니다: ['class_business class', 'class_economy class', 'class_first class'].\n" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 235 }, "id": "ZM0eVh0ArKUL", "outputId": "83238a76-b3a5-418d-c0b6-605b02b6891b" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
IDclass
010business class
120first class
230economy class
340economy class
450economy class
560business class
\n", "
" ], "text/plain": [ " ID class\n", "0 10 business class\n", "1 20 first class\n", "2 30 economy class\n", "3 40 economy class\n", "4 50 economy class\n", "5 60 business class" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "one_hot = pd.DataFrame([\n", " [10,'business class'],\n", " [20,'first class'],\n", " [30, 'economy class'],\n", " [40, 'economy class'],\n", " [50, 'economy class'],\n", " [60, 'business class']\n", "],columns=['ID','class'])\n", "one_hot" ] }, { "cell_type": "markdown", "metadata": { "id": "aVnZ7paDrWmb" }, "source": [ "1열에 대해 원-핫 인코딩을 수행합시다\n" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "id": "RUPxf7egrYKr" }, "outputs": [], "source": [ "one_hot_data = pd.get_dummies(one_hot,columns=['class'])" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 235 }, "id": "TM37pHsFr4ge", "outputId": "7be15f53-79b2-447a-979c-822658339a9e" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
IDclass_business classclass_economy classclass_first class
010100
120001
230010
340010
450010
560100
\n", "
" ], "text/plain": [ " ID class_business class class_economy class class_first class\n", "0 10 1 0 0\n", "1 20 0 0 1\n", "2 30 0 1 0\n", "3 40 0 1 0\n", "4 50 0 1 0\n", "5 60 1 0 0" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "one_hot_data" ] }, { "cell_type": "markdown", "metadata": { "id": "_zXRLOjXujdA" }, "source": [ "각 원-핫 인코딩된 열은 해당 데이터 포인트에 그 범주가 존재하는지 여부를 지정하는 0 또는 1을 포함합니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "bDnC4NQOu0qr" }, "source": [ "언제 원-핫 인코딩을 사용하나요? 원-핫 인코딩은 다음 경우 중 하나 또는 둘 모두에 사용됩니다:\n", "\n", "1. 카테고리 수와 데이터셋 크기가 작은 경우.\n", "2. 카테고리가 특정한 순서를 따르지 않는 경우.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "XnUmci_4uvyu" }, "source": [ "> 주요 요점:\n", "1. 인코딩은 비숫자 데이터를 숫자 데이터로 변환하기 위해 수행됩니다.\n", "2. 인코딩에는 라벨 인코딩과 원핫 인코딩 두 가지 유형이 있으며, 데이터셋의 요구에 따라 수행할 수 있습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "K8UXOJYRgRsJ" }, "source": [ "## 중복 데이터 제거하기\n", "\n", "> **학습 목표:** 이 절의 끝까지 학습하면 DataFrame에서 중복 값을 식별하고 제거하는 데 익숙해질 것입니다.\n", "\n", "누락된 데이터 외에도 실제 데이터셋에서는 중복된 데이터를 자주 접하게 됩니다. 다행히도 pandas는 중복 항목을 감지하고 제거하는 간단한 방법을 제공합니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "qrEG-Wa0gRsJ" }, "source": [ "### 중복 항목 식별: `duplicated`\n", "\n", "pandas의 `duplicated` 메서드를 사용하면 중복 값을 쉽게 확인할 수 있습니다. 이 메서드는 `DataFrame`에서 이전 항목과 중복된 항목인지 여부를 나타내는 Boolean 마스크를 반환합니다. 이를 직접 확인하기 위해 또 다른 예제 `DataFrame`을 만들어 보겠습니다.\n" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 204 }, "id": "ZLu6FEnZgRsJ", "outputId": "376512d1-d842-4db1-aea3-71052aeeecaf", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lettersnumbers
0A1
1B2
2A1
3B3
4B3
\n", "
" ], "text/plain": [ " letters numbers\n", "0 A 1\n", "1 B 2\n", "2 A 1\n", "3 B 3\n", "4 B 3" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example6 = pd.DataFrame({'letters': ['A','B'] * 2 + ['B'],\n", " 'numbers': [1, 2, 1, 3, 3]})\n", "example6" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "cIduB5oBgRsK", "outputId": "3da27b3d-4d69-4e1d-bb52-0af21bae87f2", "trusted": false }, "outputs": [ { "data": { "text/plain": [ "0 False\n", "1 False\n", "2 True\n", "3 False\n", "4 True\n", "dtype: bool" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example6.duplicated()" ] }, { "cell_type": "markdown", "metadata": { "id": "0eDRJD4SgRsK" }, "source": [ "### 중복 제거: `drop_duplicates`\n", "`drop_duplicates`는 `duplicated` 값이 모두 `False`인 데이터를 복사하여 반환합니다:\n" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 142 }, "id": "w_YPpqIqgRsK", "outputId": "ac66bd2f-8671-4744-87f5-8b8d96553dea", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lettersnumbers
0A1
1B2
3B3
\n", "
" ], "text/plain": [ " letters numbers\n", "0 A 1\n", "1 B 2\n", "3 B 3" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example6.drop_duplicates()" ] }, { "cell_type": "markdown", "metadata": { "id": "69AqoCZAgRsK" }, "source": [ "`duplicated`와 `drop_duplicates`는 기본적으로 모든 열을 고려하지만, `DataFrame`에서 특정 열만 검사하도록 지정할 수 있습니다:\n" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 111 }, "id": "BILjDs67gRsK", "outputId": "ef6dcc08-db8b-4352-c44e-5aa9e2bec0d3", "trusted": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lettersnumbers
0A1
1B2
\n", "
" ], "text/plain": [ " letters numbers\n", "0 A 1\n", "1 B 2" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example6.drop_duplicates(['letters'])" ] }, { "cell_type": "markdown", "metadata": { "id": "GvX4og1EgRsL" }, "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**면책 조항**: \n이 문서는 AI 번역 서비스 [Co-op Translator](https://github.com/Azure/co-op-translator)를 사용하여 번역되었습니다. 정확성을 위해 최선을 다하고 있으나, 자동 번역에는 오류나 부정확성이 포함될 수 있습니다. 원본 문서의 원어 버전을 권위 있는 출처로 간주해야 합니다. 중요한 정보의 경우, 전문적인 인간 번역을 권장합니다. 이 번역 사용으로 인해 발생하는 오해나 잘못된 해석에 대해 책임을 지지 않습니다.\n" ] } ], "metadata": { "anaconda-cloud": {}, "colab": { "name": "notebook.ipynb", "provenance": [] }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" }, "coopTranslator": { "original_hash": "8533b3a2230311943339963fc7f04c21", "translation_date": "2025-09-01T22:08:08+00:00", "source_file": "2-Working-With-Data/08-data-preparation/notebook.ipynb", "language_code": "ko" } }, "nbformat": 4, "nbformat_minor": 0 }