Example - Merge & Melt
Table of Contents
- 1) รวมตารางข้อมูลแผนที่กับข้อมูลที่ต้องการ (merge)
- 1.1) อ่านข้อมูลแผนที่
- 1.2) อ่านข้อมูลที่ต้องการ
- 1.3) การรวมตาราง (merge)
- 1.4) การเลือกตารางเฉพาะปีพร้อมกับ copy
- 1.5) ทำซ้ำโดยระบุ thousands เพิ่ม
- 2) ตัวอย่างการใช้ melt
รันคำสั่งด้านล่างเพื่อโหลดไฟล์ที่จำเป็นสำหรับตัวอย่างนี้
!wget https://bit.ly/thaigeojson
!wget https://data.go.th/dataset/c6fb53a5-4d9d-4f21-84a7-9662b25af9c3/resource/225ff892-3874-4072-9787-a2c30128e3f7/download/stat_c.txt
ตัวอย่างนี้จะเน้นแสดงรวมการลองผิดลองถูกทั้งหมด จะแตกต่างจากที่เรียนใน lab ก่อน ๆ ซึ่งเน้นแสดงแนวทางที่ถูกต้องเป็นหลัก
1) รวมตารางข้อมูลแผนที่กับข้อมูลที่ต้องการ (merge)
1.1) อ่านข้อมูลแผนที่
เริ่มที่จะรวมตารางข้อมูลอื่นก่อนเป็นตัวอย่างแรก
import pandas as pd
import geopandas as gpd
import plotly.express as px
df = gpd.read_file('thaigeojson')
df.head()
code | name | tname | area | geometry | |
---|---|---|---|---|---|
0 | 10 | Bangkok | กรุงเทพมหานคร | 1568.95 | POLYGON ((100.85537 13.69198, 100.71321 13.711... |
1 | 11 | Samut Prakan | สมุทรปราการ | 960.09 | POLYGON ((100.85537 13.69198, 100.94033 13.657... |
2 | 12 | Nonthaburi | นนทบุรี | 633.25 | POLYGON ((100.35029 14.11371, 100.33659 14.060... |
3 | 13 | Pathum Thani | ปทุมธานี | 1520.06 | POLYGON ((100.91242 14.21391, 100.90529 13.955... |
4 | 14 | Phra Nakhon Si Ayutthaya | พระนครศรีอยุธยา | 2534.07 | POLYGON ((100.59405 14.65593, 100.57436 14.589... |
fig = px.choropleth(
df,
geojson=df.geometry,
locations=df.index,
color="area",
hover_data=["tname", "area"])
fig.update_geos(fitbounds="locations")
1.2) อ่านข้อมูลที่ต้องการ
df2 = pd.read_csv("stat_c.txt")
df2.head()
YYMM|CC-CODE|CC-DESC|RCODE-CODE|RCODE-DESC|CCAATT-CODE|CCAATT-DESC|CCAATTMM-CODE|CCAATTMM-DESC|MALE|FEMALE|TOTAL|HOUSE| | ||||||||
---|---|---|---|---|---|---|---|---|
6312|0|ทั่วประเทศ|0| |0| |0| |32 | 375 | 532|33 | 811 | 195|66 | 186 | 727|27 | 224 | 743| |
6312|10|กรุงเทพมหานคร|0| |0| |0| |2 | 625 | 938|2 | 962 | 284|5 | 588 | 222|3 | 103 | 483| |
6312|11|จังหวัดสมุทรปราการ |0| |0| |0| |644 | 516|706 | 963|1 | 351 | 479|711 | 804| | NaN | NaN | NaN |
6312|12|จังหวัดนนทบุรี |0| |0| |0| |594 | 308|682 | 437|1 | 276 | 745|718 | 799| | NaN | NaN | NaN |
6312|13|จังหวัดปทุมธานี |0| |0| |0| |557 | 752|618 | 660|1 | 176 | 412|642 | 474| | NaN | NaN | NaN |
ตารางถูกอ่านออกมาแปลกๆ ออกมาเป็นหนึ่งคอลัมภ์ แต่สังเกตว่าแต่ละช่องน่าจะถูกกั้นด้วย |
แทนที่จะเป็น ,
ตามปกติ เลยแก้ด้วยการใช้คำสั่ง sep="|"
sep
ย่อมาจาก separator หรือตัวกั้น
df3 = pd.read_csv("stat_c.txt", sep="|")
df3.head()
YYMM | CC-CODE | CC-DESC | RCODE-CODE | RCODE-DESC | CCAATT-CODE | CCAATT-DESC | CCAATTMM-CODE | CCAATTMM-DESC | MALE | FEMALE | TOTAL | HOUSE | Unnamed: 13 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 6312 | 0 | ทั่วประเทศ | 0 | 0 | 0 | 32,375,532 | 33,811,195 | 66,186,727 | 27,224,743 | NaN | |||
1 | 6312 | 10 | กรุงเทพมหานคร | 0 | 0 | 0 | 2,625,938 | 2,962,284 | 5,588,222 | 3,103,483 | NaN | |||
2 | 6312 | 11 | จังหวัดสมุทรปราการ | 0 | 0 | 0 | 644,516 | 706,963 | 1,351,479 | 711,804 | NaN | |||
3 | 6312 | 12 | จังหวัดนนทบุรี | 0 | 0 | 0 | 594,308 | 682,437 | 1,276,745 | 718,799 | NaN | |||
4 | 6312 | 13 | จังหวัดปทุมธานี | 0 | 0 | 0 | 557,752 | 618,660 | 1,176,412 | 642,474 | NaN |
1.3) การรวมตาราง (merge)
ทำการรวมสองตารางด้วยคำสั่ง merge
โดยอิงจากคอลัมภ์ left_on
และ right_on
โดยสองคอลัมภ์นี้ต้องมีค่าเท่ากันจึงจะรวมตารางกัน
df4 = df.merge(df3, left_on="tname", right_on="CC-DESC")
df4.head()
code | name | tname | area | geometry | YYMM | CC-CODE | CC-DESC | RCODE-CODE | RCODE-DESC | CCAATT-CODE | CCAATT-DESC | CCAATTMM-CODE | CCAATTMM-DESC | MALE | FEMALE | TOTAL | HOUSE | Unnamed: 13 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 10 | Bangkok | กรุงเทพมหานคร | 1568.95 | POLYGON ((100.85537 13.69198, 100.71321 13.711... | 6312 | 10 | กรุงเทพมหานคร | 0 | 0 | 0 | 2,625,938 | 2,962,284 | 5,588,222 | 3,103,483 | NaN | |||
1 | 10 | Bangkok | กรุงเทพมหานคร | 1568.95 | POLYGON ((100.85537 13.69198, 100.71321 13.711... | 6212 | 10 | กรุงเทพมหานคร | 0 | 0 | 0 | 2,669,316 | 2,996,948 | 5,666,264 | 3,041,115 | NaN | |||
2 | 10 | Bangkok | กรุงเทพมหานคร | 1568.95 | POLYGON ((100.85537 13.69198, 100.71321 13.711... | 6112 | 10 | กรุงเทพมหานคร | 0 | 0 | 0 | 2,679,453 | 2,997,195 | 5,676,648 | 2,959,524 | NaN | |||
3 | 10 | Bangkok | กรุงเทพมหานคร | 1568.95 | POLYGON ((100.85537 13.69198, 100.71321 13.711... | 6012 | 10 | กรุงเทพมหานคร | 0 | 0 | 0 | 2,682,962 | 2,999,453 | 5,682,415 | 2,887,274 | NaN | |||
4 | 10 | Bangkok | กรุงเทพมหานคร | 1568.95 | POLYGON ((100.85537 13.69198, 100.71321 13.711... | 5912 | 10 | กรุงเทพมหานคร | 0 | 0 | 0 | 2,687,253 | 2,999,393 | 5,686,646 | 2,816,711 | NaN |
ผลลัพธ์มีความแปลกเนื่องจากมีกรุงเทพมหานครหลายแถว เลยต้องย้อนกลับไปดูข้อมูลเดิม
df3.columns
Index(['YYMM', 'CC-CODE', 'CC-DESC', 'RCODE-CODE', 'RCODE-DESC', 'CCAATT-CODE',
'CCAATT-DESC', 'CCAATTMM-CODE', 'CCAATTMM-DESC', 'MALE', 'FEMALE',
'TOTAL', 'HOUSE', 'Unnamed: 13'],
dtype='object')
ดูจากคอลัมภ์ทั้งหมดแล้วเห็นว่ามีคอลัมภ์ YYMM
ซึ่งน่าจะเป็นเดือนและปีที่นับสถิติ เลยดูข้อมูลคอลัมภ์นี้เพิ่ม
df3["YYMM"].describe()
count 2166.000000
mean 4966.155125
std 808.636295
min 3612.000000
25% 4312.000000
50% 5012.000000
75% 5712.000000
max 6312.000000
Name: YYMM, dtype: float64
df3["YYMM"].value_counts()
5512 78
5612 78
6312 78
6212 78
6112 78
6012 78
5912 78
5812 78
5712 78
5412 78
3912 77
3812 77
3712 77
3612 77
4112 77
4212 77
5312 77
5212 77
5112 77
5012 77
4912 77
4812 77
4712 77
4612 77
4512 77
4412 77
4312 77
4012 77
Name: YYMM, dtype: int64
1.4) การเลือกตารางเฉพาะปีพร้อมกับ copy
เห็นว่าข้อมูลจะมีหลายปี ตัดสินใจเลือกเฉพาะปี 6312
มาใช้ก่อน โดยใช้ .copy()
เพื่อคัดลอกเป็นตารางใหม่
df5 = df3[df3["YYMM"] == 6312].copy()
df5.head()
YYMM | CC-CODE | CC-DESC | RCODE-CODE | RCODE-DESC | CCAATT-CODE | CCAATT-DESC | CCAATTMM-CODE | CCAATTMM-DESC | MALE | FEMALE | TOTAL | HOUSE | Unnamed: 13 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 6312 | 0 | ทั่วประเทศ | 0 | 0 | 0 | 32,375,532 | 33,811,195 | 66,186,727 | 27,224,743 | NaN | |||
1 | 6312 | 10 | กรุงเทพมหานคร | 0 | 0 | 0 | 2,625,938 | 2,962,284 | 5,588,222 | 3,103,483 | NaN | |||
2 | 6312 | 11 | จังหวัดสมุทรปราการ | 0 | 0 | 0 | 644,516 | 706,963 | 1,351,479 | 711,804 | NaN | |||
3 | 6312 | 12 | จังหวัดนนทบุรี | 0 | 0 | 0 | 594,308 | 682,437 | 1,276,745 | 718,799 | NaN | |||
4 | 6312 | 13 | จังหวัดปทุมธานี | 0 | 0 | 0 | 557,752 | 618,660 | 1,176,412 | 642,474 | NaN |
df6 = df.merge(df5, left_on="tname", right_on="CC-DESC")
df6.head()
code | name | tname | area | geometry | YYMM | CC-CODE | CC-DESC | RCODE-CODE | RCODE-DESC | CCAATT-CODE | CCAATT-DESC | CCAATTMM-CODE | CCAATTMM-DESC | MALE | FEMALE | TOTAL | HOUSE | Unnamed: 13 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 10 | Bangkok | กรุงเทพมหานคร | 1568.95 | POLYGON ((100.85537 13.69198, 100.71321 13.711... | 6312 | 10 | กรุงเทพมหานคร | 0 | 0 | 0 | 2,625,938 | 2,962,284 | 5,588,222 | 3,103,483 | NaN |
ผลลัพธ์ก็ยังแปลกอยู่ดีเพราะเหลือแต่กรุงเทพมหานคร เลยกลับไปสังเกตดู df5
เลยเห็นว่าชื่อจังหวัดอื่นๆ นอกจากกรุงเทพจะมีคำว่าจังหวัดอยู่สำหรับคอลัมภ์ CC-DESC
แต่จะไม่มีคำว่าจังหวัดในคอลัมภ์ tname
เลยต้องแก้ไข
cc_desc = df5["CC-DESC"].values
new_cc_desc = []
for x in cc_desc:
if x.startswith("จังหวัด"):
y = x.replace("จังหวัด", "")
new_cc_desc.append(y)
else:
new_cc_desc.append(x)
new_cc_desc
['ทั่วประเทศ',
'กรุงเทพมหานคร',
'สมุทรปราการ ',
'นนทบุรี ',
'ปทุมธานี ',
'พระนครศรีอยุธยา ',
'อ่างทอง ',
'ลพบุรี ',
'สิงห์บุรี ',
'ชัยนาท ',
'สระบุรี ',
'ชลบุรี ',
'ระยอง ',
'จันทบุรี ',
'ตราด ',
'ฉะเชิงเทรา ',
'ปราจีนบุรี ',
'นครนายก ',
'สระแก้ว ',
'นครราชสีมา ',
'บุรีรัมย์ ',
'สุรินทร์ ',
'ศรีสะเกษ ',
'อุบลราชธานี ',
'ยโสธร ',
'ชัยภูมิ ',
'อำนาจเจริญ ',
'บึงกาฬ ',
'หนองบัวลำภู ',
'ขอนแก่น ',
'อุดรธานี ',
'เลย ',
'หนองคาย ',
'มหาสารคาม ',
'ร้อยเอ็ด ',
'กาฬสินธุ์ ',
'สกลนคร ',
'นครพนม ',
'มุกดาหาร ',
'เชียงใหม่ ',
'ลำพูน ',
'ลำปาง ',
'อุตรดิตถ์ ',
'แพร่ ',
'น่าน ',
'พะเยา ',
'เชียงราย ',
'แม่ฮ่องสอน ',
'นครสวรรค์ ',
'อุทัยธานี ',
'กำแพงเพชร ',
'ตาก ',
'สุโขทัย ',
'พิษณุโลก ',
'พิจิตร ',
'เพชรบูรณ์ ',
'ราชบุรี ',
'กาญจนบุรี ',
'สุพรรณบุรี ',
'นครปฐม ',
'สมุทรสาคร ',
'สมุทรสงคราม ',
'เพชรบุรี ',
'ประจวบคีรีขันธ์ ',
'นครศรีธรรมราช ',
'กระบี่ ',
'พังงา ',
'ภูเก็ต ',
'สุราษฎร์ธานี ',
'ระนอง ',
'ชุมพร ',
'สงขลา ',
'สตูล ',
'ตรัง ',
'พัทลุง ',
'ปัตตานี ',
'ยะลา ',
'นราธิวาส ']
แก้ไขแล้วตั้งคอลัมภ์ใหม่ เป็นชื่อ NEW-CC-DESC
df5["NEW-CC-DESC"] = new_cc_desc
df7 = df.merge(df5, left_on="tname", right_on="NEW-CC-DESC")
df7.head()
code | name | tname | area | geometry | YYMM | CC-CODE | CC-DESC | RCODE-CODE | RCODE-DESC | CCAATT-CODE | CCAATT-DESC | CCAATTMM-CODE | CCAATTMM-DESC | MALE | FEMALE | TOTAL | HOUSE | Unnamed: 13 | NEW-CC-DESC | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 10 | Bangkok | กรุงเทพมหานคร | 1568.95 | POLYGON ((100.85537 13.69198, 100.71321 13.711... | 6312 | 10 | กรุงเทพมหานคร | 0 | 0 | 0 | 2,625,938 | 2,962,284 | 5,588,222 | 3,103,483 | NaN | กรุงเทพมหานคร |
รวมแล้วก็ยังมีแต่กรุงเทพมหานครอยู่ดี ซึ่งแปลก ถ้าย้อนกลับไปดู new_cc_desc
จะเห็นว่าชื่อจังหวัดยังมีเว้นวรรคตามหลังทำให้ชื่อจังหวัดอื่นยังไม่ตรงกันเป๊ะๆ ต้องแก้ไข
new2_cc_desc = []
for x in cc_desc:
x = x.strip()
if x.startswith("จังหวัด"):
y = x.replace("จังหวัด", "")
new2_cc_desc.append(y)
else:
new2_cc_desc.append(x)
new2_cc_desc
['ทั่วประเทศ',
'กรุงเทพมหานคร',
'สมุทรปราการ',
'นนทบุรี',
'ปทุมธานี',
'พระนครศรีอยุธยา',
'อ่างทอง',
'ลพบุรี',
'สิงห์บุรี',
'ชัยนาท',
'สระบุรี',
'ชลบุรี',
'ระยอง',
'จันทบุรี',
'ตราด',
'ฉะเชิงเทรา',
'ปราจีนบุรี',
'นครนายก',
'สระแก้ว',
'นครราชสีมา',
'บุรีรัมย์',
'สุรินทร์',
'ศรีสะเกษ',
'อุบลราชธานี',
'ยโสธร',
'ชัยภูมิ',
'อำนาจเจริญ',
'บึงกาฬ',
'หนองบัวลำภู',
'ขอนแก่น',
'อุดรธานี',
'เลย',
'หนองคาย',
'มหาสารคาม',
'ร้อยเอ็ด',
'กาฬสินธุ์',
'สกลนคร',
'นครพนม',
'มุกดาหาร',
'เชียงใหม่',
'ลำพูน',
'ลำปาง',
'อุตรดิตถ์',
'แพร่',
'น่าน',
'พะเยา',
'เชียงราย',
'แม่ฮ่องสอน',
'นครสวรรค์',
'อุทัยธานี',
'กำแพงเพชร',
'ตาก',
'สุโขทัย',
'พิษณุโลก',
'พิจิตร',
'เพชรบูรณ์',
'ราชบุรี',
'กาญจนบุรี',
'สุพรรณบุรี',
'นครปฐม',
'สมุทรสาคร',
'สมุทรสงคราม',
'เพชรบุรี',
'ประจวบคีรีขันธ์',
'นครศรีธรรมราช',
'กระบี่',
'พังงา',
'ภูเก็ต',
'สุราษฎร์ธานี',
'ระนอง',
'ชุมพร',
'สงขลา',
'สตูล',
'ตรัง',
'พัทลุง',
'ปัตตานี',
'ยะลา',
'นราธิวาส']
df5["NEW2-CC-DESC"] = new2_cc_desc
df8 = df.merge(df5, left_on="tname", right_on="NEW2-CC-DESC")
df8.head()
code | name | tname | area | geometry | YYMM | CC-CODE | CC-DESC | RCODE-CODE | RCODE-DESC | ... | CCAATT-DESC | CCAATTMM-CODE | CCAATTMM-DESC | MALE | FEMALE | TOTAL | HOUSE | Unnamed: 13 | NEW-CC-DESC | NEW2-CC-DESC | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 10 | Bangkok | กรุงเทพมหานคร | 1568.95 | POLYGON ((100.85537 13.69198, 100.71321 13.711... | 6312 | 10 | กรุงเทพมหานคร | 0 | ... | 0 | 2,625,938 | 2,962,284 | 5,588,222 | 3,103,483 | NaN | กรุงเทพมหานคร | กรุงเทพมหานคร | |||
1 | 11 | Samut Prakan | สมุทรปราการ | 960.09 | POLYGON ((100.85537 13.69198, 100.94033 13.657... | 6312 | 11 | จังหวัดสมุทรปราการ | 0 | ... | 0 | 644,516 | 706,963 | 1,351,479 | 711,804 | NaN | สมุทรปราการ | สมุทรปราการ | |||
2 | 12 | Nonthaburi | นนทบุรี | 633.25 | POLYGON ((100.35029 14.11371, 100.33659 14.060... | 6312 | 12 | จังหวัดนนทบุรี | 0 | ... | 0 | 594,308 | 682,437 | 1,276,745 | 718,799 | NaN | นนทบุรี | นนทบุรี | |||
3 | 13 | Pathum Thani | ปทุมธานี | 1520.06 | POLYGON ((100.91242 14.21391, 100.90529 13.955... | 6312 | 13 | จังหวัดปทุมธานี | 0 | ... | 0 | 557,752 | 618,660 | 1,176,412 | 642,474 | NaN | ปทุมธานี | ปทุมธานี | |||
4 | 14 | Phra Nakhon Si Ayutthaya | พระนครศรีอยุธยา | 2534.07 | POLYGON ((100.59405 14.65593, 100.57436 14.589... | 6312 | 14 | จังหวัดพระนครศรีอยุธยา | 0 | ... | 0 | 393,551 | 425,537 | 819,088 | 336,357 | NaN | พระนครศรีอยุธยา | พระนครศรีอยุธยา |
5 rows × 21 columns
ดูน่าจะรอดแล้วสำหรับการรวมตาราง ก็ลองเอามาพลอตเลย
fig = px.choropleth(
df8,
geojson=df8.geometry,
locations=df8.index,
color="HOUSE",
hover_data=["tname", "HOUSE"])
fig.update_geos(fitbounds="locations")