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.
4241 lines
156 KiB
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
|
|
} |