Tutorial

โตแล้ว Plot อะไรก็ได้ด้วย Seaborn

By Arnon Puitrakul - 12 November 2020 - 5 min read min(s)

โตแล้ว Plot อะไรก็ได้ด้วย Seaborn

ในการ Plot Graph ต่าง ๆ น่าจะเป็นเรื่องที่เราว่าหลาย ๆ คนที่ทำงานกับข้อมูลก็น่าจะต้องทำแหละ มันทำให้เรามองเห็นข้อมูลดีมากยิ่งขึ้น แต่เมื่อก่อน การที่เราจะ Plot อะไรสักอย่างไม่ใช่เรื่อง่ายเลย แต่วันนี้มันมี Library หลายตัวมาก ๆ ที่ออกมาเพื่อการ Plot Graph หรือการทำ Data Visualisation วันนี้ตัวที่เราจะมาแนะนำกันคือ Seaborn ที่บอกว่า มันง่ายมาก ๆ และ เราจะแถม Cookbook ย่อม ๆ ให้ในบทความนี้ด้วย เผื่อใครกำลังทำแล้วอยากได้แบบนี้พอดีจะได้ก๊อป และ เอาไปแก้ให้เข้ากับเราได้เลย

Data Preparation

ก่อนที่เราจะ Plot หรือ Visualise ข้อมูลออกมาได้ เราจะต้องเตรียมข้อมูลกันก่อน ซึ่งเราแนะนำให้ทำข้อมูลให้อยู่ในรูปแบบของ Pandas Dataframe ก่อนจะได้ทำงานได้ง่ายขึ้น

# Convert Byte to MB
dataset['compressed_size_MB'] = dataset['compressed_size'] / 1000

หรือถ้าเราต้องการแปลงค่าอะไรก็ทำได้ขั้นตอนนี้เลย ตัวอย่างเช่น เราอยากจะแปลงจาก Byte ให้เป็น MB เราก็เอามาหารด้วย 1000 เข้าไป ก็จะใช้ตามนี้ ก็คือ เราเปิด Column ใหม่ขึ้นมาที่เอาค่าจาก Column ชื่อ compressed_size มาหารด้วยพันทุก Record แล้วออกมาเป็น Column ใหม่ชื่อ compressed_size_MB ก็เรียบร้อยแล้ว

ส่วนตัวอย่างที่เราจะใช้จริง ๆ ในวันนี้คือ Dataset ที่ชื่อ Solar Power Generation Data อยู่ใน Kaggle ลองไปโหลดแล้วมาทำตามได้

>>> import pandas as pd
>>> dataset = pd.read_csv('Plant_1_Generation_Data.csv')

เราเริ่มต้นจากการดึง CSV เข้ามาเป็น Pandas DataFrame ผ่านคำสั่ง read_csv ทั่ว ๆ ไปเลย

>>> dataset.columns
Index(['DATE_TIME', 'PLANT_ID', 'SOURCE_KEY', 'DC_POWER', 'AC_POWER',
       'DAILY_YIELD', 'TOTAL_YIELD'],
      dtype='object')

จากนั้น เราสามารถเช็คได้ว่า ใน Dataset ตัวนี้มี Column ชื่ออะไรบ้าง ส่วนแต่ละอันคืออะไร เราสามารถเข้าไปหาได้ในหน้าของ Kaggle ว่ามันคืออะไรบ้าง จากตรงนี้เราจะเห็นได้ว่า มีทั้งหมด 7 Column ด้วยกัน

>>> dataset['PLANT_ID'].unique()
array([4135001])

เราอยากรู้ว่า ในข้อมูลชุดนี้ ประกอบด้วยข้อมูลจาก Power Plant กี่ที่ เราก็ขอดูว่ามันมีค่าที่ต่างกันกี่อัน ในที่นี้คือมีค่าเดียว แปลว่าในทั้ง Dataset นี้มาจาก 1 Plant เท่านั้น

>>> dataset['DATE_TIME'] = pd.to_datetime(dataset['DATE_TIME'])

เราลืมไปว่า เออในนี้มีข้อมูลที่เป็นวันที่และเวลาอยู่ด้วยแต่เวลาเรา Import เข้ามา มันไม่ได้คิดอะไร มันเลยกลายเป็น String ธรรมดา ทำให้เรา Process หรือจัดการอะไรได้ยาก ดังนั้นเพื่อให้ง่ายขึ้นเราก็จะแปลงมันให้อยู่ในรูปของ DateTime กันก่อน ผ่านคำสั่ง to_datetime ได้เลย

>>> dataset[dataset['DATE_TIME'].dt.month == 5]
                DATE_TIME  PLANT_ID  ... DAILY_YIELD  TOTAL_YIELD
0     2020-05-15 00:00:00   4135001  ...         0.0    6259559.0
1     2020-05-15 00:00:00   4135001  ...         0.0    6183645.0
2     2020-05-15 00:00:00   4135001  ...         0.0    6987759.0
3     2020-05-15 00:00:00   4135001  ...         0.0    7602960.0
4     2020-05-15 00:00:00   4135001  ...         0.0    7158964.0
...                   ...       ...  ...         ...          ...
43533 2020-05-06 23:45:00   4135001  ...      7838.0    7202373.0
43534 2020-05-06 23:45:00   4135001  ...      3874.0    6946769.0
43535 2020-05-06 23:45:00   4135001  ...      7739.0    7171001.0
43536 2020-05-06 23:45:00   4135001  ...      7723.0    6500302.0
43537 2020-05-06 23:45:00   4135001  ...      7817.0    7279090.0

[35192 rows x 7 columns]

ตัวอย่างเช่น ถ้าเราอยากจะเอาทุก Record ของเดือน 5 ออกมา เราก็สามารถเรียกได้จากคำสั่ง dt.month ได้เลย หรือจริง ๆ แล้วถ้าเราอยากได้ของ วันที่ 15 เดือน 5 ปี 2020

>>> dataset[(dataset['DATE_TIME'].dt.day == 15) & (dataset['DATE_TIME'].dt.month == 5) & (dataset['DATE_TIME'].dt.year == 2020)]
               DATE_TIME  PLANT_ID  ... DAILY_YIELD  TOTAL_YIELD
0    2020-05-15 00:00:00   4135001  ...         0.0    6259559.0
1    2020-05-15 00:00:00   4135001  ...         0.0    6183645.0
2    2020-05-15 00:00:00   4135001  ...         0.0    6987759.0
3    2020-05-15 00:00:00   4135001  ...         0.0    7602960.0
4    2020-05-15 00:00:00   4135001  ...         0.0    7158964.0
...                  ...       ...  ...         ...          ...
1949 2020-05-15 23:00:00   4135001  ...      6387.0    7045068.0
1950 2020-05-15 23:00:00   4135001  ...      6329.0    6788927.0
1951 2020-05-15 23:00:00   4135001  ...      6386.0    7014252.0
1952 2020-05-15 23:00:00   4135001  ...      6396.0    6345776.0
1953 2020-05-15 23:00:00   4135001  ...      5965.0    7122116.0

[1954 rows x 7 columns]

จะเห็นว่าจำนวน Rows มันน้อยลง เพราะเราเอามาแค่วันเดียวเท่านั้น แต่เอ๊ะ สิ่งที่มันแปลก ๆ คือ ทำไมมันมีวันที่เวลาเดียวกันอยู่ละ ทั้ง ๆ ที่ Plant ID มีแค่อันเดีว ถ้าเราเอากลับไปสังเกตุที่ Column อีกที เราจะเจอกับ Column ที่ชื่อ SOURCE_KEY และ เมื่อเราเข้าไปดูใน Kaggle เขาอธิบายว่ามันเป็น Inverter ID

>>> dataset['SOURCE_KEY'].unique()
array(['1BY6WEcLGh8j5v7', '1IF53ai7Xc0U56Y', '3PZuoBAID5Wc2HD',
       '7JYdWkrLSPkdwr4', 'McdE0feGgRqW7Ca', 'VHMLBKoKgIrUVDU',
       'WRmjgnKYAwPKWDb', 'ZnxXDlPa8U1GXgE', 'ZoEaEvLYb1n2sOq',
       'adLQvlD726eNBSB', 'bvBOhCH3iADSZry', 'iCRJl6heRkivqQ3',
       'ih0vzX44oOqAx2f', 'pkci93gMrogZuBj', 'rGa61gmuvPhdLxV',
       'sjndEbLyjtCKgGv', 'uHbuxQJl8lW7ozc', 'wCURE6d3bPkepu2',
       'z9Y9gH1T5YWrNuG', 'zBIq5rxdHJRwDNY', 'zVJPv84UY57bAof',
       'YxYtjZvoooNbGkE'], dtype=object)

>>> len(dataset['SOURCE_KEY'].unique())
22

เราเลยลองเอาออกมาดูหน่อยว่า มันมีกี่ Inverter คอยแปลงไฟอยู่ ผ่านคำสั่ง Unique ออกมาเยอะมาก นับเองก็จะดูตลกไป เราก็ครอบด้วย len() เราก็จะเห็นว่าทั้งหมดมี 22 Inverter

Plotting Data

>>> single_inverter_date_data = dataset[(dataset['SOURCE_KEY'] == '1BY6WEcLGh8j5v7') & (dataset['DATE_TIME'].dt.day == 15) & (dataset['DATE_TIME'].dt.month == 5) & (dataset['DATE_TIME'].dt.year == 2020)]

               DATE_TIME  PLANT_ID  ... DAILY_YIELD  TOTAL_YIELD
0    2020-05-15 00:00:00   4135001  ...         0.0    6259559.0
21   2020-05-15 00:15:00   4135001  ...         0.0    6259559.0
42   2020-05-15 00:30:00   4135001  ...         0.0    6259559.0
63   2020-05-15 00:45:00   4135001  ...         0.0    6259559.0
84   2020-05-15 01:00:00   4135001  ...         0.0    6259559.0
...                  ...       ...  ...         ...          ...
1844 2020-05-15 22:00:00   4135001  ...      5754.0    6265313.0
1866 2020-05-15 22:15:00   4135001  ...      5754.0    6265313.0
1888 2020-05-15 22:30:00   4135001  ...      5754.0    6265313.0
1910 2020-05-15 22:45:00   4135001  ...      5754.0    6265313.0
1932 2020-05-15 23:00:00   4135001  ...      5754.0    6265313.0

[93 rows x 7 columns]

เราลองมา Plot พลังงานที่ได้ในวันที่ 15 เดือน 5 กัน ว่ามันจะออกมาเป็นยังไง แต่เรามีหลาย Inverter อาจจะยากไป เราลองเอามาแค่อันเดียวก่อนละกัน

>>> import matplotlib.pyplot as plt
>>> import seaborn as sns

หลังจากที่เราได้ Data มาแล้ว เราลองเอามันมา Plot ดูก่อน แต่ก่อนหน้านั้นเราจะต้อง Import Seaborn และ Matplotlib เข้ามาก่อนด้วยคำสั่งด้านบน

>>> sns.lineplot(data=single_inverter_date_data, x='DATE_TIME', y='DAILY_YIELD')
>>> plt.show()

เราลองมา Plot พลังงานที่ได้มาในแต่ละช่วงของวันกัน โดยที่มันจะอยู่ที่ Column ที่ชื่อว่า DAILY_YIELD ในทีนี้ เราจะ Plot Line Chart ออกมา ซึ่งจะใช้คำสั่งที่ชื่อว่า lineplot โดยที่เรายัด DataFrame ผ่าน Arugement ชื่อ data พร้อมกับบอกว่า แกน X เราจะให้มันแสดงอะไร ในที่นี้คือ DATE_TIME ซึ่งก็คือ วันที่และเวลา และ แกน Y เราก็จะให้แสดงเป็น DAILY_YIELD

จะเห็นว่านอกจากที่เราจะสั่ง Seaborn Plot แล้ว ในการที่เราจะให้มันแสดงขึ้นมาเป็นหน้าต่างแบบ Interactive เราก็ยังคงต้องใช้ Matplotlib ช่วยอยู่ เพื่อให้มันแสดงขึ้นมาเราเลยเรียก plt.show()

เท่านี้เราก็จะได้ Graph แรกของเราออกมาแล้ว เย้ ~ เราจะเห็นว่า มันออกมาตามที่เราสั่งเลย ทั้งในแกน X และ Y แต่แหม่ ถ้าเอาไปใช้จริงเลย มันก็จะแอบไม่สวยตรง Label ของแกน X และ Y เราลองมาแก้กันหน่อย

>>> plot = sns.lineplot(data=single_inverter_date_data, x='DATE_TIME', y='DAILY_YIELD')
>>> plt.xlabel('Date')
>>> plt.ylabel('Energy Yield')
>>> plt.title('Energy Yield for Inverter 1BY6WEcLGh8j5v7')
>>> plt.show()

เรา Plot เหมือนเดิม แต่ตอนนี้เราเพิ่ม อีก 3 คำสั่งเข้ามาคือ xlabel และ ylabel สำหรับการเปลี่ยน Label ที่แกน X และ Y ส่วน title คือ การเพิ่มหัวของกราฟเข้ามา อันนี้สามารถใช้กับ Plot แบบไหนก็ได้หมด

กราฟก็จะเหมือนเดิมหมด แต่สิ่งที่เปลี่ยนคือ หัวกราฟ, Label ตรงแกน X และ Y ที่เปลี่ยนไป แต่เราก็ยังเห็นว่า อื้ม ตรงเวลามันแสดงวันที่ซะหมด เราเลือกมาวันเดียวแล้ว มันก็ควรจะแสดงเวลาสิ

>>> import matplotlib.dates as mdates
>>> plot = sns.lineplot(data=single_inverter_date_data, x='DATE_TIME', y='DAILY_YIELD')
>>> plot.xaxis.set_major_locator(mdates.HourLocator())
>>> plot.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M:%S"))
>>> plot.tick_params(axis="x", rotation=45)
>>> plt.show()

เพื่อแก้ปัญหานี้ เราอาจจะต้องลงไปลึกใน Matplotlib หน่อย อันนี้เราทำมาให้เป็น Cookbook เลย สามารถก๊อปไปใช้ได้เลยคือ เราสั่ง Plot Line Plot เหมือนเดิม แต่เราใช้ HourLocater กับ Formatter เปลี่ยนค่าในแกน X ให้กลายเป็น Format ที่เราต้องการคือ ชั่วโมง:นาที:วินาที นั่นนำไปสู่อีกปัญหาคือ มันยาว จนถ้าเราแสดงผลแบบปกติ มันจะแสดงไม่พอ ทับกันเละไปหมด ทำให้เราต้องหมุนค่าที่แสดงในแกน X 45 องศา เอียงนิดหน่อยด้วย การเรียก tick_params พร้อมกับเลือกแกน X  และสั่งให้หมุน 45 องศา

เราก็ได้กราฟที่สวยงามออกมา ส่วนพวก xlabel, ylabel และ title ก็เติมเอาได้เลย แต่จะเห็นได้ว่า เราแก้ปัญหาเรื่องการแสดงผลเรียบร้อยแล้ว ทำให้ปัญหาต่อไป ถ้าเราอยากที่จะแสดงทุก Inverter เลยละ จะเป็นไปได้มั้ย คำตอบคือได้

>> all_inverter_single_day = dataset[(dataset['DATE_TIME'].dt.day == 15) & (dataset['DATE_TIME'].dt.month == 5) & (dataset['DATE_TIME'].dt.year == 2020)]
>>> plot = sns.lineplot(data=all_inverter_single_day, x='DATE_TIME', y='DAILY_YIELD', hue='SOURCE_KEY')
>>> plt.show()

ใน Seaborn นอกจากที่เราจะกำหนดแกน X และ Y ได้ เรายังกำหนดให้มันแยกข้อมูลตามสีได้อีก ในที่นี้เราจะแยกสีด้วย Inverter ID กัน หรือก็คือ Column ที่ชื่อว่า SOURCE_KEY เราสามารถเติม Argument ที่ชื่อว่า hue ลงไปเพื่อให้มันแยกตามสีได้

เราจะเห็นว่ากราฟมันออกมาแทบจะทับกันไปหมด ซึ่งก็แน่ละ มันน่าจะเป็น Site เดียวกันอยู่ที่เดียวกันน่าจะให้พลังงานไม่ต่างเลย แต่มันมีสีเขียวหลุดออกมา อันนี้น่าจะแปลก ๆ แต่ด้วยสี มันทำให้ดูยาก เราลองเปลี่ยนจากสีเป็น ขีด แบบอื่น ๆ ละกันจะได้แยกง่าย ๆ ด้วย

>>> plot = sns.lineplot(data=all_inverter_single_day, x='DATE_TIME', y='DAILY_YIELD', style='SOURCE_KEY')
>>> plt.show()

ใน Seaborn เราจะเปลี่ยนจากให้มันแยกเป็นสี ๆ ให้เป็นแบบต่าง ๆ แทนเราก็สามารถเปลี่ยนไปใช้เป็น style ได้ หรือจริง ๆ ถ้าเราอยากใช้ทั้งคู่เลยก็ได้เหมือนกัน

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

เรามาลองทำ Bar Plot กันบ้างดีกว่า เราลองมาดูว่า Inverter แต่ละตัวให้ไฟได้กี่หน่วย จากข้อมูลที่เรามี อันที่น่าจะดูเข้าเค้าที่สุดน่าจะเป็น DAILY_YIELD หรือก็คือ บอกว่า ในวันนั้น ๆ มันได้ไฟไปเท่าไหร่ ซึ่งมันก็จะเพิ่มไปเรื่อย ๆ ในแต่ละช่วงของวัน ในการทำ Plot ก่อนหน้านี้ เรามีตัวที่เราดึงมาแค่วันเดียว แต่แค่มันเรียงเป็น Time Series ทั้งวันเท่านั้น แต่ในการที่เราจะ Plot ว่าแต่ในวันนั้น มันได้ไฟเท่าไหร่ เราต้อง Summerise ข้อมูลออกมาก่อน

>>> inverter_max = all_inverter_single_day.groupby('SOURCE_KEY')['DAILY_YIELD'].max().reset_index()

จริง ๆ ก็คือ มันเป็นการดึงค่าที่มากที่สุดใน Column DAILY_YIELD เท่านั้นเอง แต่ถ้าทำแบบนั้นเราก็จะได้แค่อันที่มากที่สุด ทำให้เราต้องเล่นท่านิดหน่อยด้วยการสั่งให้มัน Group ข้อมูลทั้งหมด ตาม SOURCE_KEY หรือก็คือ Inverter แต่ละเครื่อง จากนั้น เราขอแค่ DAILY_YIELD ออกมา และ ให้มันหาอันที่มีค่ามากที่สุด ซึ่งในที่นี้ มันก็จะมีแค่ DAILY_YIELD เท่านั้น สุดท้าย ก็ให้มันเอา Index ออกมาด้วย (หรือก็คือ เอา SOURCE_KEY ออกมาด้วย)

>>> plot = sns.barplot(data=inverter_max, x='SOURCE_KEY', y='DAILY_YIELD')

จากนั้นเราจะสั่งให้มัน Plot Bar Plot ออกมา โดยใช้สำสั่ง barplot พร้อมกับป้อนข้อมูลที่เราทำออกมาเมื่อกี้ลงไป กับบอกว่าแกน X และ Y คือ ตัวเครื่อง และ ไฟที่ได้ (ที่เราหาอันที่ Max สุด ในวันนั้น)

>>> plot.tick_params(axis="x", rotation=90)
>>> plt.show()

เมื่อครู่ เราอาจจะเห็นแล้วว่า เลขรหัสเครื่อง Inverter มันยาวมาก ทำให้เวลาเรา Plot ออกมา มันน่าจะติด ๆ กันหมดเราก็ใช้ Trick จากตอนต้นคือ การสั่งให้มันหมุน Label บนแกน X ทั้งหมดเลยสิ และ สุดท้ายเราก็สั่ง Show ออกมาก็เป็นอันเสร็จแล้ว

เราก็จะได้กราฟสวย ๆ ออกมาได้ไม่ยากเลย มันก็จะเป็นกราฟที่แสดงพลังงานที่ Inverter แต่ละตัวผลิตได้ในวันที่เราเลือกออกมาตอนแรกนั่นเอง ส่วนถ้าอยากจะใส่ Title และ X,Y Label ก็ใส่ได้ตามสบายเลย

Multi-Line Plot

เราลองมาทำอะไรให้หรรษาขึ้นอีกดีกว่า ถ้าเกิดว่าเราอยากรู้ว่า ระหว่าง 2 วัน Inverter ตัวนึงทำงานได้ต่างกันแค่ไหน เราน่าจะทำยังไงดีนะ ตัวอย่างเช่น เราอยากรู้ว่า Inverter ID 1BY6WEcLGh8j5v7 ให้ไฟเท่าไหร่ ของวันที่ 15-05-2020 กับ 16-05-2020 ต่างกันขนาดไหน

ถ้าเราลองดึงข้อมูลของ Inverter ที่เราต้องการ ในวันที่ทั้ง 2 วัน แล้ว Plot ด้วย DAILY_YIELD และ SOURCE_ID เพียว ๆ เลย เราจะเจอปัญหาว่า เอ๋ ทำไม Plot มันอยู่คนละอันบนแกน X เลย นั่นเพราะว่ามันนับวันที่เข้าไปด้วยนั่นเอง ทำให้เจอเหตุการณ์แบบนั้น ทำให้เราต้องเล่นท่ากันหน่อย

>>> dataset['DAY'] = dataset['DATE_TIME'].dt.date
>>> dataset['TIME'] = dataset['DATE_TIME'].dt.time

ก่อนอื่น เราจะขอสร้าง Column ใหม่ขึ้นมา 2 อันด้วยกัน คือ DAY สำหรับเก็บแค่วันที่เท่านั้น และ TIME สำหรับเก็บเวลาเท่านั้น ถ้าใครกำลัง งง ลองอ่านไปเรื่อย ๆ ก่อน แล้วเดี๋ยวจะอ๋อเอง

>>> day_1 = dataset[(dataset['SOURCE_KEY'] == '1BY6WEcLGh8j5v7') & (dataset['DATE_TIME'].dt.day == 15) & (dataset['DATE_TIME'].dt.month == 5) & (dataset['DATE_TIME'].dt.year == 2020)]
>>> day_2 = dataset[(dataset['SOURCE_KEY'] == '1BY6WEcLGh8j5v7') & (dataset['DATE_TIME'].dt.day == 16) & (dataset['DATE_TIME'].dt.month == 5) & (dataset['DATE_TIME'].dt.year == 2020)]
>>> combined_day = day_1.append(day_2)

จากนั้น เราก็เลือกมาแค่ 2 วันคือวันที่ 15 และ 16 ออกมาตรง ๆ ได้เลย และสุดท้ายของการเตรียมข้อมูลก็คือ เราก็จะเอา DataFrame ของทั้ง 2 วันมา Merge รวมกันผ่านการ Append แล้วเก็บลง DataFrame ชุดใหม่ เพื่อความง่ายในการเรียก

>>> plot = sns.lineplot(data=combined_day, x='TIME', y='DAILY_YIELD', hue='DAY')
>>> plot.xaxis.set_major_locator(mdates.HourLocator())
>>> plot.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M:%S"))
>>> plot.tick_params(axis="x", rotation=45)
>>> plt.show()

ตรงนี้แหละสำคัญ เราสั่งให้ Seaborn Plot ตัว Line Plot เหมือนที่เราเคยทำ แต่เราเปลี่ยนนิดหน่อยคือ แทนที่แกน X เราจะเป็น DATE_TIME ตรง ๆ เราก็เอา TIME เฉย ๆ ที่เราพึ่งทำขึ้นมา มาใส่แทน ทำให้ข้อมูลของวันทั้ง 2 มันมากองอยู่ที่เดียวกันได้ แต่เราแยกสีด้วยวันแทนนั่นเอง

เท่านี้เราก็จะได้ Plot ที่แสดงพลังงานของทั้ง 2 วันมาแล้วอย่างง่ายดาย

plt.yscale('log')

อันนี้แถมให้ เผื่อเวลาเรา Plot ข้อมูลที่มันมีความห่างกันมาก ๆ แล้วถ้าเราใช้ Scale ธรรมดา อันที่มันอยู่ห่าง ๆ มันก็จะหายไปเลย วิธีแก้คือ เราก็ใช้เป็น Log Scale แทนได้ เราก็เพิ่มคำสั่งด้านบนหลังจากที่เราสั่ง Plot Graph ไปแล้วก็ใช้ได้เลย

Save to Disk

ถ้าเราทำงานจริง ๆ แล้วเราต้องทำงานกับข้อมูลเยอะมาก ๆ เราอาจจะต้อง Generate ออกมาสักพัน Plot การที่เรามานั่งสั่ง plt.show() คงไม่ไหวเนอะ ไม่ต้องกลัว เพราะ Seaborn มีคำสั่งง่าย ๆ ที่ทำให้เราสามารถ Save Plot ที่เราทำขึ้นมาลง Disk ของเราได้เลย

plot.savefig('output.png')

คำสั่งง่าย ๆ คือ savefig แล้วเราก็ป้อนที่อยู่ของไฟล์รูปที่เราต้องการลงไปได้เลย มันก็จะไปสร้างไฟล์รูปที่มี Plot ที่เราทำไว้อยู่ แต่ปัญหาคือ ขนาดของไฟล์ที่ได้ออกมา บางทีมันอาจจะแอบเล็กไปหน่อย เช่นเราอาจจะต้องเอาไปใช้ในการตีพิมพ์ เราก็อยากจะได้ไฟล์ที่มันมีขนาดใหญ่หน่อย เวลาเอาไปพิมพ์แล้วมันจะได้ไม่แตก

plot.savefig('output.png', dpi=400)

เราก็สามารถเติม Argument DPI ใส่ลงไปได้เลย ยิ่งเยอะไฟล์รูปยิ่งใหญ่มากขึ้นเท่านั้น ก็แล้วแต่คนจะใส่ลงไปเลย สำหรับเรา เราใส่อย่างมากสุดก็ 300 เท่านั้นแหละ เพราะเวลาเราไปพิมพ์ออกมาจริง ๆ ชัดแค่นั้นมันก็พอแล้ว ไม่ได้คิดอะไรขนาดนั้น

สรุป : Seaborn ทำให้เรา Visualise ข้อมูลได้ง่ายขึ้นมาก

วันนี้เราก็เอาพื้นฐานของการใช้ Seaborn มาแชร์กัน จริง ๆ แล้ว แก่น ของการใช้งาน Seaborn ไม่สิ ทุกการทำ Data Visualisation จริง ๆ มันคือ การกำหนดว่าเราจะแสดงผลข้อมูลยังไงมากกว่า เพราะ Seaborn จริง ๆ ถ้าเรารู้ว่าเราอยากได้อะไร เราแค่เรียงข้อมูลให้อยู่ในรูปที่ถูกต้อง กับ Plot แบบที่เราอยากได้ และ แค่ต้องไปหาเพิ่มว่า Plot ที่เราอยากได้ มันต้องใช้คำสั่งอะไร เช่น heatmap มันก็จะมีคำสั่งของมันอยู่ สั่งไปบรรทัดเดียวได้ Heatmap เลยอะไรแบบนั้น ส่วนพวกที่ Advance หน่อย ๆ อย่างการเอา Plot หลาย ๆ อันมาทับกันมันก็ทำได้เช่นกัน แต่อาจจะต้องอาศัย Matplotlib ช่วยสักหน่อย ต้องบอกเลยว่าถ้าเรารู้ Seaborn ก็ทำให้เรา Visualise ข้อมูลง่าย ๆ ได้แล้ว ถ้าอยากได้ละเอียด สวยงามก็ไปอ่าน Matplotlib เพิ่มได้จะดีมาก

สำหรับใครที่ไม่รู้ว่า Seaborn มัน Plot อะไรได้บ้าง มันมี Example Gallery อยู่ ลองเข้าไปดูได้ ในนั้นมีตัวอย่างเยอะมาก