สถาบันข้อมูลขนาดใหญ่ (องค์การมหาชน)

Logo BDI For web

เรียนรู้วิธีการสร้าง Interactive Visualization ด้วย Plotly

Mar 1, 2021

หนึ่งในขั้นตอนของการวิเคราะห์ข้อมูลที่สำคัญคือการสำรวจและตรวจสอบข้อมูลเบื้องต้น อาทิ ข้อมูลเป็นข้อมูลประเภทไหน ข้อมูลมีการกระจายตัวเป็นอย่างไร แต่ละตัวแปรมีความสัมพันธ์อย่างไรเทียบกับข้อมูลทั้งหมด เพราะจะช่วยทำให้การตั้งสมมุติฐานของโจทย์ที่ต้องการวิเคราะห์ได้ดีขึ้น ซึ่งปกติแล้วจะนำข้อมูลมาแสดงผลในรูปแบบของภาพนิทัศน์ (visualization) เช่น แผนภูมิแท่ง (bar chart), แผนภูมิเส้น (line chart), แผนภูมิจุด (scatter plot) เป็นต้น

หนึ่งในตัวอย่างแผนภูมิที่ Plotly library สามารถสร้างได้

สำหรับเครื่องมือการสร้างแผนภูมิใน Python นั้น มีหลายวิธี สำหรับบทความที่ทางเว็บไซต์ได้เขียนไปในก่อนหน้านี้นั้น ได้ใช้การแสดงผลด้วย Matplotlib library เช่น แผนภูมิอนุกรมเวลา และแผนภูมิเส้น ซึ่งสามารถแสดงผลความสัมพันธ์เบื้องต้นได้ง่ายและรวดเร็ว

อย่างไรก็ตาม library ดังกล่าว มีข้อจำกัดในด้านการสร้างและแสดงผลที่โต้ตอบกับผู้ใช้งานได้ง่าย ถึงแม้ว่าจะมีความสามารถในการนำทางแบบโต้ตอบ (Interactive Toolbar) ของ Matplotlib library ที่ช่วยให้ผู้ใช้สามารถดูข้อมูล ขยายภาพเฉพาะจุด เก็บแผนภูมิดังกล่าวเป็นไฟล์รูป เทียบกับทาง Plotly library มีความสามารถที่น่าสนใจเพิ่มเติม เช่น กล่องข้อความหรือกลุ่มของข้อมูลสั้น ๆ (Tooltip) ทั้งแบบทีละจุดข้อมูลและแบบเปรียบเทียบข้อมูลทั้งหมด และการเลือกดูข้อมูลด้วยตัวกรองข้อมูล (Filter)

ตัวอย่างการใช้งานของคุณสมบัติการนำทางแบบโต้ตอบ ใน Matplotlib library
ตัวอย่างการใช้งานของคุณสมบัติการนำทางแบบโต้ตอบ ใน Plotly library

เครื่องมือการสร้างแผนภูมิใน Python ที่เป็นที่นิยมเช่น Matplotlib นั้น มีข้อจำกัดในด้านการแสดงผลที่โต้ตอบกับผู้ใช้งาน (interactive visualization) เช่น ไม่สามารถสร้างกล่องข้อความหรือกลุ่มของข้อมูลสั้น ๆ (Tooltip) ทั้งแบบทีละจุดข้อมูลและแบบเปรียบเทียบข้อมูลทั้งหมด และการเลือกดูข้อมูลด้วยตัวกรองข้อมูล (Filter)

ในบทความนี้ ผู้เขียนขอแนะนำ Plotly library ซึ่งเป็นเครื่องมือในการสร้างแผนภูมิที่มีความสามารถในการแสดงผลที่โต้ตอบกับผู้ใช้งาน ได้หลายหลาย มีแผนภูมิมากกว่า 40 ประเภท สามารถนำแผนภูมิที่ทำเสร็จสิ้นแล้วไปเพิ่มลงในเว็บไซด์ที่ต้องการได้ง่ายด้วย Python framework ที่ชื่อว่า “Plotly Dash” และที่สำคัญสามารถนำไปใช้งาน แก้ไข และเผยแพร่ได้อย่างเสรี (open source library)

การติดตั้ง library

สำหรับตัวอย่างในบทความนี้ ผู้เขียนได้ใช้งานบน Jupyter Notebook ซึ่งเป็นสิ่งแวดล้อมสำหรับการพัฒนาแบบเบ็ดเสร็จ (IDE) ที่นิยมสำหรับการวิเคราะห์ข้อมูลโดยการใช้ภาษา Python โดยสามารถทำติดตั้งได้โดยการใช้ command ด้านล่างหรืออ่านเพิ่มเติมได้ ที่นี่

!pip install plotly==4.14.3
# หากแผนภูมิไม่สามารถแสดงได้ใน jupyter notebook ให้ลอง run command นี้ดู
!pip install "notebook>=5.3" "ipywidgets>=7.5"

ข้อมูล

ผู้เขียนใช้ข้อมูลยอดขายของวีดิโอเกมจากเว็บไซต์ vgchartz.com โดยคัดเลือกเฉพาะวีดิโอเกมที่ขายได้มากกว่าหนึ่งแสนตลับ โดยสามารถอ่านรายละเอียดที่มาของข้อมูลได้ ที่นี่

import pandas as pd
data = pd.read_csv('https://github.com/Elliot-Taylor/VideoGameSalesPredictions/blob/master/vgsales.csv?raw=true')
data.head()
RankNamePlatformYearGenrePublisherNA_SalesEU_SalesJP_SalesOther_SalesGlobal_Sales
1Wii SportsWii2006SportsNintendo41.4929.023.778.4682.74
2Super Mario Bros.NES1985PlatformNintendo29.083.586.810.7740.24
3Mario Kart WiiWii2008RacingNintendo15.8512.883.793.3135.82
4Wii Sports ResortWii2009SportsNintendo15.7511.013.282.9633
5Pokemon Red/Pokemon BlueGB1996Role-PlayingNintendo11.278.8910.22131.37
ตัวอย่างข้อมูลยอดขายของวีดิโอเกมจากเว็บไซต์ vgchartz.com

จากการดูตัวอย่างข้อมูลจะพบว่า มีตัวแปรต่อเนื่องดังนี้ ลำดับของเกมที่ขายได้ตามจำนวนยอดขายทั้งหมด (Rank) ปีที่เกมดังกล่าวถูกวางขาย (Year) ยอดขายของทวีปอเมริกาเหนือ (NA_Sales) ยอดขายของทวีปยุโรป (EU_Sales) ยอดขายของประเทศญี่ปุ่น  (JP_Sales) ยอดขายประเทศอื่น ๆ (Other_Sales) ยอดขายรวม (Global_Sales) และมีตัวแปรแบบจัดกลุ่มดังนี้ ชื่อเกม (Name) แพลตฟอร์มที่เกมถูกเอาไปเล่น (Platform) ประเภทของเกม (Genre) ชื่อบริษัทที่พัฒนาเกม (Publisher)

ตัวอย่างการใช้ plotly

สำหรับบทความนี้ ทางผู้เขียนสร้างแผนภูมิด้วย plotly.express ซึ่งเป็นตัว function ที่เขียนมาให้สร้างสร้างแผนภูมิ Plotly ได้ง่ายขึ้น โดยจะเริ่มต้นด้วยการวาดกราฟแท่ง (Bar Graph) โดยทางผู้เขียนต้องการทราบว่า บริษัทที่พัฒนาเกม (Publisher) ขนาดใหญ่ที่ขายเกมมากกว่า 500 เกม ชอบสร้างเกมประเภทไหน (Genre)

# นำเข้า plotly.express 
import plotly.express as px
# คัดเลือกเฉพาะเกมที่ถูกพัฒนาโดยบริษัทที่พัฒนาเกม (Publisher) ที่ผลิตออกมาเกิน 500 เกม
data1 = data[data.groupby('Publisher')['Publisher'].transform('count').ge(500)]
# จัดกลุ่มข้อมูลก่อนนำไปสร้างแผนภูมิ
data1 = data1.groupby(["Publisher", "Genre"])['Name'].agg('count').reset_index(name="Count")
# กราฟแท่ง (Bar Graph)
fig = px.bar(data1, x="Publisher", y="Count", color="Genre",
             labels=dict(Publisher='บริษัทที่พัฒนาเกม',Count="จำนวน",Genre='ประเภทของเกม'))
fig.show()
แผนภูมิแท่ง (Bar Graph) แสดงความสัมพันธ์ระหว่างบริษัทที่พัฒนาเกม (Publisher) และประเภทของเกม (Genre) โดยใช้ Plotly

จากแผนภูมิตัวอย่าง จะเห็นจากแผนภูมิได้ว่า บริษัท Electronic Arts จะชอบสร้างเกมประเภท Sports เป็นพิเศษ ซึ่ง tooltip ช่วยให้ผู้ใช้สามารถโต้ตอบกับแผนภูมิด้วยเมาส์ และเห็นข้อมูลเพิ่มเติมในเฉพาะสิ่งที่สนใจได้อีกด้วย ในกรณีนี้ พบว่า Electronic Arts ได้ทำเกมประเภท Sports ออกมาแล้วกว่า 561 เกม ในขณะที่ บริษัท Namco Bandai Games จะชอบสร้างเกมประเภท Sports มีสัดส่วนการสร้างเกมประเภท Role-Playing เทียบกับเกมประเภทอื่นสูงกว่าบริษัทอื่น

ตัวอย่างต่อไปจะใช้กราฟเส้น (Line Graph) โดยในกราฟนี้ ทางผู้เขียนต้องการทราบว่า ในแต่ละปี (Year) เกมประเภทไหน (Genre) ถูกนำมาวางขายเยอะที่สุด

ตัวอย่างต่อไปจะใช้กราฟเส้น (Line Graph) โดยในกราฟนี้ ทางผู้เขียนต้องการทราบว่า ในแต่ละปี (Year) เกมประเภทไหน (Genre) ถูกนำมาวางขายเยอะที่สุด
# จัดกลุ่มข้อมูลก่อนนำไปสร้างแผนภูมิ
data2 = data.groupby(["Genre", "Year"])['Name'].agg('count').reset_index(name="Count")
# กราฟเส้น (Line Graph)
fig = px.line(data2, x="Year", y="Count", color='Genre',
              labels=dict(Year='ปีที่เกมดังกล่าวถูกวางขาย',Count="จำนวน",Genre='ประเภทของเกม'))
fig.show()
แผนภูมิเส้น (Line Graph) แสดงความสัมพันธ์ระหว่างปี (Year) และประเภทของเกม (Genre) โดยใช้ Plotly

จากแผนภูมิตัวอย่าง นอกจากการแสดงผลของแนวโน้มโดยรวมระหว่างความสัมพันธ์ของประเภทของเกมเทียบเป็นรายปี เมื่อทำการเลือกดูเฉพาะกลุ่มและทำการเลือกการเปรียบเทียบข้อมูลด้วย tooltip ทำให้เห็นได้ว่าเกมประเภท Racing กับ Platform ขายได้ดีและไปในทิศทางเดียวกันในช่วงระหว่างปี 2000 – 2005 หลังจากนั้นเกมประเภท Role-Playing กับ Puzzle กลับได้รับความนิยมมากกว่าและมียอดขายไปทิศทางเดียวกันในช่วงระหว่างปี 2005 – 2010

ตัวอย่างสุดท้ายจะวาดแผนภูมิจุด (Scatter Graph) ของเกมที่มียอดขายสูงสุด 50 อันดับแรก โดยดูความสัมพันธ์ระหว่างยอดขายของแต่ละเกมของประเทศญี่ปุ่น (JP_Sales) เทียบกับ ยอดขายประเทศอื่น ๆ (Other_Sales) โดยถูกแบ่งสีตามประเภทของเกม (Genre) และมีขนาดของจุดที่สัมพันธ์กับยอดขายรวม (Global_Sales)

# คัดเลือกข้อมูลเฉพาะเกมที่มียอดขายสูงสุด 50 อันดับแรก
data3 = data[data["Rank"] <= 50]
data3 = data3.sort_values('Genre')
# กราฟการกระจาย (Scatter Graph)
fig = px.scatter(data3, x="JP_Sales", y="Other_Sales",hover_name='Name',size="Global_Sales", color='Genre',
                labels=dict(JP_Sales='ยอดขายของประเทศญี่ปุ่น',Other_Sales="ยอดขายประเทศอื่น ๆ",Global_Sales="ยอดขายรวม",Name="ชื่อ",Genre='ประเภทของเกม'))
fig.show()
แผนภูมิการกระจาย (Scatter Graph) แสดงความสัมพันธ์ระหว่างยอดขายของแต่ละเกมของประเทศญี่ปุ่น (JP_Sales) ยอดขายของแต่ละเกมของประเทศอื่น ๆ (Other_Sales) ประเภทของเกม (Genre) และยอดขายรวม (Global_Sales) โดยใช้ Plotly

แผนภูมิตัวอย่างได้ใช้การแสดงเทียบแกนข้อมูลแนวตั้งและแนวนอนแบบ toggle ซึ่งช่วยแสดงให้เห็นว่าเกมแนว action ขายได้ดีในกลุ่มประเทศอื่น เกมแนว sport ขายได้ดีในทุกประเทศ เกมแนว role-playing ขายได้ดีในประเทศญี่ปุ่น และในแนวเกมประเภท Shooter จะเกาะกลุ่มล่างซ้าย ซึ่งเป็นกลุ่มที่มีแต่เกมที่ทำยอดขายที่ไม่ดีในทุกประเทศ

จบไปแล้วนะครับสำหรับการใช้งาน Plotly เบื้องต้น หวังว่าบทความนี้จะเป็นไอเดียที่ดีในการที่ผู้อ่านจะนำไปปรับใช้ เพื่อให้แผนภูมิมีความน่าสนใจมากขึ้นและช่วยให้เราหา insight จากข้อมูลได้ง่ายขึ้นนะครับ หากผู้อ่านสนใจการสร้างแผนภูมิบน Plotly ที่อยู่นอกเหนือจากบทความนี้ สามารถเข้าไปดูได้ ที่นี่

เนื้อหาโดย ธนกร ทำอิ่นแก้ว
ตรวจทานและปรับปรุงโดย ปพจน์​ ธรรมเจริญพร

Thanakorn Thaminkaew

Data Scientist at Big Data Institute (Public Organization), BDI

© Big Data Institute | Privacy Notice