You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Data-Science-For-Beginners/translations/th/2-Working-With-Data/08-data-preparation/notebook.ipynb

4241 lines
156 KiB

{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "rQ8UhzFpgRra"
},
"source": [
"# การเตรียมข้อมูล\n",
"\n",
"[แหล่งโน้ตบุ๊กต้นฉบับจาก *Data Science: Introduction to Machine Learning for Data Science Python and Machine Learning Studio โดย Lee Stott*](https://github.com/leestott/intro-Datascience/blob/master/Course%20Materials/4-Cleaning_and_Manipulating-Reference.ipynb)\n",
"\n",
"## การสำรวจข้อมูล `DataFrame`\n",
"\n",
"> **เป้าหมายการเรียนรู้:** เมื่อจบส่วนย่อยนี้ คุณควรจะสามารถค้นหาข้อมูลทั่วไปเกี่ยวกับข้อมูลที่จัดเก็บใน pandas DataFrames ได้อย่างคล่องแคล่ว\n",
"\n",
"เมื่อคุณโหลดข้อมูลเข้าสู่ pandas ข้อมูลนั้นมักจะอยู่ในรูปแบบ `DataFrame` อย่างไรก็ตาม หากชุดข้อมูลใน `DataFrame` ของคุณมี 60,000 แถวและ 400 คอลัมน์ คุณจะเริ่มต้นทำความเข้าใจข้อมูลที่คุณกำลังทำงานด้วยได้อย่างไร? โชคดีที่ pandas มีเครื่องมือที่สะดวกในการดูข้อมูลโดยรวมของ `DataFrame` อย่างรวดเร็ว รวมถึงแถวแรกและแถวสุดท้ายบางส่วน\n",
"\n",
"เพื่อสำรวจฟังก์ชันนี้ เราจะนำเข้าไลบรารี scikit-learn ของ Python และใช้ชุดข้อมูลที่โด่งดังซึ่งนักวิทยาศาสตร์ข้อมูลทุกคนเคยเห็นมาหลายร้อยครั้ง: ชุดข้อมูล *Iris* ของนักชีววิทยาชาวอังกฤษ Ronald Fisher ที่ใช้ในงานวิจัยปี 1936 ของเขา \"The use of multiple measurements in taxonomic problems\":\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` ในที่นี้เป็นแอตทริบิวต์ของกรอบข้อมูล ไม่ใช่ฟังก์ชัน ซึ่งเป็นเหตุผลว่าทำไมมันจึงไม่มีวงเล็บตามท้าย\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "d3AZKs0PinGP"
},
"source": [
"### `DataFrame.columns`\n",
"ตอนนี้เรามาดูข้อมูลใน 4 คอลัมน์กันดีกว่า แต่ละคอลัมน์แสดงถึงอะไรบ้าง? คุณสมบัติ `columns` จะให้ชื่อของคอลัมน์ใน dataframe กับเรา\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": [
"<class 'pandas.core.frame.DataFrame'>\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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>sepal length (cm)</th>\n",
" <th>sepal width (cm)</th>\n",
" <th>petal length (cm)</th>\n",
" <th>petal width (cm)</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>count</th>\n",
" <td>150.000000</td>\n",
" <td>150.000000</td>\n",
" <td>150.000000</td>\n",
" <td>150.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>mean</th>\n",
" <td>5.843333</td>\n",
" <td>3.057333</td>\n",
" <td>3.758000</td>\n",
" <td>1.199333</td>\n",
" </tr>\n",
" <tr>\n",
" <th>std</th>\n",
" <td>0.828066</td>\n",
" <td>0.435866</td>\n",
" <td>1.765298</td>\n",
" <td>0.762238</td>\n",
" </tr>\n",
" <tr>\n",
" <th>min</th>\n",
" <td>4.300000</td>\n",
" <td>2.000000</td>\n",
" <td>1.000000</td>\n",
" <td>0.100000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25%</th>\n",
" <td>5.100000</td>\n",
" <td>2.800000</td>\n",
" <td>1.600000</td>\n",
" <td>0.300000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>50%</th>\n",
" <td>5.800000</td>\n",
" <td>3.000000</td>\n",
" <td>4.350000</td>\n",
" <td>1.300000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>75%</th>\n",
" <td>6.400000</td>\n",
" <td>3.300000</td>\n",
" <td>5.100000</td>\n",
" <td>1.800000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>max</th>\n",
" <td>7.900000</td>\n",
" <td>4.400000</td>\n",
" <td>6.900000</td>\n",
" <td>2.500000</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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",
"ด้วยฟังก์ชันและคุณสมบัติทั้งหมดที่กล่าวมาข้างต้น เราได้มุมมองระดับสูงของชุดข้อมูลแล้ว เรารู้ว่ามีจำนวนจุดข้อมูลเท่าไร มีจำนวนฟีเจอร์เท่าไร ประเภทข้อมูลของแต่ละฟีเจอร์คืออะไร และจำนวนค่าที่ไม่เป็น null สำหรับแต่ละฟีเจอร์\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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>sepal length (cm)</th>\n",
" <th>sepal width (cm)</th>\n",
" <th>petal length (cm)</th>\n",
" <th>petal width (cm)</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>5.1</td>\n",
" <td>3.5</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4.9</td>\n",
" <td>3.0</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4.7</td>\n",
" <td>3.2</td>\n",
" <td>1.3</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4.6</td>\n",
" <td>3.1</td>\n",
" <td>1.5</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5.0</td>\n",
" <td>3.6</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>sepal length (cm)</th>\n",
" <th>sepal width (cm)</th>\n",
" <th>petal length (cm)</th>\n",
" <th>petal width (cm)</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>145</th>\n",
" <td>6.7</td>\n",
" <td>3.0</td>\n",
" <td>5.2</td>\n",
" <td>2.3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>146</th>\n",
" <td>6.3</td>\n",
" <td>2.5</td>\n",
" <td>5.0</td>\n",
" <td>1.9</td>\n",
" </tr>\n",
" <tr>\n",
" <th>147</th>\n",
" <td>6.5</td>\n",
" <td>3.0</td>\n",
" <td>5.2</td>\n",
" <td>2.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>148</th>\n",
" <td>6.2</td>\n",
" <td>3.4</td>\n",
" <td>5.4</td>\n",
" <td>2.3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>149</th>\n",
" <td>5.9</td>\n",
" <td>3.0</td>\n",
" <td>5.1</td>\n",
" <td>1.8</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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 floating-point และใช้เพื่อระบุค่าที่หายไปในตัวเลขแบบทศนิยมเท่านั้น\n",
"\n",
"สำหรับค่าที่หายไปที่ไม่ใช่ตัวเลขแบบทศนิยม Pandas ใช้ Python `None` object แม้ว่ามันอาจดูสับสนที่คุณจะพบค่าที่แตกต่างกันสองแบบที่บอกสิ่งเดียวกัน แต่มีเหตุผลทางโปรแกรมที่ดีสำหรับการออกแบบเช่นนี้ และในทางปฏิบัติ การเลือกใช้วิธีนี้ช่วยให้ Pandas สามารถจัดการกับกรณีส่วนใหญ่ได้อย่างมีประสิทธิภาพ อย่างไรก็ตาม ทั้ง `None` และ `NaN` มีข้อจำกัดที่คุณต้องระวังเกี่ยวกับวิธีการใช้งานของมัน\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "lOHqUlZFgRr5"
},
"source": [
"### `None`: ข้อมูลที่ขาดหายซึ่งไม่ใช่ float\n",
"เนื่องจาก `None` มาจาก Python จึงไม่สามารถใช้งานในอาร์เรย์ของ NumPy และ pandas ที่ไม่ได้มีชนิดข้อมูลเป็น `'object'` ได้ โปรดจำไว้ว่า อาร์เรย์ของ 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": [
"ความจริงเกี่ยวกับการแปลงประเภทข้อมูลแบบ upcast มีผลกระทบสองประการตามมา ประการแรก การดำเนินการจะถูกดำเนินการในระดับของโค้ด Python ที่ถูกตีความแทนที่จะเป็นโค้ด NumPy ที่ถูกคอมไพล์ โดยพื้นฐานแล้ว หมายความว่าการดำเนินการใด ๆ ที่เกี่ยวข้องกับ `Series` หรือ `DataFrames` ที่มี `None` อยู่ในนั้นจะทำงานช้าลง แม้ว่าคุณอาจจะไม่สังเกตเห็นผลกระทบด้านประสิทธิภาพนี้ แต่สำหรับชุดข้อมูลขนาดใหญ่ มันอาจกลายเป็นปัญหาได้\n",
"\n",
"ผลกระทบประการที่สองเกิดจากผลกระทบแรก เนื่องจาก `None` โดยพื้นฐานแล้วจะดึง `Series` หรือ `DataFrame` กลับเข้าสู่โลกของ Python แบบดั้งเดิม การใช้การรวมข้อมูลของ NumPy/pandas เช่น `sum()` หรือ `min()` บนอาร์เรย์ที่มีค่า ``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<ipython-input-10-ce9901ad18bd>\u001b[0m in \u001b[0;36m<module>\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": [
"**ข้อสำคัญ**: การบวก (และการดำเนินการอื่นๆ) ระหว่างจำนวนเต็มและค่า `None` ไม่สามารถกำหนดได้ ซึ่งอาจจำกัดสิ่งที่คุณสามารถทำได้กับชุดข้อมูลที่มีค่าเหล่านี้\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pWvVHvETgRr9"
},
"source": [
"### `NaN`: ค่าลอยตัวที่หายไป\n",
"\n",
"แตกต่างจาก `None`, NumPy (และ pandas ด้วย) รองรับ `NaN` สำหรับการดำเนินการแบบเวกเตอร์ที่รวดเร็วและ ufuncs ข่าวร้ายคือการคำนวณใดๆ ที่ทำกับ `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`: ค่าที่เป็น null ใน pandas\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` ได้อย่างยืดหยุ่น เนื่องจากคุณสมบัติการออกแบบนี้ จึงอาจเป็นประโยชน์ที่จะมองว่า `None` และ `NaN` เป็นสองรูปแบบที่แตกต่างกันของ \"null\" ใน pandas จริง ๆ แล้ว วิธีการหลักบางอย่างที่คุณจะใช้ในการจัดการค่าที่หายไปใน pandas ก็สะท้อนแนวคิดนี้ในชื่อของมัน:\n",
"\n",
"- `isnull()`: สร้างหน้ากาก Boolean เพื่อระบุค่าที่หายไป\n",
"- `notnull()`: ตรงข้ามกับ `isnull()`\n",
"- `dropna()`: ส่งคืนข้อมูลที่ถูกกรอง\n",
"- `fillna()`: ส่งคืนสำเนาของข้อมูลที่มีการเติมหรือประมาณค่าที่หายไป\n",
"\n",
"วิธีการเหล่านี้เป็นสิ่งสำคัญที่คุณควรเรียนรู้และทำความคุ้นเคย ดังนั้นเรามาทำความเข้าใจแต่ละวิธีอย่างละเอียดกันเถอะ\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Yh5ifd9FgRsB"
},
"source": [
"### การตรวจจับค่าที่เป็น null\n",
"\n",
"เมื่อเราเข้าใจถึงความสำคัญของค่าที่หายไปแล้ว ขั้นตอนต่อไปคือการตรวจจับค่าที่หายไปในชุดข้อมูลของเรา ก่อนที่จะจัดการกับมัน \n",
"ทั้ง `isnull()` และ `notnull()` เป็นวิธีหลักในการตรวจจับข้อมูลที่เป็น null โดยทั้งสองจะคืนค่ามาสก์แบบ 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` จะเป็นค่าศูนย์ในเชิงคณิตศาสตร์ แต่ก็ยังถือว่าเป็นจำนวนเต็มที่สมบูรณ์ และ pandas ก็จัดการกับมันในลักษณะนั้น ส่วน `''` นั้นมีความละเอียดอ่อนกว่าเล็กน้อย แม้ว่าเราใช้มันใน Section 1 เพื่อแสดงถึงค่าข้อความว่างเปล่า แต่จริง ๆ แล้วมันเป็นวัตถุประเภทข้อความ และไม่ได้เป็นตัวแทนของ null ในมุมมองของ pandas\n",
"\n",
"ตอนนี้ ลองเปลี่ยนมุมมองและใช้วิธีการเหล่านี้ในลักษณะที่ใกล้เคียงกับการใช้งานจริง คุณสามารถใช้ Boolean masks โดยตรงเป็นดัชนีของ ``Series`` หรือ ``DataFrame`` ซึ่งมีประโยชน์เมื่อคุณต้องการทำงานกับค่าที่หายไป (หรือค่าที่มีอยู่) แบบแยกส่วน\n",
"\n",
"หากเราต้องการจำนวนรวมของค่าที่หายไป เราสามารถใช้การบวกค่าทั้งหมดใน mask ที่สร้างขึ้นโดยวิธี `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",
"> **เป้าหมายการเรียนรู้:** เมื่อจบหัวข้อนี้ คุณควรทราบวิธีและเวลาที่เหมาะสมในการแทนที่หรือลบค่าที่เป็น null จาก DataFrames\n",
"\n",
"โมเดล Machine Learning ไม่สามารถจัดการกับข้อมูลที่หายไปได้ด้วยตัวเอง ดังนั้นก่อนที่จะส่งข้อมูลเข้าสู่โมเดล เราจำเป็นต้องจัดการกับค่าที่หายไปเหล่านี้\n",
"\n",
"วิธีการจัดการกับข้อมูลที่หายไปมีผลกระทบที่ละเอียดอ่อน ซึ่งอาจส่งผลต่อการวิเคราะห์ขั้นสุดท้ายและผลลัพธ์ในโลกความเป็นจริง\n",
"\n",
"มีวิธีหลัก ๆ สองวิธีในการจัดการกับข้อมูลที่หายไป:\n",
"\n",
"1. ลบแถวที่มีค่าที่หายไป\n",
"2. แทนค่าที่หายไปด้วยค่าบางอย่าง\n",
"\n",
"เราจะพูดถึงทั้งสองวิธีนี้ รวมถึงข้อดีและข้อเสียของแต่ละวิธีอย่างละเอียด\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3VaYC1TvgRsD"
},
"source": [
"### การลบค่าที่เป็น null\n",
"\n",
"ปริมาณข้อมูลที่เราส่งต่อไปยังโมเดลมีผลโดยตรงต่อประสิทธิภาพของมัน การลบค่าที่เป็น null หมายความว่าเรากำลังลดจำนวนจุดข้อมูล และด้วยเหตุนี้จึงลดขนาดของชุดข้อมูล ดังนั้นจึงแนะนำให้ลบแถวที่มีค่าที่เป็น null เมื่อชุดข้อมูลมีขนาดค่อนข้างใหญ่\n",
"\n",
"อีกกรณีหนึ่งอาจเป็นแถวหรือคอลัมน์ที่มีค่าหายไปจำนวนมาก ในกรณีนี้อาจลบออกได้ เพราะมันจะไม่เพิ่มคุณค่ามากนักให้กับการวิเคราะห์ของเรา เนื่องจากข้อมูลส่วนใหญ่ในแถวหรือคอลัมน์นั้นหายไป\n",
"\n",
"นอกเหนือจากการระบุค่าที่หายไปแล้ว pandas ยังมีวิธีที่สะดวกในการลบค่าที่เป็น null จาก `Series` และ `DataFrame` เพื่อดูตัวอย่างการใช้งานนี้ เรามาดูที่ `example3` ฟังก์ชัน `DataFrame.dropna()` ช่วยในการลบแถวที่มีค่าที่เป็น null\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",
"เนื่องจาก DataFrames มีสองมิติ จึงมีตัวเลือกมากขึ้นสำหรับการลบข้อมูล\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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1.0</td>\n",
" <td>NaN</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2.0</td>\n",
" <td>5.0</td>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>NaN</td>\n",
" <td>6.0</td>\n",
" <td>9</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"(คุณสังเกตไหมว่า pandas ได้เปลี่ยนประเภทข้อมูลของสองคอลัมน์เป็น float เพื่อรองรับค่า `NaN`?)\n",
"\n",
"คุณไม่สามารถลบค่าหนึ่งค่าออกจาก `DataFrame` ได้ ดังนั้นคุณต้องลบทั้งแถวหรือทั้งคอลัมน์ ขึ้นอยู่กับสิ่งที่คุณกำลังทำ คุณอาจต้องการทำอย่างใดอย่างหนึ่ง และ pandas ก็มีตัวเลือกให้คุณทั้งสองแบบ เนื่องจากในงานด้านวิทยาศาสตร์ข้อมูล คอลัมน์มักจะแทนตัวแปร และแถวแทนการสังเกตข้อมูล คุณจึงมีแนวโน้มที่จะลบแถวของข้อมูลมากกว่า โดยค่าเริ่มต้นของ `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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2.0</td>\n",
" <td>5.0</td>\n",
" <td>8</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>9</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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 หลายค่า หรือแม้กระทั่งทั้งหมด คุณสามารถกำหนดการตั้งค่าเหล่านี้ใน `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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" <th>3</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1.0</td>\n",
" <td>NaN</td>\n",
" <td>7</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2.0</td>\n",
" <td>5.0</td>\n",
" <td>8</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>NaN</td>\n",
" <td>6.0</td>\n",
" <td>9</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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` ให้คุณควบคุมได้ละเอียดมากขึ้น: คุณกำหนดจำนวนค่าที่ *ไม่เป็นค่าว่าง* ที่แถวหรือคอลัมน์ต้องมีเพื่อที่จะถูกเก็บไว้:\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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" <th>3</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2.0</td>\n",
" <td>5.0</td>\n",
" <td>8</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"ที่นี่ แถวแรกและแถวสุดท้ายถูกลบออก เนื่องจากมีเพียงสองค่าที่ไม่เป็นค่าว่างเท่านั้น\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mCcxLGyUgRsG"
},
"source": [
"### การเติมค่าที่เป็น null\n",
"\n",
"บางครั้งการเติมค่าที่หายไปด้วยค่าที่อาจเป็นไปได้ก็สมเหตุสมผล มีเทคนิคบางอย่างในการเติมค่าที่เป็น null วิธีแรกคือการใช้ความรู้เฉพาะด้าน (ความรู้เกี่ยวกับหัวข้อที่ชุดข้อมูลนั้นอ้างอิง) เพื่อประมาณค่าที่หายไป\n",
"\n",
"คุณสามารถใช้ `isnull` เพื่อทำสิ่งนี้โดยตรง แต่บางครั้งอาจเป็นงานที่ยุ่งยาก โดยเฉพาะอย่างยิ่งถ้าคุณมีค่าที่ต้องเติมจำนวนมาก เนื่องจากนี่เป็นงานที่พบได้บ่อยในวิทยาศาสตร์ข้อมูล pandas จึงมีฟังก์ชัน `fillna` ซึ่งจะคืนค่าชุด `Series` หรือ `DataFrame` ที่มีค่าที่หายไปถูกแทนที่ด้วยค่าที่คุณเลือก ลองสร้างตัวอย่าง `Series` อีกตัวเพื่อดูว่ามันทำงานอย่างไรในทางปฏิบัติ\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "CE8S7louLezV"
},
"source": [
"### ข้อมูลประเภทหมวดหมู่ (ไม่ใช่ตัวเลข)\n",
"ก่อนอื่นเรามาพิจารณาข้อมูลที่ไม่ใช่ตัวเลขกัน ในชุดข้อมูล เรามีคอลัมน์ที่มีข้อมูลประเภทหมวดหมู่ เช่น เพศ, จริงหรือเท็จ เป็นต้น\n",
"\n",
"ในกรณีส่วนใหญ่ เราจะแทนค่าที่หายไปด้วย `mode` ของคอลัมน์นั้น เช่น หากเรามีข้อมูล 100 จุด และ 90 จุดระบุว่า จริง, 8 จุดระบุว่า เท็จ และ 2 จุดไม่ได้กรอกข้อมูล เราสามารถเติมค่าที่หายไป 2 จุดนั้นด้วย \"จริง\" โดยพิจารณาจากทั้งคอลัมน์\n",
"\n",
"อีกครั้ง เราสามารถใช้ความรู้เฉพาะด้านในกรณีนี้ได้ ลองพิจารณาตัวอย่างการเติมค่าด้วย mode\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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>2</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3</td>\n",
" <td>4</td>\n",
" <td>None</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>5</td>\n",
" <td>6</td>\n",
" <td>False</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>7</td>\n",
" <td>8</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>9</td>\n",
" <td>10</td>\n",
" <td>True</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"ตอนนี้ มาหาค่าฐานนิยมก่อนที่จะเติมค่า `None` ด้วยค่าฐานนิยม\n"
]
},
{
"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": [
"ดังนั้น เราจะแทนที่ None ด้วย True\n"
]
},
{
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>2</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3</td>\n",
" <td>4</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>5</td>\n",
" <td>6</td>\n",
" <td>False</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>7</td>\n",
" <td>8</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>9</td>\n",
" <td>10</td>\n",
" <td>True</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>-2.0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>-1.0</td>\n",
" <td>2</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>NaN</td>\n",
" <td>4</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1.0</td>\n",
" <td>6</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2.0</td>\n",
" <td>8</td>\n",
" <td>9</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"เติมด้วยค่าเฉลี่ย\n"
]
},
{
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>-2.0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>-1.0</td>\n",
" <td>2</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0.0</td>\n",
" <td>4</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1.0</td>\n",
" <td>6</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2.0</td>\n",
" <td>8</td>\n",
" <td>9</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"ตอนนี้ลองใช้ DataFrame อีกตัวหนึ่ง และคราวนี้เราจะแทนค่าที่เป็น 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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>-2</td>\n",
" <td>0.0</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>-1</td>\n",
" <td>2.0</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0</td>\n",
" <td>NaN</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1</td>\n",
" <td>6.0</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2</td>\n",
" <td>8.0</td>\n",
" <td>9</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"การเติมด้วยค่ามัธยฐาน\n"
]
},
{
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>-2</td>\n",
" <td>0.0</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>-1</td>\n",
" <td>2.0</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0</td>\n",
" <td>4.0</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1</td>\n",
" <td>6.0</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2</td>\n",
" <td>8.0</td>\n",
" <td>9</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"คุณสามารถเติมค่าที่ว่างทั้งหมดด้วยค่าเดียว เช่น `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": [
"คุณสามารถ **เติมค่าด้วยค่าก่อนหน้า** สำหรับค่าที่เป็น null ซึ่งหมายถึงการใช้ค่าที่ถูกต้องล่าสุดเพื่อเติมค่าที่เป็น null:\n"
]
},
{
"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": [
"ดังที่คุณอาจเดาได้ สิ่งนี้ทำงานในลักษณะเดียวกันกับ DataFrames แต่คุณยังสามารถระบุ `axis` ที่จะใช้เติมค่าที่เป็น null ได้:\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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" <th>3</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1.0</td>\n",
" <td>NaN</td>\n",
" <td>7</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2.0</td>\n",
" <td>5.0</td>\n",
" <td>8</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>NaN</td>\n",
" <td>6.0</td>\n",
" <td>9</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" <th>3</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1.0</td>\n",
" <td>1.0</td>\n",
" <td>7.0</td>\n",
" <td>7.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2.0</td>\n",
" <td>5.0</td>\n",
" <td>8.0</td>\n",
" <td>8.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>NaN</td>\n",
" <td>6.0</td>\n",
" <td>9.0</td>\n",
" <td>9.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" <th>3</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1.0</td>\n",
" <td>5.5</td>\n",
" <td>7</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2.0</td>\n",
" <td>5.0</td>\n",
" <td>8</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1.5</td>\n",
" <td>6.0</td>\n",
" <td>9</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>ID</th>\n",
" <th>class</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>10</td>\n",
" <td>business class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>20</td>\n",
" <td>first class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>30</td>\n",
" <td>economy class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>40</td>\n",
" <td>economy class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>50</td>\n",
" <td>economy class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>60</td>\n",
" <td>business class</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"ในการเข้ารหัสป้ายกำกับในคอลัมน์แรก เราต้องอธิบายการจับคู่จากแต่ละคลาสไปยังตัวเลขก่อนที่จะทำการแทนที่\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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>ID</th>\n",
" <th>class</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>10</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>20</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>30</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>40</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>50</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>60</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"**การเข้ารหัสแบบ One Hot Encoding**\n",
"\n",
"การเข้ารหัสอีกประเภทหนึ่งคือ One Hot Encoding ในการเข้ารหัสประเภทนี้ แต่ละหมวดหมู่ของคอลัมน์จะถูกเพิ่มเป็นคอลัมน์แยกต่างหาก และแต่ละข้อมูลจะได้รับค่า 0 หรือ 1 ขึ้นอยู่กับว่ามันมีหมวดหมู่นั้นหรือไม่ ดังนั้น หากมี n หมวดหมู่ที่แตกต่างกัน จะมีการเพิ่มคอลัมน์ n คอลัมน์เข้าไปใน dataframe\n",
"\n",
"ตัวอย่างเช่น ลองพิจารณาตัวอย่างประเภทที่นั่งในเครื่องบิน หมวดหมู่คือ: ['business class', 'economy class', 'first class'] ดังนั้น หากเราทำการเข้ารหัสแบบ One Hot Encoding จะมีการเพิ่มสามคอลัมน์ต่อไปนี้ลงในชุดข้อมูล: ['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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>ID</th>\n",
" <th>class</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>10</td>\n",
" <td>business class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>20</td>\n",
" <td>first class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>30</td>\n",
" <td>economy class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>40</td>\n",
" <td>economy class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>50</td>\n",
" <td>economy class</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>60</td>\n",
" <td>business class</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"ให้เราทำการเข้ารหัสแบบ One Hot Encoding ในคอลัมน์ที่ 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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>ID</th>\n",
" <th>class_business class</th>\n",
" <th>class_economy class</th>\n",
" <th>class_first class</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>10</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>20</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>30</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>40</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>50</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>60</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"แต่ละคอลัมน์ที่ถูกเข้ารหัสแบบ One-hot จะมีค่า 0 หรือ 1 ซึ่งระบุว่าหมวดหมู่นั้นมีอยู่สำหรับจุดข้อมูลนั้นหรือไม่\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bDnC4NQOu0qr"
},
"source": [
"เราควรใช้การเข้ารหัสแบบ One Hot เมื่อใด? การเข้ารหัสแบบ One Hot ถูกใช้ในกรณีใดกรณีหนึ่งหรือทั้งสองกรณีดังต่อไปนี้:\n",
"\n",
"1. เมื่อจำนวนหมวดหมู่และขนาดของชุดข้อมูลมีขนาดเล็ก\n",
"2. เมื่อหมวดหมู่ไม่มีลำดับที่เฉพาะเจาะจง\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XnUmci_4uvyu"
},
"source": [
"> ข้อควรทราบ:\n",
"1. การเข้ารหัสใช้เพื่อแปลงข้อมูลที่ไม่ใช่ตัวเลขให้เป็นข้อมูลตัวเลข\n",
"2. การเข้ารหัสมีสองประเภท ได้แก่ การเข้ารหัสแบบ Label และการเข้ารหัสแบบ One Hot ซึ่งสามารถเลือกใช้ตามความต้องการของชุดข้อมูล\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "K8UXOJYRgRsJ"
},
"source": [
"## การลบข้อมูลซ้ำ\n",
"\n",
"> **เป้าหมายการเรียนรู้:** เมื่อจบหัวข้อนี้ คุณควรจะสามารถระบุและลบค่าที่ซ้ำกันจาก DataFrames ได้อย่างมั่นใจ\n",
"\n",
"นอกจากข้อมูลที่หายไปแล้ว คุณมักจะพบข้อมูลที่ซ้ำกันในชุดข้อมูลจริง โชคดีที่ pandas มีวิธีที่ง่ายในการตรวจจับและลบรายการที่ซ้ำกันออกไป\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "qrEG-Wa0gRsJ"
},
"source": [
"### การระบุค่าซ้ำ: `duplicated`\n",
"\n",
"คุณสามารถตรวจสอบค่าที่ซ้ำกันได้อย่างง่ายดายโดยใช้เมธอด `duplicated` ใน pandas ซึ่งจะคืนค่าหน้ากาก Boolean ที่บ่งบอกว่ารายการใน `DataFrame` เป็นค่าซ้ำของรายการก่อนหน้าหรือไม่ ลองสร้างตัวอย่าง `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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>letters</th>\n",
" <th>numbers</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>A</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>B</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>A</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>B</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>B</td>\n",
" <td>3</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>letters</th>\n",
" <th>numbers</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>A</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>B</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>B</td>\n",
" <td>3</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>letters</th>\n",
" <th>numbers</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>A</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>B</td>\n",
" <td>2</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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": [
"> **ข้อคิดสำคัญ:** การลบข้อมูลที่ซ้ำกันเป็นส่วนสำคัญของแทบทุกโครงการด้านวิทยาศาสตร์ข้อมูล ข้อมูลที่ซ้ำกันสามารถเปลี่ยนผลลัพธ์ของการวิเคราะห์และทำให้คุณได้ผลลัพธ์ที่ไม่ถูกต้อง!\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## การตรวจสอบคุณภาพข้อมูลในโลกจริง\n",
"\n",
"> **เป้าหมายการเรียนรู้:** เมื่อจบส่วนนี้ คุณควรมีความมั่นใจในการตรวจจับและแก้ไขปัญหาคุณภาพข้อมูลทั่วไปในโลกจริง เช่น ค่าประเภทที่ไม่สอดคล้องกัน ค่าตัวเลขที่ผิดปกติ (ค่าผิดปกติ) และข้อมูลซ้ำที่มีความแตกต่างเล็กน้อย\n",
"\n",
"แม้ว่าค่าที่หายไปและข้อมูลซ้ำแบบตรงตัวจะเป็นปัญหาที่พบได้ทั่วไป แต่ชุดข้อมูลในโลกจริงมักมีปัญหาที่ซับซ้อนมากขึ้น:\n",
"\n",
"1. **ค่าประเภทที่ไม่สอดคล้องกัน**: หมวดหมู่เดียวกันที่สะกดต่างกัน (เช่น \"USA\", \"U.S.A\", \"United States\")\n",
"2. **ค่าตัวเลขที่ผิดปกติ**: ค่าผิดปกติที่รุนแรงซึ่งบ่งบอกถึงข้อผิดพลาดในการป้อนข้อมูล (เช่น อายุ = 999)\n",
"3. **แถวที่เกือบซ้ำกัน**: บันทึกที่แสดงถึงหน่วยเดียวกันแต่มีความแตกต่างเล็กน้อย\n",
"\n",
"มาสำรวจเทคนิคในการตรวจจับและจัดการกับปัญหาเหล่านี้กันเถอะ\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### การสร้างชุดข้อมูลตัวอย่างที่ \"ไม่สะอาด\"\n",
"\n",
"ก่อนอื่น เรามาสร้างชุดข้อมูลตัวอย่างที่มีปัญหาต่างๆ ซึ่งเรามักพบในข้อมูลจริง:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"# Create a sample dataset with quality issues\n",
"dirty_data = pd.DataFrame({\n",
" 'customer_id': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],\n",
" 'name': ['John Smith', 'Jane Doe', 'John Smith', 'Bob Johnson', \n",
" 'Alice Williams', 'Charlie Brown', 'John Smith', 'Eva Martinez',\n",
" 'Bob Johnson', 'Diana Prince', 'Frank Castle', 'Alice Williams'],\n",
" 'age': [25, 32, 25, 45, 28, 199, 25, 31, 45, 27, -5, 28],\n",
" 'country': ['USA', 'UK', 'U.S.A', 'Canada', 'USA', 'United Kingdom',\n",
" 'United States', 'Mexico', 'canada', 'USA', 'UK', 'usa'],\n",
" 'purchase_amount': [100.50, 250.00, 105.00, 320.00, 180.00, 90.00,\n",
" 102.00, 275.00, 325.00, 195.00, 410.00, 185.00]\n",
"})\n",
"\n",
"print(\"Sample 'Dirty' Dataset:\")\n",
"print(dirty_data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. การตรวจจับค่าประเภทที่ไม่สอดคล้องกัน\n",
"\n",
"สังเกตว่าคอลัมน์ `country` มีการแสดงผลหลายรูปแบบสำหรับประเทศเดียวกัน เรามาระบุความไม่สอดคล้องเหล่านี้กัน:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Check unique values in the country column\n",
"print(\"Unique country values:\")\n",
"print(dirty_data['country'].unique())\n",
"print(f\"\\nTotal unique values: {dirty_data['country'].nunique()}\")\n",
"\n",
"# Count occurrences of each variation\n",
"print(\"\\nValue counts:\")\n",
"print(dirty_data['country'].value_counts())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### การทำให้ค่าประเภทเป็นมาตรฐาน\n",
"\n",
"เราสามารถสร้างการแมปเพื่อทำให้ค่าประเภทเหล่านี้เป็นมาตรฐานได้ วิธีง่ายๆ คือการแปลงเป็นตัวพิมพ์เล็กและสร้างพจนานุกรมการแมป:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create a standardization mapping\n",
"country_mapping = {\n",
" 'usa': 'USA',\n",
" 'u.s.a': 'USA',\n",
" 'united states': 'USA',\n",
" 'uk': 'UK',\n",
" 'united kingdom': 'UK',\n",
" 'canada': 'Canada',\n",
" 'mexico': 'Mexico'\n",
"}\n",
"\n",
"# Standardize the country column\n",
"dirty_data['country_clean'] = dirty_data['country'].str.lower().map(country_mapping)\n",
"\n",
"print(\"Before standardization:\")\n",
"print(dirty_data['country'].value_counts())\n",
"print(\"\\nAfter standardization:\")\n",
"print(dirty_data[['country_clean']].value_counts())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**ทางเลือก: การใช้การจับคู่แบบ Fuzzy**\n",
"\n",
"สำหรับกรณีที่ซับซ้อนมากขึ้น เราสามารถใช้การจับคู่สตริงแบบ Fuzzy ด้วยไลบรารี `rapidfuzz` เพื่อช่วยตรวจจับสตริงที่คล้ายกันโดยอัตโนมัติ:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" from rapidfuzz import process, fuzz\n",
"except ImportError:\n",
" print(\"rapidfuzz is not installed. Please install it with 'pip install rapidfuzz' to use fuzzy matching.\")\n",
" process = None\n",
" fuzz = None\n",
"\n",
"# Get unique countries\n",
"unique_countries = dirty_data['country'].unique()\n",
"\n",
"# For each country, find similar matches\n",
"if process is not None and fuzz is not None:\n",
" print(\"Finding similar country names (similarity > 70%):\")\n",
" for country in unique_countries:\n",
" matches = process.extract(country, unique_countries, scorer=fuzz.ratio, limit=3)\n",
" # Filter matches with similarity > 70 and not identical\n",
" similar = [m for m in matches if m[1] > 70 and m[0] != country]\n",
" if similar:\n",
" print(f\"\\n'{country}' is similar to:\")\n",
" for match, score, _ in similar:\n",
" print(f\" - '{match}' (similarity: {score}%)\")\n",
"else:\n",
" print(\"Skipping fuzzy matching because rapidfuzz is not available.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. การตรวจจับค่าตัวเลขที่ผิดปกติ (Outliers)\n",
"\n",
"เมื่อดูที่คอลัมน์ `age` เราพบค่าที่น่าสงสัยบางค่า เช่น 199 และ -5 ลองใช้วิธีทางสถิติเพื่อตรวจจับค่าผิดปกติเหล่านี้กันเถอะ\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Display basic statistics\n",
"print(\"Age column statistics:\")\n",
"print(dirty_data['age'].describe())\n",
"\n",
"# Identify impossible values using domain knowledge\n",
"print(\"\\nRows with impossible age values (< 0 or > 120):\")\n",
"impossible_ages = dirty_data[(dirty_data['age'] < 0) | (dirty_data['age'] > 120)]\n",
"print(impossible_ages[['customer_id', 'name', 'age']])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### การใช้วิธี IQR (Interquartile Range)\n",
"\n",
"วิธี IQR เป็นเทคนิคทางสถิติที่มีความทนทานสำหรับการตรวจจับค่าผิดปกติ ซึ่งมีความไวต่อค่าที่สุดขีดน้อยกว่า:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Calculate IQR for age (excluding impossible values)\n",
"valid_ages = dirty_data[(dirty_data['age'] >= 0) & (dirty_data['age'] <= 120)]['age']\n",
"\n",
"Q1 = valid_ages.quantile(0.25)\n",
"Q3 = valid_ages.quantile(0.75)\n",
"IQR = Q3 - Q1\n",
"\n",
"# Define outlier bounds\n",
"lower_bound = Q1 - 1.5 * IQR\n",
"upper_bound = Q3 + 1.5 * IQR\n",
"\n",
"print(f\"IQR-based outlier bounds for age: [{lower_bound:.2f}, {upper_bound:.2f}]\")\n",
"\n",
"# Identify outliers\n",
"age_outliers = dirty_data[(dirty_data['age'] < lower_bound) | (dirty_data['age'] > upper_bound)]\n",
"print(f\"\\nRows with age outliers:\")\n",
"print(age_outliers[['customer_id', 'name', 'age']])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### การใช้วิธี Z-Score\n",
"\n",
"วิธี Z-Score ใช้ในการระบุค่าผิดปกติโดยอ้างอิงจากจำนวนส่วนเบี่ยงเบนมาตรฐานจากค่าเฉลี่ย:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" from scipy import stats\n",
"except ImportError:\n",
" print(\"scipy is required for Z-score calculation. Please install it with 'pip install scipy' and rerun this cell.\")\n",
"else:\n",
" # Calculate Z-scores for age, handling NaN values\n",
" age_nonan = dirty_data['age'].dropna()\n",
" zscores = np.abs(stats.zscore(age_nonan))\n",
" dirty_data['age_zscore'] = np.nan\n",
" dirty_data.loc[age_nonan.index, 'age_zscore'] = zscores\n",
"\n",
" # Typically, Z-score > 3 indicates an outlier\n",
" print(\"Rows with age Z-score > 3:\")\n",
" zscore_outliers = dirty_data[dirty_data['age_zscore'] > 3]\n",
" print(zscore_outliers[['customer_id', 'name', 'age', 'age_zscore']])\n",
"\n",
" # Clean up the temporary column\n",
" dirty_data = dirty_data.drop('age_zscore', axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### การจัดการค่าผิดปกติ\n",
"\n",
"เมื่อพบค่าผิดปกติ สามารถจัดการได้หลายวิธี:\n",
"1. **ลบออก**: ลบแถวที่มีค่าผิดปกติ (หากเป็นข้อผิดพลาด)\n",
"2. **จำกัดค่า**: แทนที่ด้วยค่าขอบเขต\n",
"3. **แทนที่ด้วย NaN**: ถือว่าเป็นข้อมูลที่หายไปและใช้เทคนิคการเติมข้อมูล\n",
"4. **เก็บไว้**: หากเป็นค่าที่สุดโต่งที่ถูกต้อง\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create a cleaned version by replacing impossible ages with NaN\n",
"dirty_data['age_clean'] = dirty_data['age'].apply(\n",
" lambda x: np.nan if (x < 0 or x > 120) else x\n",
")\n",
"\n",
"print(\"Age column before and after cleaning:\")\n",
"print(dirty_data[['customer_id', 'name', 'age', 'age_clean']])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3. การตรวจจับแถวที่คล้ายกันมาก\n",
"\n",
"สังเกตว่าชุดข้อมูลของเรามีหลายรายการสำหรับ \"John Smith\" ที่มีค่าต่างกันเล็กน้อย ลองมาระบุรายการที่อาจเป็นข้อมูลซ้ำกันโดยอิงจากความคล้ายคลึงของชื่อ\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# First, let's look at exact name matches (ignoring extra whitespace)\n",
"dirty_data['name_normalized'] = dirty_data['name'].str.strip().str.lower()\n",
"\n",
"print(\"Checking for duplicate names:\")\n",
"duplicate_names = dirty_data[dirty_data.duplicated(['name_normalized'], keep=False)]\n",
"print(duplicate_names.sort_values('name_normalized')[['customer_id', 'name', 'age', 'country']])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### การค้นหาข้อมูลซ้ำที่คล้ายกันด้วยการจับคู่แบบคลุมเครือ\n",
"\n",
"สำหรับการตรวจจับข้อมูลซ้ำที่ซับซ้อนมากขึ้น เราสามารถใช้การจับคู่แบบคลุมเครือเพื่อค้นหาชื่อที่คล้ายกัน:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" from rapidfuzz import process, fuzz\n",
"\n",
" # Function to find potential duplicates\n",
" def find_near_duplicates(df, column, threshold=90):\n",
" \"\"\"\n",
" Find near-duplicate entries in a column using fuzzy matching.\n",
" \n",
" Parameters:\n",
" - df: DataFrame\n",
" - column: Column name to check for duplicates\n",
" - threshold: Similarity threshold (0-100)\n",
" \n",
" Returns: List of potential duplicate groups\n",
" \"\"\"\n",
" values = df[column].unique()\n",
" duplicate_groups = []\n",
" checked = set()\n",
" \n",
" for value in values:\n",
" if value in checked:\n",
" continue\n",
" \n",
" # Find similar values\n",
" matches = process.extract(value, values, scorer=fuzz.ratio, limit=len(values))\n",
" similar = [m[0] for m in matches if m[1] >= threshold]\n",
" \n",
" if len(similar) > 1:\n",
" duplicate_groups.append(similar)\n",
" checked.update(similar)\n",
" \n",
" return duplicate_groups\n",
"\n",
" # Find near-duplicate names\n",
" duplicate_groups = find_near_duplicates(dirty_data, 'name', threshold=90)\n",
"\n",
" print(\"Potential duplicate groups:\")\n",
" for i, group in enumerate(duplicate_groups, 1):\n",
" print(f\"\\nGroup {i}:\")\n",
" for name in group:\n",
" matching_rows = dirty_data[dirty_data['name'] == name]\n",
" print(f\" '{name}': {len(matching_rows)} occurrence(s)\")\n",
" for _, row in matching_rows.iterrows():\n",
" print(f\" - Customer {row['customer_id']}: age={row['age']}, country={row['country']}\")\n",
"except ImportError:\n",
" print(\"rapidfuzz is not installed. Skipping fuzzy matching for near-duplicates.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### การจัดการข้อมูลซ้ำ\n",
"\n",
"เมื่อระบุข้อมูลซ้ำได้แล้ว คุณต้องตัดสินใจว่าจะจัดการอย่างไร:\n",
"1. **เก็บรายการแรกที่พบ**: ใช้ `drop_duplicates(keep='first')`\n",
"2. **เก็บรายการสุดท้ายที่พบ**: ใช้ `drop_duplicates(keep='last')`\n",
"3. **รวมข้อมูล**: รวมข้อมูลจากแถวที่ซ้ำกัน\n",
"4. **ตรวจสอบด้วยตนเอง**: ทำเครื่องหมายเพื่อให้มนุษย์ตรวจสอบ\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Example: Remove duplicates based on normalized name, keeping first occurrence\n",
"cleaned_data = dirty_data.drop_duplicates(subset=['name_normalized'], keep='first')\n",
"\n",
"print(f\"Original dataset: {len(dirty_data)} rows\")\n",
"print(f\"After removing name duplicates: {len(cleaned_data)} rows\")\n",
"print(f\"Removed: {len(dirty_data) - len(cleaned_data)} duplicate rows\")\n",
"\n",
"print(\"\\nCleaned dataset:\")\n",
"print(cleaned_data[['customer_id', 'name', 'age', 'country_clean']])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### สรุป: กระบวนการทำความสะอาดข้อมูลแบบครบวงจร\n",
"\n",
"มารวมทุกอย่างเข้าด้วยกันเพื่อสร้างกระบวนการทำความสะอาดข้อมูลที่สมบูรณ์:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def clean_dataset(df):\n",
" \"\"\"\n",
" Comprehensive data cleaning function.\n",
" \"\"\"\n",
" # Create a copy to avoid modifying the original\n",
" cleaned = df.copy()\n",
" \n",
" # 1. Standardize categorical values (country)\n",
" country_mapping = {\n",
" 'usa': 'USA', 'u.s.a': 'USA', 'united states': 'USA',\n",
" 'uk': 'UK', 'united kingdom': 'UK',\n",
" 'canada': 'Canada', 'mexico': 'Mexico'\n",
" }\n",
" cleaned['country'] = cleaned['country'].str.lower().map(country_mapping)\n",
" \n",
" # 2. Clean abnormal age values\n",
" cleaned['age'] = cleaned['age'].apply(\n",
" lambda x: np.nan if (x < 0 or x > 120) else x\n",
" )\n",
" \n",
" # 3. Remove near-duplicate names (normalize whitespace)\n",
" cleaned['name'] = cleaned['name'].str.strip()\n",
" cleaned = cleaned.drop_duplicates(subset=['name'], keep='first')\n",
" \n",
" return cleaned\n",
"\n",
"# Apply the cleaning pipeline\n",
"final_cleaned_data = clean_dataset(dirty_data)\n",
"\n",
"print(\"Before cleaning:\")\n",
"print(f\" Rows: {len(dirty_data)}\")\n",
"print(f\" Unique countries: {dirty_data['country'].nunique()}\")\n",
"print(f\" Invalid ages: {((dirty_data['age'] < 0) | (dirty_data['age'] > 120)).sum()}\")\n",
"\n",
"print(\"\\nAfter cleaning:\")\n",
"print(f\" Rows: {len(final_cleaned_data)}\")\n",
"print(f\" Unique countries: {final_cleaned_data['country'].nunique()}\")\n",
"print(f\" Invalid ages: {((final_cleaned_data['age'] < 0) | (final_cleaned_data['age'] > 120)).sum()}\")\n",
"\n",
"print(\"\\nCleaned dataset:\")\n",
"print(final_cleaned_data[['customer_id', 'name', 'age', 'country', 'purchase_amount']])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 🎯 แบบฝึกหัดท้าทาย\n",
"\n",
"ถึงเวลาของคุณแล้ว! ด้านล่างนี้คือแถวข้อมูลใหม่ที่มีปัญหาด้านคุณภาพหลายจุด คุณสามารถ:\n",
"\n",
"1. ระบุปัญหาทั้งหมดในแถวนี้\n",
"2. เขียนโค้ดเพื่อแก้ไขแต่ละปัญหา\n",
"3. เพิ่มแถวที่แก้ไขแล้วลงในชุดข้อมูล\n",
"\n",
"นี่คือข้อมูลที่มีปัญหา:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# New problematic row\n",
"new_row = pd.DataFrame({\n",
" 'customer_id': [13],\n",
" 'name': [' Diana Prince '], # Extra whitespace\n",
" 'age': [250], # Impossible age\n",
" 'country': ['U.S.A.'], # Inconsistent format\n",
" 'purchase_amount': [150.00]\n",
"})\n",
"\n",
"print(\"New row to clean:\")\n",
"print(new_row)\n",
"\n",
"# TODO: Your code here to clean this row\n",
"# Hints:\n",
"# 1. Strip whitespace from the name\n",
"# 2. Check if the name is a duplicate (Diana Prince already exists)\n",
"# 3. Handle the impossible age value\n",
"# 4. Standardize the country name\n",
"\n",
"# Example solution (uncomment and modify as needed):\n",
"# new_row_cleaned = new_row.copy()\n",
"# new_row_cleaned['name'] = new_row_cleaned['name'].str.strip()\n",
"# new_row_cleaned['age'] = np.nan # Invalid age\n",
"# new_row_cleaned['country'] = 'USA' # Standardized\n",
"# print(\"\\nCleaned row:\")\n",
"# print(new_row_cleaned)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### ประเด็นสำคัญ\n",
"\n",
"1. **หมวดหมู่ที่ไม่สอดคล้องกัน** เป็นเรื่องปกติในข้อมูลจริง ควรตรวจสอบค่าที่ไม่ซ้ำกันและปรับมาตรฐานด้วยการใช้การจับคู่หรือการจับคู่แบบคลุมเครือ\n",
"\n",
"2. **ค่าผิดปกติ** สามารถส่งผลกระทบต่อการวิเคราะห์ได้อย่างมาก ใช้ความรู้เฉพาะด้านร่วมกับวิธีการทางสถิติ (IQR, Z-score) เพื่อตรวจจับค่าผิดปกติ\n",
"\n",
"3. **ข้อมูลที่เกือบซ้ำกัน** ตรวจจับได้ยากกว่าข้อมูลที่ซ้ำกันแบบตรงไปตรงมา ลองใช้การจับคู่แบบคลุมเครือและการปรับข้อมูลให้เป็นมาตรฐาน (เช่น การเปลี่ยนเป็นตัวพิมพ์เล็ก, การลบช่องว่าง) เพื่อช่วยระบุข้อมูลเหล่านี้\n",
"\n",
"4. **การทำความสะอาดข้อมูลเป็นกระบวนการที่ต้องทำซ้ำ** อาจต้องใช้เทคนิคหลายอย่างและตรวจสอบผลลัพธ์ก่อนที่จะสรุปชุดข้อมูลที่ทำความสะอาดแล้ว\n",
"\n",
"5. **บันทึกการตัดสินใจของคุณ** เก็บข้อมูลเกี่ยวกับขั้นตอนการทำความสะอาดที่คุณใช้และเหตุผลที่ทำ เนื่องจากสิ่งนี้สำคัญต่อการทำซ้ำและความโปร่งใส\n",
"\n",
"> **แนวทางปฏิบัติที่ดีที่สุด:** ควรเก็บสำเนาของข้อมูล \"ดิบ\" ไว้เสมอ อย่าทับไฟล์ข้อมูลต้นฉบับของคุณ - สร้างเวอร์ชันที่ทำความสะอาดแล้วพร้อมตั้งชื่อไฟล์ให้ชัดเจน เช่น `data_cleaned.csv`\n"
]
},
{
"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": "6301339d1c9a301b00639c635dc9b731",
"translation_date": "2025-10-03T20:13:34+00:00",
"source_file": "2-Working-With-Data/08-data-preparation/notebook.ipynb",
"language_code": "th"
}
},
"nbformat": 4,
"nbformat_minor": 0
}