Home / Example - Merge & Melt

Example - Merge & Melt

You are not logged in.

If you are a current student, please Log In for full access to this page.

Table of Contents

รันคำสั่งด้านล่างเพื่อโหลดไฟล์ที่จำเป็นสำหรับตัวอย่างนี้

!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) อ่านข้อมูลที่ต้องการ

top

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)

top

ทำการรวมสองตารางด้วยคำสั่ง 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

top

เห็นว่าข้อมูลจะมีหลายปี ตัดสินใจเลือกเฉพาะปี 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")

สังเกตว่าสีตอนนี้เป็นแบบ nominal (เทียบกันไม่ได้) อยู่ น่าจะเป็นเพราะว่าคอลัมน์นี้ยังไม่ใช่ตัวเลข ลองใช้วิธีแปลงค่า astype(int) ดูว่าช่วยไหม

fig = px.choropleth(
    df8, 
    geojson=df8.geometry, 
    locations=df8.index, 
    color=df8["HOUSE"].astype(int), 
    hover_data=["tname", "HOUSE"])

fig.update_geos(fitbounds="locations")
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-25-ecc601cd681d> in <module>
      3     geojson=df8.geometry,
      4     locations=df8.index,
----> 5     color=df8["HOUSE"].astype(int),
      6     hover_data=["tname", "HOUSE"])
      7 


/opt/conda/lib/python3.9/site-packages/pandas/core/generic.py in astype(self, dtype, copy, errors)
   5875         else:
   5876             # else, only a single dtype is given
-> 5877             new_data = self._mgr.astype(dtype=dtype, copy=copy, errors=errors)
   5878             return self._constructor(new_data).__finalize__(self, method="astype")
   5879 


/opt/conda/lib/python3.9/site-packages/pandas/core/internals/managers.py in astype(self, dtype, copy, errors)
    629         self, dtype, copy: bool = False, errors: str = "raise"
    630     ) -> "BlockManager":
--> 631         return self.apply("astype", dtype=dtype, copy=copy, errors=errors)
    632 
    633     def convert(


/opt/conda/lib/python3.9/site-packages/pandas/core/internals/managers.py in apply(self, f, align_keys, ignore_failures, **kwargs)
    425                     applied = b.apply(f, **kwargs)
    426                 else:
--> 427                     applied = getattr(b, f)(**kwargs)
    428             except (TypeError, NotImplementedError):
    429                 if not ignore_failures:


/opt/conda/lib/python3.9/site-packages/pandas/core/internals/blocks.py in astype(self, dtype, copy, errors)
    671             vals1d = values.ravel()
    672             try:
--> 673                 values = astype_nansafe(vals1d, dtype, copy=True)
    674             except (ValueError, TypeError):
    675                 # e.g. astype_nansafe can fail on object-dtype of strings


/opt/conda/lib/python3.9/site-packages/pandas/core/dtypes/cast.py in astype_nansafe(arr, dtype, copy, skipna)
   1072         # work around NumPy brokenness, #1987
   1073         if np.issubdtype(dtype.type, np.integer):
-> 1074             return lib.astype_intsafe(arr.ravel(), dtype).reshape(arr.shape)
   1075 
   1076         # if we have a datetime/timedelta array of objects


pandas/_libs/lib.pyx in pandas._libs.lib.astype_intsafe()


ValueError: invalid literal for int() with base 10: '3,103,483'

ไม่ช่วยอยู่ดี จะเห็นว่าข้อมูลเลขติด , อยู่ ต้องกลับไปแก้ไขตั้งแต่ตอนอ่านข้อมูล

1.5) ทำซ้ำโดยระบุ thousands เพิ่ม

top

df9 = pd.read_csv("stat_c.txt", sep="|", thousands=",")
df9.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 32375532 33811195 66186727 27224743 NaN
1 6312 10 กรุงเทพมหานคร 0 0 0 2625938 2962284 5588222 3103483 NaN
2 6312 11 จังหวัดสมุทรปราการ 0 0 0 644516 706963 1351479 711804 NaN
3 6312 12 จังหวัดนนทบุรี 0 0 0 594308 682437 1276745 718799 NaN
4 6312 13 จังหวัดปทุมธานี 0 0 0 557752 618660 1176412 642474 NaN

ย้อนกลับไปทำตามเดิมทั้งหมด (เลือกปี เปลี่ยนชื่อจังหวัด)

df10 = df9[df9["YYMM"] == 6312].copy()
df10.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 32375532 33811195 66186727 27224743 NaN
1 6312 10 กรุงเทพมหานคร 0 0 0 2625938 2962284 5588222 3103483 NaN
2 6312 11 จังหวัดสมุทรปราการ 0 0 0 644516 706963 1351479 711804 NaN
3 6312 12 จังหวัดนนทบุรี 0 0 0 594308 682437 1276745 718799 NaN
4 6312 13 จังหวัดปทุมธานี 0 0 0 557752 618660 1176412 642474 NaN
cc_desc = df10["CC-DESC"].values
new3_cc_desc = []
for x in cc_desc:
    x = x.strip()
    if x.startswith("จังหวัด"):
        y = x.replace("จังหวัด", "")
        new3_cc_desc.append(y)
    else:
        new3_cc_desc.append(x)
new3_cc_desc
['ทั่วประเทศ',
 'กรุงเทพมหานคร',
 'สมุทรปราการ',
 'นนทบุรี',
 'ปทุมธานี',
 'พระนครศรีอยุธยา',
 'อ่างทอง',
 'ลพบุรี',
 'สิงห์บุรี',
 'ชัยนาท',
 'สระบุรี',
 'ชลบุรี',
 'ระยอง',
 'จันทบุรี',
 'ตราด',
 'ฉะเชิงเทรา',
 'ปราจีนบุรี',
 'นครนายก',
 'สระแก้ว',
 'นครราชสีมา',
 'บุรีรัมย์',
 'สุรินทร์',
 'ศรีสะเกษ',
 'อุบลราชธานี',
 'ยโสธร',
 'ชัยภูมิ',
 'อำนาจเจริญ',
 'บึงกาฬ',
 'หนองบัวลำภู',
 'ขอนแก่น',
 'อุดรธานี',
 'เลย',
 'หนองคาย',
 'มหาสารคาม',
 'ร้อยเอ็ด',
 'กาฬสินธุ์',
 'สกลนคร',
 'นครพนม',
 'มุกดาหาร',
 'เชียงใหม่',
 'ลำพูน',
 'ลำปาง',
 'อุตรดิตถ์',
 'แพร่',
 'น่าน',
 'พะเยา',
 'เชียงราย',
 'แม่ฮ่องสอน',
 'นครสวรรค์',
 'อุทัยธานี',
 'กำแพงเพชร',
 'ตาก',
 'สุโขทัย',
 'พิษณุโลก',
 'พิจิตร',
 'เพชรบูรณ์',
 'ราชบุรี',
 'กาญจนบุรี',
 'สุพรรณบุรี',
 'นครปฐม',
 'สมุทรสาคร',
 'สมุทรสงคราม',
 'เพชรบุรี',
 'ประจวบคีรีขันธ์',
 'นครศรีธรรมราช',
 'กระบี่',
 'พังงา',
 'ภูเก็ต',
 'สุราษฎร์ธานี',
 'ระนอง',
 'ชุมพร',
 'สงขลา',
 'สตูล',
 'ตรัง',
 'พัทลุง',
 'ปัตตานี',
 'ยะลา',
 'นราธิวาส']
df10["NEW3-CC-DESC"] = new3_cc_desc
df11 = df.merge(df10, left_on="tname", right_on="NEW3-CC-DESC")
df11.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 NEW3-CC-DESC
0 10 Bangkok กรุงเทพมหานคร 1568.95 POLYGON ((100.85537 13.69198, 100.71321 13.711... 6312 10 กรุงเทพมหานคร 0 0 0 2625938 2962284 5588222 3103483 NaN กรุงเทพมหานคร
1 11 Samut Prakan สมุทรปราการ 960.09 POLYGON ((100.85537 13.69198, 100.94033 13.657... 6312 11 จังหวัดสมุทรปราการ 0 0 0 644516 706963 1351479 711804 NaN สมุทรปราการ
2 12 Nonthaburi นนทบุรี 633.25 POLYGON ((100.35029 14.11371, 100.33659 14.060... 6312 12 จังหวัดนนทบุรี 0 0 0 594308 682437 1276745 718799 NaN นนทบุรี
3 13 Pathum Thani ปทุมธานี 1520.06 POLYGON ((100.91242 14.21391, 100.90529 13.955... 6312 13 จังหวัดปทุมธานี 0 0 0 557752 618660 1176412 642474 NaN ปทุมธานี
4 14 Phra Nakhon Si Ayutthaya พระนครศรีอยุธยา 2534.07 POLYGON ((100.59405 14.65593, 100.57436 14.589... 6312 14 จังหวัดพระนครศรีอยุธยา 0 0 0 393551 425537 819088 336357 NaN พระนครศรีอยุธยา
fig = px.choropleth(
    df11, 
    geojson=df11.geometry, 
    locations=df11.index, 
    color="HOUSE", 
    hover_data=["tname", "HOUSE"])

fig.update_geos(fitbounds="locations")

ได้เป็นสีแล้ว!!! แต่กรุงเทพเข้มกว่าสีอื่นมาก ลองใช้ log มาช่วยเพิ่มดู

fig = px.choropleth(
    df11, 
    geojson=df11.geometry, 
    locations=df11.index, 
    color=np.log(df11["HOUSE"]), 
    hover_data=["tname", "HOUSE"])

fig.update_geos(fitbounds="locations")
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-34-5fa9ec9e1215> in <module>
      3     geojson=df11.geometry,
      4     locations=df11.index,
----> 5     color=np.log(df11["HOUSE"]),
      6     hover_data=["tname", "HOUSE"])
      7 


NameError: name 'np' is not defined

ลืม import np

import numpy as np
fig = px.choropleth(
    df11, 
    geojson=df11.geometry, 
    locations=df11.index, 
    color=np.log(df11["HOUSE"]), 
    hover_data=["tname", "HOUSE"])

fig.update_geos(fitbounds="locations")

เริ่มมีสีสัน พอแค่นี้ก่อน

2) ตัวอย่างการใช้ melt

top

จะเริ่มดูที่เฉพาะ กรุงเทพมหานคร จาก df9

df12 = df9[df9["CC-DESC"] == "กรุงเทพมหานคร"]
df12.head()
YYMM CC-CODE CC-DESC RCODE-CODE RCODE-DESC CCAATT-CODE CCAATT-DESC CCAATTMM-CODE CCAATTMM-DESC MALE FEMALE TOTAL HOUSE Unnamed: 13
1 6312 10 กรุงเทพมหานคร 0 0 0 2625938 2962284 5588222 3103483 NaN
79 6212 10 กรุงเทพมหานคร 0 0 0 2669316 2996948 5666264 3041115 NaN
157 6112 10 กรุงเทพมหานคร 0 0 0 2679453 2997195 5676648 2959524 NaN
235 6012 10 กรุงเทพมหานคร 0 0 0 2682962 2999453 5682415 2887274 NaN
313 5912 10 กรุงเทพมหานคร 0 0 0 2687253 2999393 5686646 2816711 NaN
df13 = df12.melt(id_vars=["YYMM"], value_vars=["MALE", "FEMALE", "TOTAL", "HOUSE"])
df13
YYMM variable value
0 6312 MALE 2625938
1 6212 MALE 2669316
2 6112 MALE 2679453
3 6012 MALE 2682962
4 5912 MALE 2687253
... ... ... ...
107 4012 HOUSE 1810530
108 3912 HOUSE 1703128
109 3812 HOUSE 1661311
110 3712 HOUSE 1562110
111 3612 HOUSE 1472621

112 rows × 3 columns

px.line(df13, x="YYMM", y="value", color="variable")
df13.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 112 entries, 0 to 111
Data columns (total 3 columns):
 #   Column    Non-Null Count  Dtype 
---  ------    --------------  ----- 
 0   YYMM      112 non-null    int64 
 1   variable  112 non-null    object
 2   value     112 non-null    int64 
dtypes: int64(2), object(1)
memory usage: 2.8+ KB

ปี YYMM ตอนนี้เป็น quantitative แต่ถ้าเป็น nominal น่าจะดีขึ้นโดยการแปลงเป็น astype(str)

px.line(df13, x=df13["YYMM"].astype(str), y="value", color="variable")

2.1) การกลับแกน X

top

หลังจากการแปลงแล้วดีขึ้น แต่ลำดับปี-เดือน ควรจะเรียงให้น้อยอยู่ฝั่งซ้ายด้วยการ update_xaxes

fig = px.line(df13, x=df13["YYMM"].astype(str), y="value", color="variable")

fig.update_xaxes(autorange="reversed")