Author: TanJourney

  • สร้างบัญชีรายรับ-รายจ่าย คุมการเงินตัวเองง่ายๆด้วย Google Sheets

    สร้างบัญชีรายรับ-รายจ่าย คุมการเงินตัวเองง่ายๆด้วย Google Sheets

    เราเชื่อว่าหลายคนคงพบเจอปัญหานี้กับมาแล้วทั้งนั้นกับคำว่า “เดือนชนเดือน” ทำไมได้เงินเดือน เงินพิเศษมาพอถึงสิ้นเดือนก็เกือบจะหมดพอดี หรือเลวร้ายกว่านั้นคือใกล้จะหมดหลังจากได้เงินมาแปปเดียว เพราะต้องจ่ายหนี้ให้คนโน้นคนนี้บ้าง ส่งเงินให้ที่บ้านบ้าง

    แถมการรับเงินหรือจ่ายค่าโน่นค่านี่ก็กระจัดกระจายไปหมด จ่ายเงินสดบ้าง จ่ายผ่าน Application ของธนาคารเอง แถมจะปรับแต่งให้ตรงตามใจเราก็ไม่ค่อยจะได้อีก

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

    โดยเราจะใช้เครื่องมือที่ทรงพลังมากและฟรีด้วยอย่าง Google Sheets เครื่องมือสร้าง Spreadsheets ได้ฟรีแค่เพียงสมัคร Google Account (Gmail) ก็ใช้งานได้ทันที

    ข้อดีอย่างหนึ่งเลยของ Google Sheets คือ workspace ที่ใช้งานจะเป็นรูปแบบ tabular ที่มีทั้ง Rows และ Columns ที่เหมือนกับ Relational Databases ใน​ SQL เลย

    สร้างชีทใหม่ภายใน 5 วินาที

    เริ่มต้นด้วยการเปิดเว็บ browser ขึ้นมา แล้วพิมพ์ sheets.new ในช่อง URL

    ปล.ให้เวลา 2 วิในการพิมพ์ ส่วนอีก 3 วิเป็นเวลาที่เน็ตโหลดหน้าขึ้นมา 5555555++


    ตั้งชื่อชีทใหม่

    เวลาเราสร้างอะไรใหม่ๆอย่าลืมตั้งชื่อกันนะ เวลาพูดถึงเค้าจะได้จำได้ ก็เหมือนกับคนที่เราอยากรู้จักเราก็มักจะจำเค้าได้ดีจากชื่อและหน้าตา เดี๋ยววววววววววว..

    เอาเมาส์ไปคลิกที่ชื่อข้างๆโลโก้ Google Sheets แล้วพิมพ์ชื่อได้เลย


    แบ่งชีทให้ชัดเจน

    จะเห็นว่า แถบข้างล่างของ Google Sheets เราสามารถเพิ่มชีทสำหรับแบ่ง table ออกเป็นส่วนๆได้ เพื่อให้งานของเราเป็นระบบมากยิ่งขึ้น

    ดังนั้น เราจะแบ่งบัญชีรายรับ-รายจ่ายนี้ออกเป็น 4 ส่วน ได้แก่

    • INCOME = บัญชีรายรับ
    • EXPENSE = บัญชีรายจ่าย
    • COMBINED_DATA = ชีทสำหรับรวมข้อมูลรายรับ-รายจ่ายเพื่อทำ pivot table
    • DASHBOARD = ชีทรวมกราฟและแผนภูมิต่างๆในการสรุปสุขภาพการเงินของเรา สำหรับการวิเคราะห์ insights ที่ได้จากบัญชีของเรา (ปล่อยน้องเป็นหน้าเปล่าๆไปก่อน แบบทิ้งไว้กลางทาง – Potato 55555)

    ตั้งชื่อ header ให้บัญชีรายรับรายจ่าย

    การตั้งชื่อ header ในบัญชีรายรับรายจ่ายสำคัญมากๆ เหมือนเราวางโครงสร้างบ้านเราให้มั่นคง ของเราจะสร้างทั้งหมด 8 header ให้กับชีท INCOME กับ EXPENSE ก่อน ทุกคนสามารถเพิ่มเติมจากนี้ได้นะ

    • INCOME_ID/EXPENSE_ID = ลำดับที่รายการเงินเข้า-ออก
    • DESCRIPTION = รายละเอียดของรายการเงินเข้า-ออก (เหมือน note ในสลิปธนาคาร)
    • LOCATION = สถานที่ที่ได้รับเงินหรือเสียเงิน
    • CATEGORY = ประเภทของรายรับ-รายจ่าย เช่น ค่าอาหาร, ค่าเดินทาง
    • PAYMENT_METHOD = ช่องทางการรับเงิน-จ่ายเงิน เช่น เงินสด, บัญชีกสิกร, บัตรเดบิต, บัตรรถไฟฟ้า
    • DATE = วันที่รับเงิน-จ่ายเงิน (แนะนำให้ใช้ format: YYYY-mm-dd)
    • AMOUNT = จำนวนเงินที่ได้รับมา-จำนวนเงินที่จ่ายไป (บาท)
    • SOURCE = ที่มาของ transaction นั้นๆว่าเป็น INCOME หรือ EXPENSE

    Additional Tips!

    เรามี trick เล็กๆน้อยๆสำหรับการรันตัวเลข ID และใส่คำซ้ำในทุกๆแถวมาฝาก สำหรับสายขยันที่ไม่อยากเสียเวลากับงานที่ต้องทำซ้ำๆ

    เราขอแนะนำ 3 ฟังก์ชันที่จะมาช่วยแก้ปัญหานี้กันก่อน นั่นคือฟังก์ชัน IF จะรับ input 3 ตัว

    • logical_expression = เงื่อนไขที่คอยเช็คคนๆนี้ (cell) ว่าจะผ่านด่านตรวจมั้ย
    • value_if_true = ผลที่จะตามมาหากคนๆนี้ทำตามกฎ
    • value_if_false = ผลที่ตามมาหากคนๆนี้ไม่ทำตามกฎ

    นี่มันฟังก์ชันผู้คุมกฎชัดๆ

    ฟังก์ชันที่ 2 คือ ISBLANK สำหรับเช็คว่า cell นั้นเป็นช่องว่างหรือไม่

    • ถ้า cell นั้นว่าง แล้ว จะ return เป็นค่า TRUE
    • ถ้า cell นั้นไม่ว่าง แล้ว จะ return เป็นค่า FALSE

    และฟังก์ชันสุดท้ายคือ ROW สำหรับ return เป็นตัวเลขที่บอกว่า cell นั้นอยู่แถวที่เท่าไหร่

    ทุกอย่างก็พร้อมแล้ว เราจะมารันเลขในคอลัมน์ ID กัน

    เริ่มแรก ให้เราพิมพ์สูตรนี้เข้าไปที่ cell A2

    =IF(ISBLANK(F2:F)=FALSE,ROW(A2:A)-1,"")

    ภายในฟังก์ชัน IF เราสร้างเงื่อนไขว่า

    • ถ้า แถวไหนในคอลัมน์ DATE ไม่เป็นช่องว่าง แล้ว ให้นำลำดับที่ของแถวนั้นลบ 1
      เช่น ROW(A2) จะ return เป็นเลข 2 แต่ในตารางต้องระบุเป็นเลข 1 จึงต้องลบ 1 ด้วย
    • ถ้า แถวไหนในคอลัมน์ DATE เป็นช่องว่าง แล้ว ให้ cell นี้เป็นช่องว่างเหมือนเดิม

    จากนั้นให้เรากดปุ่ม command + shift + enter ใน keyboard เพื่อ apply function ArrayFormula ให้สูตรนี้รันเป็น array

    ส่วนคอลัมน์ SOURCE ใน cell H2 เราแค่แก้จาก ROW(A2:A)-1 เป็น “Income” (“Expense”) ได้เลย

    คำเตือน!! ตัวช่วยนี้จะใช้ได้ ก็ต่อเมื่อ เราชัวร์ว่าคอลัมน์ที่เราใส่ในฟังก์ชัน ISBLANK จะมีข้อมูลอยู่ครบทุกแถวจริงๆ

    ทีนี้เราลอง test ว่าใช้ได้จริงมั้ย โดยการพิมพ์วันที่ใน cell F2 ดูกัน ถ้า cell A2 ขึ้นเป็นเลข 1 และ cell H2 ขึ้นเป็นคำว่า Income แสดงว่าใช้ได้


    ตั้งค่า column วันที่ให้ใช้งานได้สะดวก

    Pain point หนึ่งเลยที่เวลาคนกรอกข้อมูลที่เป็นวันที่ น่าจะเจอปัญหาเรื่อง format ของวันที่ ที่แต่ละคนเข้าใจจะไม่ตรงกัน โดย format มาตรฐานที่แนะนำจะเป็น YYYY-mm-dd

    ขั้นตอนแรก ให้เราเอาเมาส์ไปคลิกที่ cell F2 จากนั้นกด Command + Shift + Arrow Down เพื่อ highlight cell F2 เป็นต้นไป ไม่รวม header

    Note: ใครใช้ Windows ให้เปลี่ยนจาก Command เป็น CTRL

    ขั้นตอนต่อไป ให้ไปที่แถบเมนู (menu bar) คลิก Data > Data validation จากนั้นจะขึ้นหน้าต่าง Data validation rules ขึ้นทางขวามือ

    ขั้นต่อไป กด + Add rule จะขึ้นช่อง Apply to range และ Criteria ขึ้นมา

    • Apply to range = ขอบเขตของ cell ที่เราจะ apply rule ที่เราสร้าง
    • criteria = rule ที่เราจะสร้าง ในขั้นตอนนี้เราจะเลือกเป็น is valid date เพื่อให้แน่ใจว่าวันที่นี้มีอยู่จริง ถูกต้อง และ cell ที่เราสร้าง rule นี้ขึ้นมาก็จะกลายเป็นวันที่ทั้งหมด ทำให้เวลาเรากรอกวันที่ จะโชว์เป็นปฏิทินที่เราสามารถคลิกเลือกวันที่ได้เลย

    แต่หากเราลองเล่นดูจะพบว่า.. อ่าว เฮ้ยยยย ไม่เหมือนที่คุยกันไว้นี่หน่าาา 555555 เดี๋ยวนะ วันที่ยังไม่เปลี่ยนเป็น format ที่เราต้องการเลย

    ให้ทุกคน highlight cell F2 เป็นต้นไปเหมือนเดิม จากนั้นสังเกตที่แถบเครื่องมือคลิกที่ 123 (More formats) > Custom date and time

    ในช่องซ้ายมือข้างปุ่ม Apply ให้เปลี่ยนตามนี้เลย โดยแต่ละอันคั่นด้วยเครื่องหมาย

    • Year = Full numeric year (1930)
    • Month = Month with leading zero (08)
    • Day = Day with leading zero (05)

    เสร็จแล้วกด Apply ได้ แค่นี้ก็เสร็จเรียบร้อยยยยยย

    จากนั้นก็ทำแบบเดียวกันกับชีทรายจ่ายด้วยนะ อย่าลืมเชียว!!


    สร้าง Dropdown List กับสิ่งที่ต้องใช้ซ้ำๆ

    ข้อมูลบาง column เราอาจจะต้องมีการพิมพ์ซ้ำอยู่บ่อยๆใช่มั้ย อย่างในเคสนี้ก็เป็นคอลัมน์ CATEGORY กับ PAYMENT_METHOD ที่จะมีการเรียกใช้ซ้ำทุกวัน

    ดังนั้นเราจะมาสร้าง dropdown list เพื่อที่เราสามารถมาคลิกกดเลือกได้แบบสบายๆ โดยในตัวอย่างนี้เราจะทำให้ดูเฉพาะชีทรายรับนะครับ

    ขั้นตอนแรก ให้เรา highlight cell D2 เป็นต้นไป จากนั้นสังเกตที่แถบเมนูเลือก Insert > Dropdown

    จะมีหน้าต่าง Data validation rules ขึ้นมาทางขวามือ

    • Apply to range = ขอบเขตที่เราจะใช้ dropdown นี้
    • Criteria = เลือกเป็น Dropdown จากนั้นใส่ตัวเลือกที่เราต้องใช้บ่อยๆ

    ใน column PAYMENT_METHOD ก็ทำแบบเดียวกันเลย


    Combine Data

    เราจะ combine data ทั้งรายรับและรายจ่ายเข้าด้วยกันเป็น 1 sheet เพื่อที่เราจำสามารถสร้าง pivot table ที่นำตัวเลขรายรับ-รายจ่ายมาคำนวณได้

    QUERY

    มาแล้ว!! พระเอกของงานนี้ที่จะช่วยเราดึงข้อมูลให้มารวมไว้ที่เดียว นั่นคือ ฟังก์ชัน QUERY ซึ่งจะรับ input หลักๆอยู่ 2 ตัว คือ

    • data = ข้อมูลที่เราต้องการดึง
    • query = เป็นเหมือนคำถามที่เราถามกับ data ว่าต้องการข้อมูลส่วนไหนบ้าง ซึ่ง syntax จะคล้ายกับการเขียน SQL เลย

    VSTACK vs. HSTACK

    ถ้ามีแค่ชีทเดียวเราก็ใช้ QUERY ได้แบบสบายๆเลย แต่งานนี้ไม่ง่ายเท่าไหร่ ถ้าไม่ได้นางเอกอย่าง ฟังก์ชัน VSTACK และ HSTACK มาช่วย

    สองฟังก์ชันนี้ทำหน้าที่เป็นเหมือนกาวที่ใช้เชื่อมหลายๆตารางเข้าด้วยกัน โดย VSTACK ใช้รวมตารางในแนวตั้ง และ HSTACK ใช้รวมตารางในแนวนอน ตามชื่อเป๊ะ!

    เริ่ม Combine ได้!

    ไปที่ชีท COMBINED_DATA แล้วสร้าง header ใน cell A1 ว่า TRANSACTION_ID จากนั้นใน cell A2 ใส่สูตรนี้เพื่อให้รันเลข ID แบบอัตโนมัติเหมือนกับชีทรายรับ-รายจ่าย

    =IF(ISBLANK(F2:F)=FALSE,ROW(A2:A)-1,"")

    จากนั้นใน cell B1 เราจะพิมพ์สูตรนี้ลงไป

    =QUERY(
      VSTACK(
    HSTACK("DESCRIPTION","LOCATION","CATEGORY","PAYMENT_METHOD","DATE","AMOUNT","SOURCE"),
    HSTACK(INCOME!B2:H),
    HSTACK(EXPENSE!B2:H)
      ), "select * where Col5 is not null")

    ในฟังก์ชัน QUERY เราจะอธิบายแยกเป็นสองส่วนให้เข้าใจง่ายๆนะ

    • data = เราจะเริ่มใช้ VSTACK เพื่อให้ช่วงของข้อมูลทุกอย่าง stack กันเป็นคอลัมน์ก่อน จากนั้นเราถึงจะใช้ HSTACK เพื่อรวมข้อมูลที่เป็น header และข้อมูลในตาราง
      HSTACK อันที่ 1 เราใส่เป็น header
      HSTACK อันที่ 2 เราดึงข้อมูล INCOME ทั้งหมดด้วยการ refer ไปที่ชีท INCOME
      HSTACK อันที่ 3 เราดึงข้อมูล EXPENSE ทั้งหมดด้วยการ refer ไปที่ชีท EXPENSE
    • query = เราดึงข้อมูลทุกคอลัมน์จาก data โดยที่คอลัมน์ที่ 5 (DATE) ไม่มีค่า NULL

    เท่านี้เวลามีข้อมูลใหม่ๆเข้ามาจากชีท INCOME และ EXPENSE ในชีท COMBINED_DATA จะถูก update ให้อัตโนมัติเลย


    สร้าง Pivot Table เช็คสุขภาพการเงิน

    ถ้าพูดให้เข้าใจง่ายๆ Pivot Table คือ ตารางสรุปข้อมูลจาก raw data

    โดยก่อนที่เราจะไปสร้าง pivot table กัน เรามา review คำศัพท์ใหม่สองคำนี้กันก่อนนะ

    Dimension vs. Measurement

    • Dimension คือ ข้อมูลที่เป็นจำพวก category ต่างๆ เช่น เพศ, กลุ่มลูกค้า, ชื่อเมือง
    • Measurement คือ ข้อมูลที่เป็นตัวเลขที่สามารถคำนวณได้ในทางคณิตศาสตร์ ซึ่งต้องอ้างอิงกับหลักความเป็นจริง เช่น อายุ, ราคาสินค้า, จำนวนสินค้า, ระยะทาง

    How to build a PIVOT TABLE?

    เริ่มต้นจาก highlight ข้อมูลทั้งหมด แล้วไปที่แถบเมนูคลิก Insert > Pivot table

    สังเกตว่าจะมีหน้าต่าง Create pivot table ขึ้นมาสำหรับเริ่มสร้าง pivot table

    • Data range = ข้อมูลที่เราจะใช้สรุปผลเป็น pivot table
    • Insert to = ชีทที่จะใช้โชว์ pivot table (ในตัวอย่างนี้เราเลือกเป็น New sheet)

    เสร็จแล้วกด Create ได้เลย แล้วจะมีหน้าต่าง Pivot table editor ขึ้นมาทางขวามือ ซึ่งจะแบ่งการทำงานออกเป็น 4 ส่วนให้เราต้องเข้าไปปรับแต่งกัน

    • Rows = เราจะนำ dimension มาใส่ไว้เป็นตัวหลักของแถวใน column แรกของ table
    • Columns = เหมือนกับ Rows เลยแต่จะเป็นส่วนขยายจาก column แรกอีกที
    • Values = สิ่งที่สามารถวัดค่าได้เป็นตัวเลข ส่วนใหญ่จะเป็น measurement
      แต่เราก็สามารถใส่ dimension ได้ แต่จะทำได้แค่การนับจำนวนข้อมูลเท่านั้น
    • Filters = กรองแถวสิ่งที่อยาก/ไม่อยากเห็นใน pivot table โดยการเขียนเงื่อนไข

    หากใครยังงงอยู่เรามีภาพให้ดูเข้าใจง่ายๆกัน

    ***ข้อมูลที่เรานำมาใช้จะ mock up มาให้อยู่ในช่วงเดือนกรกฎาคม-ธันวาคม 2024 นะครับ

    จำนวนรายรับ-รายจ่ายทั้งหมดที่เกิดขึ้นในบัญชี

    เริ่มต้นจาก highlight ข้อมูล COMBINED_DATA ทั้งหมดก่อน

    จากนั้นไปที่ INSERT > Pivot table โดยส่วนของ Insert to เลือกเป็น New sheet เพื่อสร้าง pivot table นี้ในชีทใหม่เลย (เราตั้งชื่อ sheet ใหม่เป็น PIVOT_TABLE)

    • Values = AMOUNT ตั้งค่าเป็น SUM (หาจำนวนเงินรวมทั้งหมด)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Income เท่านั้น

    Note: Data type ใน Google Sheets ประเภท Date จะเป็น Numeric ด้วย

    ทีนี้ในการสร้าง report อันต่อๆไปให้เรา copy report ที่ทำก่อนหน้านี้มาแปะไว้ cell ที่ว่างๆแล้วสามารถเปลี่ยน Rows, Columns, Values, Filters ได้เลย

    จากนั้น report ต่อไปให้เราตั้งค่าตามนี้ได้เลย

    • Values = AMOUNT ตั้งค่าเป็น SUM (หาจำนวนเงินรวมทั้งหมด)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Expense เท่านั้น

    สังเกตว่าเราแค่เปลี่ยน filter SOURCE จาก INCOME เป็น EXPENSE เท่านั้นเอง

    ซึ่ง report รายจ่ายรวมจะอยู่ติดกับ report รายรับรวม เพื่อง่ายต่อการทำ bar chart ที่มี bar 2 อันให้ chart เดียว สำหรับเปรียบเทียบรายรับ-รายจ่ายรวมได้ชัดเจน

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

    ตัวเลขตัวนั้นก็คือ อัตรากำไรสุทธิ (Net Profit Margin: NPM) นั่นเอง

    NPM = (รายได้รวม - รายจ่ายรวม) / รายได้รวม
    • Values = เลือกเป็น Calculated Field แล้วพิมพ์สูตรตามที่เราวางแผนไว้
    =(SUMPRODUCT(SOURCE = "Income", AMOUNT) -
      SUMPRODUCT(SOURCE = "Expense", AMOUNT)
     ) / SUMPRODUCT(SOURCE = "Income", AMOUNT)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล

    Summarise: จาก transcation ทั้งหมดพบว่า ในขณะนี้มีรายจ่ายมากกว่ารายได้ถึง 8,846.76 บาท (คิดเป็น NPM อยู่ที่ -19.88%) ซึ่งสูงมากกกกกกก ในชีวิตจริงเราอยากเห็นตัวเลขนี้เป็นบวกให้ได้มากที่สุดเท่าที่จะทำได้

    โดยเฉลี่ยเราได้เงินและใช้จ่ายต่อเดือนอยู่ที่เท่าใด

    รายรับและรายจ่ายโดยเฉลี่ยต่อเดือนจะพอให้เราคาดการณ์ในภาพรวมได้ว่า สถานะตอนนี้เรามีรายได้-รายจ่ายมากกว่ากัน

    โดยเราจะคำนวณรายได้เฉลี่ยและรายจ่ายเฉลี่ยได้จาก

    รายได้ (รายจ่าย) เฉลี่ยต่อเดือน = รายได้รวม (รายจ่ายรวม) / จำนวนเดือนที่เก็บข้อมูล
    • Values = เลือกเป็น Calculated Field แล้วพิมพ์สูตรตามที่เราวางแผนไว้
    ## ใช้ IF เช็คก่อนว่าสูตรที่เราคำนวณเป็นเดือนเดียวกันหรือไม่ (ตัวหารในสูตรคำนวณค่าเฉลี่ยเท่ากับ 0 หรือเปล่า?)
    
    = IF(MONTH(MAX(DATE)) - MONTH(MIN(DATE)) = 0, 
         SUM(AMOUNT), 
         SUM(AMOUNT) / ( MONTH(MAX(DATE)) - MONTH(MIN(DATE)) )
    )
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Income เท่านั้น

    และการคำนวณรายจ่ายเฉลี่ยต่อเดือนก็ทำแบบเดียวกับรายได้เฉลี่ยต่อเดือนเลย

    • Values = เลือกเป็น Calculated Field แล้วพิมพ์สูตรตามที่เราวางแผนไว้
    ## ใช้ IF เช็คก่อนว่าสูตรที่เราคำนวณเป็นเดือนเดียวกันหรือไม่ (ตัวหารในสูตรคำนวณค่าเฉลี่ยเท่ากับ 0 หรือเปล่า?)
    
    = IF(MONTH(MAX(DATE)) - MONTH(MIN(DATE)) = 0, 
         SUM(AMOUNT), 
         SUM(AMOUNT) / ( MONTH(MAX(DATE)) - MONTH(MIN(DATE)) )
    )
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Expense เท่านั้น

    Note: เราใช้ AVERAGE คำนวณตรงๆไม่ได้เพราะตัวหารใน AVERAGE จะใช้เป็นจำนวน transaction ที่เกิดขึ้น (จำนวน row ทั้งหมด)

    Summarise: จาก report พบว่า ในภาพรวมโดยเฉลี่ยรายรับน้อยกว่ารายจ่ายอยู่ 1,769.35 บาท ซึ่งเป็นสถานะที่ไม่ค่อยดีซักเท่าไหร่เลย

    วันไหนที่มีค่าใช้จ่ายรวมมากที่สุด

    Routine ของแต่ละคนใน 1 สัปดาห์ของใครหลายคนมักจะวน loop กันใช่มั้ย แล้วก็จะมีเหตุการณ์แบบวันนี้ของทุกสัปดาห์จะใช้เงินเยอะสุดเลย ดังนั้นเราจะมาเจาะในประเด็นนี้กัน

    • Rows = DATE
    • Values = AMOUNT ตั้งค่าเป็นแบบ SUM (หาจำนวนเงินรวมทั้งหมด)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Expense เท่านั้น

    แต่สังเกตว่ารายรับ-รายจ่ายจะยังแยกเป็นรายวันอยู่ ซึ่งเราอยากดูเป็นวันในสัปดาห์เพื่อจะหา pattern หรือ insights บางอย่างจากการใช้จ่ายของเรา

    ให้เราคลิกขวาตรงไหนก็ได้ในคอลัมน์ DATE แล้วเลือก Create pivot date group > Day of the week

    Summarise: จาก report จะเห็นว่า วันเสาร์เป็นวันที่มีการใช้เงินมากที่สุด รองลงมา คือ วันอังคารและวันอาทิตย์ ซึ่งพอจะคาดการณ์นิสัยได้ว่า วันเสาร์เป็นวันที่สามารถออกไปเที่ยวหรือไป hang out ดึกๆกับเพื่อนกับแฟนได้ ทำให้มีการใช้เงินที่ค่อนข้างเยอะกว่าวันอื่นๆ

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

    แนวโน้มรายรับ-รายจ่ายแต่ละเดือนเป็นอย่างไร

    ทุกวันนี้เรามีข้อมูลเงินเข้าเงินออกไหลเข้ามาจากที่ต่างๆเยอะมาก ทำให้เรามองด้วยตาเปล่าอาจจะไม่เห็น trend ที่ชัดเจน

    ดังนั้น การสรุปรายรับ-รายจ่ายเป็นแบบ Time Series ก็จะช่วยเราทำนายรายรับ-รายจ่ายที่พอจะเป็นไปได้ในอนาคต

    • Rows = DATE
    • Values = AMOUNT ตั้งค่าเป็นแบบ SUM (หาจำนวนเงินรวมทั้งหมด)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Income เท่านั้น

    จากนั้นคลิกขวาตรงไหนก็ได้ในคอลัมน์ DATE แล้วเลือก Create pivot date group > Year-Month

    ในส่วนของรายจ่ายก็ทำแบบเดียวกันเลย เราแค่เปลี่ยน filter SOURCE เป็น Expense

    • Rows = DATE
    • Values = AMOUNT ตั้งค่าเป็นแบบ SUM (หาจำนวนเงินรวมทั้งหมด)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Expense เท่านั้น

    จากนั้นคลิกขวาตรงไหนก็ได้ในคอลัมน์ DATE แล้วเลือก Create pivot date group > Year-Month

    แต่เนื่องจากเราจะทำ report นี้เป็น line chart ที่มีทั้งเส้นของ Total Income และ Total Expense ภายใน chart เดียวกัน

    จึงจำเป็นที่เราจะต้องรวม report ทั้งสองอันนี้เป็น 1 report ด้วยการใช้ฟังก์ชัน QUERY โดยเราจะเลือกทุกคอลัมน์ยกเว้นคอลัมน์ R เพื่อให้ report เหลือแค่ 1 dimension และ 2 measurements

    Summarise: จาก report จะเห็นว่าช่วง Q3 2024 (Jul-Sep 2024) สถานะการเงินค่อนข้างที่จะแย่มากๆเพราะมีรายจ่ายเยอะกว่ารายรับที่สูงมากๆ แต่พอถึงช่วง Q4 2024 (Oct-Dec 2024) สถานการณ์เริ่มกลับมาดีขึ้นบ้าง แต่ภาพรวมในครึ่งปีหลังค่อนข้างน่าเป็นห่วงสุดๆ

    คำนวณรายรับ-รายจ่ายรวมแบ่งตาม CATEGORY

    การที่เราเห็นรายรับของเราว่ามาจากแหล่งไหนบ้าง จะบ่งบอกถึงการทำงานของเราและ routine ในแต่ละวันของเราได้ประมาณนึงเลย

    • Rows = CATEGORY ตั้งค่าให้ Total Income เป็นแบบ Descending
    • Values = AMOUNT ตั้งค่าเป็นแบบ SUM (หาจำนวนเงินรวมทั้งหมด)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Income เท่านั้น

    Summarise: จาก report พบว่า รายได้ส่วนใหญ่มาจากค่าจ้างและครอบครัวเป็นหลัก ซึ่งพอจะบอกได้ว่าคนๆนี้น่าจะทำอาชีพ freelance เพราะไม่มีรายได้จากเงินเดือนเลย

    การแยกค่าใช้จ่ายเป็น category ให้ชัดเจนจะทำให้รู้ถึงพฤติกรรมการใช้ชีวิตของเราได้เป็นอย่างดีว่าเงินหมดไปกับอะไรมากเป็นอันดับต้นๆ

    • Rows = CATEGORY ตั้งค่าให้ Total Expense เป็นแบบ Descending
    • Values = AMOUNT ตั้งค่าเป็นแบบ SUM (หาจำนวนเงินรวมทั้งหมด)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Expense เท่านั้น

    Summarise: จาก report พบว่า ค่าใช้จ่ายส่วนใหญ่มาจากเครื่องดื่ม ซึ่งอาจจะเป็นค่ากาแฟหรือเครื่องดื่มบางอย่างกันนะ อันนี้ก็ไม่สามารถตอบได้ 100% 55555 อันดับที่ 2 คือ ค่าเดินทาง ซึ่งพอจะตอบคาดการณ์ได้ว่าบ้าน ที่ทำงาน หรือห้างอาจจะอยู่ไกลกัน และรองลงมา คือ ค่ากิจกรรมต่างๆ เช่น บัตรคอนเสิร์ต บัตรเข้าชมงาน

    คำนวณรายรับ-รายจ่ายรวมแบ่งตาม PAYMENT_METHOD

    ในส่วนนี้จะช่วยให้เรารู้ว่าควรบริหารจัดการบัญชีและเงินที่เข้ามาให้มีระบบได้อย่างไร

    • Rows = PAYMENT_METHOD ตั้งค่าให้ Total Income เป็นแบบ Descending
    • Values = AMOUNT ตั้งค่าเป็นแบบ SUM (หาจำนวนเงินรวมทั้งหมด)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Income เท่านั้น

    Summarise: จาก report นี้เห็นได้ชัดเลยว่ามีความเป็นไปได้สูงมากๆที่คนๆนี้จะรับค่าจ้างจากการทำงานมาจากบัญชี KBANK และเงินที่ได้จากครอบครัวจะเข้ามาจากบัญชี SCB เหมือนเริ่มตรวจสอบเส้นทางการเงินได้เลย เอ๊ะ! หรือว่าเราไปทำงานสรรพากรดีนะ 555555

    และเราจะมาลองดูกันว่าเราใช้จ่ายเงินผ่านทางไหนมากที่สุดกัน!

    • Rows = PAYMENT_METHOD ตั้งค่าให้ Total Expense เป็นแบบ Descending
    • Values = AMOUNT ตั้งค่าเป็นแบบ SUM (หาจำนวนเงินรวมทั้งหมด)
    • Filters = กรอง DATE ตั้งแต่วันที่เริ่มเก็บข้อมูล และ SOURCE เป็น Expense เท่านั้น

    Summarise: ดูจาก report นี้ก็พอตอบได้เลยว่าเงินของคนๆนี้จะออกง่ายมากถ้าที่ไหนมีพร้อมเพย์ ที่นั่นต้องมีเงินของเรา 5555 (อย่างกับสโลแกนประจำตัว) และเงินอีกก้อนส่วนใหญ่จะไหลออกมาจากบัญชี KBANK อีกช่องทาง

    ข้อสังเกตของคนๆนี้ คือ รายจ่ายจากพร้อมเพย์ กับ รายจ่ายจากบัญชี KBANK (debit card + saving account) มีจำนวนเงินที่ค่อนข้างใกล้เคียงกันมากๆเลย

    ซึ่งทำให้เราเห็นอะไรบางอย่างว่า การใช้งานพร้อมเพย์และแอพ KPlus (จาก KBANK) มีความสะดวกสบาย ใช้งานง่ายใน level เดียวกัน

    อะไรก็ตามที่ดูใช้งานง่าย คนส่วนใหญ่มักจะใช้เพื่ออำนวยสะดวกให้ตัวเอง บัตรเดบิต บัตรเครดิตก็เช่นกัน 55555+


    Build Dashboard in GGSheets

    Dashboard คือ หน้าต่างแสดง chart ต่างๆจาก report หลายๆ chart มารวมให้อยู่ใน 1 หน้า สำหรับ monitor เฉพาะสิ่งที่ user ต้องการจะดูและ tracking ได้อยู่ตลอดเวลา เช่น KPI ที่บริษัทตั้งเป้าไว้, ลูกค้าที่ทำยอดขายสูงสุด, สินค้าตัวไหนขายดีสุด

    The greatest value of a picture is
    when it forces us notice what we never expected to see.

    John Tukey

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

    Chart ที่เราใช้ในการทำ dashboard นี้มีทั้งหมด 4 charts ที่ต้องมีทุกบ้าน ได้แก่

    1. Scorecard สำหรับแสดงตัวเลขสำคัญๆที่เห็นเป็นภาพรวม เช่น KPIs ของบริษัทตั้งไว้
    2. Pie chart เป็นกราฟวงกลมที่แบ่งสัดส่วนตาม dimension ที่มีไม่เยอะเกินไป
    3. Bar chart เป็นกราฟแท่งที่เหมาะกับการแสดงผลแบบเปรียบเทียบ
    4. Line chart เป็นกราฟเส้นแสดงตาม Timeline / Time Series

    ขั้นตอนแรก ให้เรา highlight report ที่เราต้องการจะสร้าง chart จากนั้นไปที่แถบเมนูคลิก Insert > Chart

    สังเกตว่า chart ของเราจะอยู่ในชีท PIVOT_TABLE แต่เราอยากได้ไปโชว์ในชีท DASHBOARD ใช่มั้ย

    ให้เรากดสัญลักษณ์ 3 จุดที่มุมขวาของ chart แล้วเลือก Copy chart จากนั้นก็ลบ chart ในหน้าชีท PIVOT_TABLE ได้เลย

    ย้ายตัวเองมาอยู่ที่ชีท DASHBOARD แล้วก็กดปุ่ม Command + V เพื่อวาง chart ได้เลย

    ส่วนที่เหลือก็เป็นการปรับแต่ง chart ของตัวเองให้ดูเข้าใจง่าย ใช้สีไม่เยอะเกินไป โดยการไปที่ 3 จุดเหมือนเดิมแล้วเลือก Edit chart

    สังเกตว่าเมนูปรับแต่งแบ่งเป็น 2 ส่วน ได้แก่

    • Setup = เลือก chart / ตั้งค่าว่าข้อมูลที่ใช้ทำ chart อยู่ที่ไหน
    • Customize = ปรับแต่งได้ตั้งแต่ตัวกราฟเอง แกนของกราฟ ข้อความที่โชว์อยู่ ซึ่งเยอะมากจนทุกคนต้องลองเล่นเลย แต่อย่าเล่นเพลินจนลืมเป้าหมายที่เราทำ dashboard นะ

    เห็นธีมสี dashboard ก็รู้เลยว่ากด public post ช่วงไหน 5555555

    สิ่งสำคัญในการทำ dashboard คือ การจัดเรียงลำดับความสำคัญของ chart ว่าเราต้องการเล่าเรื่องราวให้ user ฟังแบบใดให้ตรงใจกับ business requirement

    ซึ่งใน dashboard นี้เรากำลังจะเล่าว่า

    • ในภาพรวม ณ ตอนนี้เรามีสถานะรายได้-รายจ่ายเป็นอย่างไร จาก dashboard เห็นชัดเลยว่า สถานะการเงินติดลบ มั้ยน้าาาาาาา T T
    • ต่อมาเราก็มาลงรายละเอียดว่าในวันไหนเรามีรายจ่ายมากที่สุด เพราะ routine คนส่วนใหญ่ใน 1 สัปดาห์มักจะวนลูปเหมือนเดิม สังเกตว่าวันเสาร์มาแรงมาก อาจจะเป็นวันที่เราออกไปใช้เที่ยวเลยใช้เงินเยอะเป็นพิเศษ
    • จากนั้นลองมาดูเทรนด์ในภาพใหญ่ว่าในแต่ละเดือนแนวโน้มรายรับ-รายจ่ายเป็นอย่างไร เดือนไหนที่ดูจะติดลบ (เส้นเขียวอยู่ต่ำกว่าเส้นแดง) ก็ไปดูต่อว่าเราจ่ายกับอะไรเยอะไปรึเปล่า หรือ หาเงินมาได้น้อยเกินไป หรือสามารถแบ่งดูเป็น quarter ได้
    • หลังจากนั้นเรามาดูที่มาของรายได้-รายจ่ายของเราว่าส่วนใหญ่มาจากไหนเป็นอันดับต้นๆเพื่อควบคุมเงินของเรา สังเกตว่าในนี้ค่าเครื่องดื่มกับค่าเดินทางมาเยอะเชียว อาจจะเป็นเพราะหมดไปกับค่ากาแฟ บูสเอเนอจี้ในทุกๆวัน กาแฟมา งานเดิน 55555 หรืออาจจะเป็นค่าเครื่องดื่มบางประเภทกันนะ
    • สุดท้ายก็มาดูว่ารายได้-รายจ่ายเราเข้า-ออกจากช่องไหนกันบ้างเพื่อบริหารบัญชีของเราให้ง่ายต่อการดูแลและควบคุมพฤติกรรมของใช้ของเราต่อไป สังเกตว่า PromptPay มาเป็นอันดับ 1 เลย แสดงว่าสแกนจ่ายง่าย เงินก็ออกง่ายเลยทีนี้

    Looker Studio (Optional)

    Looker Studio เป็นเครื่องมือสร้าง dashboard ที่ทรงพลังจาก Google ซึ่งเราสามารถ dashboard ได้ง่ายกว่า Google Sheets อีก ที่สำคัญคือใช้งานฟรีแค่มี Gmail

    และเราว่าความพิเศษของ Looker Studio อยู่ที่การ import data ได้หลากหลายมาก ไม่ว่าจะเป็น Google Sheets, MS Excel, CSV file และอีกเยอะเลย แถมมีฟีเจอร์อย่าง Data freshness ด้วย

    ในการสร้าง dashboard ไม่ว่าจะเป็น Google Sheets, Looker Studio, Tableau หรือ Power BI มีอยู่ด้วยกัน 3 step ง่ายๆเลยคือ Connect > Create > Share

    Connect (Data)

    ก้าวแรกสำคัญมาก ถ้าเราไม่มี data เราก็สร้าง dashboard ไม่ได้จริงมั้ย

    ดังนั้น เราต้อง connect data เข้ามาใน Looker Studio ของเราก่อน

    ขั้นตอนแรกให้เราไปที่เว็บไซต์ https://lookerstudio.google.com/

    ให้เรากดไปที่ปุ่มรูป + Create หรือ + Blank Report เพื่อสร้าง dashboard ใหม่

    จากนั้นจะขึ้นหน้าต่างให้ Add data to report ซึ่งอย่างที่เราบอกมีให้ import data เยอะมาก แต่ครั้งนี้เราจะเลือกเป็น Google Sheets

    จากนั้นเราเลือกชีทที่เราจะใช้ทำเป็น dashboard

    • Spreadsheet = เลือกไฟล์ Google Sheets จากใน Google Drive
    • Worksheet = เลือก worksheet จากไฟล์ที่เราจะสร้าง dashboard
    • Options = เราจะเลือกว่าแถวแรกของ table เป็น headers และดึงแถวที่ถูกซ่อนและถูกกรองมาด้วย

    ถ้าเลือกเสร็จแล้ว กด Add > ADD TO REPORT ได้เลย

    และเราจะได้หน้าต่างที่พร้อมสำหรับการทำ dashboard กันแล้ว หน้าตาคล้ายๆกับที่เราทำ pivot table เลย

    ทุกคนสามารถเข้าไปอ่านคู่มือการใช้ Looker Studio เบื้องต้นได้ที่ https://support.google.com/looker-studio/answer/9171315?hl=en#zippy=%2Cinstructions

    ก่อนจะเริ่มสร้าง chart จัดเรียง dashboard เราจะพาทุกคนไปรู้จักกับ Data freshness ฟีเจอร์ที่ทำให้งานของเราเริ่มมีความ automation มากขึ้น ทำให้ data ของเราถูกอัพเดทอัตโนมัติเมื่อมี data point ใหม่ๆเข้ามา เหมือนผักผลไม้ที่ถูกแช่ในตู้เย็น สดใหม่ตลอด

    ขั้นตอนแรกให้ไปที่แถบเมนูเลือก Resource > Manage added data sources

    จากนั้นจะขึ้นหน้าต่าง data ทั้งหมดที่เราเพิ่มเข้าไปใน dashboard ในที่นี้มีอยู่ไฟล์เดียวให้ไปส่วนของ Action คลิกคำว่า EDIT

    จะขึ้นหน้าต่างข้อมูลทั้งหมดของไฟล์ data ทุกคอลัมน์, data type แต่ละอันคอลัมน์ เราสามารถเช็คและตั้งค่าตรงนี้ได้

    แต่ให้เราสังเกตขวาบนของจอจะเห็นคำว่า Data freshness ให้เราคลิกเข้าไป

    แล้วเลือกได้เลยว่าอยากจะให้ data ใน dashboard อัพเดททุกๆกี่นาทีกี่ชั่วโมง โดย default จะเป็นทุกๆ 15 นาที

    สังเกตว่า ถ้าข้อมูลเรายิ่งเยอะและเราให้ data อัพเดทบ่อยๆเท่าไหร่ dashboard เราจะยิ่งช้าไปด้วยนะ นี่จึงเป็นเรื่องที่ต้อง trade off กันนิดนึง

    Create (Chart)

    เราขอแนะนำ tools สำหรับการสร้าง chart เรียงตามลำดับการใช้งาน แบ่งเป็น 5 โซน

    1. โซนสีเหลือง เป็นส่วนของเครื่องมือที่คล้ายๆ Powerpoint เลย สามารถเพิ่มหน้า, chart, filter, เส้น/รูปร่าง ใส่ข้อความ เปลี่ยน theme
    2. โซนสีม่วง เป็น workspace ที่เราไว้ใช้ dashboard
    3. โซนสีน้ำเงิน เป็นโซนที่เราไว้เลือก chart ที่เราจะใช้
    4. โซนสีแดง เป็นส่วนที่โชว์ว่า dataset ของเรามี features อะไรอยู่บ้าง รวมถึงเราสามารถสร้าง calculated field เองได้
    5. โซนสีส้ม เป็นโซนที่เราลาก features จากโซนสีแดงมาใส่ที่ Dimension กับ Metric เพื่อสร้าง chart เหมือนกับการสร้าง pivot table ใน Google Sheets เลย และมีไว้ปรับแต่ง chart ของเรา

    สังเกตว่า การสร้าง dashboard ใน Looker Studio จะลดขั้นตอนในการสร้าง pivot table ก่อนที่จะสร้าง chart เลย แต่ถ้าอยากเปลี่ยน chart เป็น table ก็เลือกได้จากโซนสีน้ำเงิน

    Share (Dashboard)

    เราขอแชร์ตัวอย่าง dashboard ที่เราทำมากับข้อมูลชุดนี้มาให้ดูนะคร้าบ เผื่อทุกคนจะได้มีแนวทางไปปรับใช้เป็นของตัวเอง


    Epilogue

    สุดท้ายเรามีสมการหนึ่งที่ทุกคนสามารถเข้าใจได้

    สิ่งที่เราได้จากสมการข้างบนนี้เรียบง่ายมากๆ จริงมั้ย

    • หาเงินให้ได้เยอะๆ และควบคุมค่าใช้จ่ายให้น้อยที่สุด สิ่งที่ไม่จำเป็นในชีวิตมากก็ไม่ควรซื้อแล้วเงินเก็บจะเยอะแน่นอน
    • แต่ถ้าหาเงินได้เยอะ แต่ก็ใช้เยอะ อยากซื้อทุกอย่างที่อยากจะได้โดยไม่วางแผนเลย สุดท้ายเงินเก็บก็เหลือน้อยอยู่ดี

    แต่ชีวิตจริงปฏิบัติย๊ากยากกกกกจังค้าบบบบบ น้ำตาไหลนิดนึงเลย

    แต่วันก่อนเราได้ฟัง podcast คุณภาพจากช่อง THE STANDARD WEALTH อย่าง NEW GEN INVESTOR EP.25 ตั้งแต่นาทีที่ 1:35 ถึง 6:57

    ทำให้เราเปลี่ยนแนวคิดจากสมการข้างบนให้เป็นสมการนี้เลย

    เมื่อเราได้รับเงินเดือนหรือค่าจ้างมาให้วันแรก อยากให้ทุกคนออมก่อนใช้ ไม่ใช่ใช้ก่อนออม เพราะไม่มีอยู่จริง 555555

    อาจจะเริ่มซัก 5% หรือ 10% จากเงินที่เราได้มาเพื่อออมและลงทุนในระยะยาวก่อนเก็บไว้ใช้ รับรองว่ามีเงินเก็บอย่างแน่นอน

    ดังนั้น dashboard ที่ได้ลงมือทำเป็นเพียงมอนิเตอร์ที่ track ให้เรารู้ว่าค่าใช้จ่ายในส่วนไหนน้อยหรือมาก เห็นแนวโน้มที่อาจจะเกิดขึ้นได้ สำคัญคือเราต้องปรับการใช้ชีวิตให้ค่าใช้จ่ายน้อยที่สุด และหาช่องทางที่เราจะสามารถหาเงินได้มากขึ้น



    Comments

    Leave a comment


  • จากข้อมูลสู่การตัดสินใจ: วิเคราะห์ shipping ด้วย Google Sheets

    จากข้อมูลสู่การตัดสินใจ: วิเคราะห์ shipping ด้วย Google Sheets

    ตั้งแต่ที่มีการแพร่ระบาดของโรค Covid-19 ทุกคนก็ต้องกักตัวอยู่ในบ้านกันหมด จนทำให้เกิดการ work from home บ้าง หรือการสั่งอาหาร สั่งของผ่านทาง website หรือ application ต่างๆที่มีจำนวนเพิ่มมากขึ้น

    จนกระทั่งหลังจากที่ทุกคนเริ่มกลับมาใช้ชีวิตได้ตามปกติ แต่ trend เหล่านี้กลายเป็น new normal life ของใครหลายๆคนอยู่ ทำให้ธุรกิจที่เกี่ยวข้องกับการขนส่งพัสดุมีการเติบโตเป็นอย่างมาก

    จึงเป็นสาเหตุให้ปัจจุบัน ธุรกิจเหล่านี้มีข้อมูลไหลเข้ามาในระบบหลังบ้านเป็นจำนวนมากเช่นกัน ซึ่งจะดีกว่ามั้ยถ้าเราสามารถจัดการข้อมูลที่มีอยู่มากมายเหล่านี้มาสร้างให้เกิด value กับธุรกิจเรา

    ดังนั้น วันนี้เราจะมาแชร์ไอเดียในการทำ report และ dashboard เพื่อสรุปข้อมูลของเรากันง่ายๆด้วย Google Sheets โดยข้อมูลที่เราใช้จะมาจาก Lorenzo Shipping Company ในเว็บไซต์ https://data.world/thegove/lorenzo-shipping-company

    หรือใครสะดวกใช้ Excel ก็สามารถทำตามได้เหมือนกัน เพียงแต่บาง tool อาจจะใช้ชื่อและตำแหน่งของ tool จะไม่เหมือนกับใน Google Sheets ซะทีเดียวนะ : )

    1. เข้าใจและเตรียมข้อมูลก่อนเริ่มวิเคราะห์ทุกครั้ง
      1. เข้าใจโครงสร้างของข้อมูล
      2. กำจัดคนที่ไม่ใช่ด้วย outlier detection
      3. การตั้งชื่อให้ table
      4. VLOOKUP = JOIN tables in SQL
      5. ลบคอลัมน์ที่ไม่ได้ใช้ทิ้ง
      6. สร้างคอลัมน์ใหม่สำหรับชื่อคนขับรถ
    2. สร้าง reports ด้วย Pivot table
      1. ลูกค้าของเราส่วนใหญ่เป็นจัดอยู่ใน type อะไร
      2. ลูกค้าของเราส่วนใหญ่อยู่ในรัฐใด
      3. ลูกค้าที่มีจำนวน order มากที่สุด 3 คนแรกของ LTC
      4. โดยเฉลี่ยแล้วน้ำหนักของพัสดุที่ต้องไปส่งอยู่ที่เท่าใด
      5. รถบรรทุกคันไหนที่ออกไปส่งพัสดุบ่อยที่สุด
      6. Driver คนไหนที่ต้องส่งพัสดุที่หนักมากที่สุดต่อวัน
      7. จำนวนพัสดุทั้งหมดที่ต้องจัดส่ง
      8. วันและเดือนไหนของสัปดาห์ที่มีการส่งพัสดุมากที่สุด
    3. สรุป insights ที่ได้จาก reports
    4. นำ Insights มาวางแผนการบริการ
    5. จาก reports สู่ 1 dashboard
    6. More posts

    เข้าใจและเตรียมข้อมูลก่อนเริ่มวิเคราะห์ทุกครั้ง

    เข้าใจโครงสร้างของข้อมูล

    นี่คือภารกิจที่ data analyst อย่างเราต้องทำก่อนทุกครั้ง และควรทำเป็นนิสัยเลยคือ การทำความเข้าใจกับข้อมูลก่อนว่า dataset ชุดนี้เค้ามีอะไรให้เราบ้าง

    จากที่เห็น ER diagram อันนี้ จะเห็นว่า เราจะมีข้อมูลของลูกค้า รถบรรทุกที่ใช้ส่งพัสดุ คนขับรถ เมืองปลายทาง และข้อมูลที่เกี่ยวกับพัสดุ เช่น น้ำหนักพัสดุ, วันที่ส่ง เป็นต้น

    ใครที่ลองโหลด data มาแล้วจะเห็นว่าข้อมูลมีทั้งหมด 5 tables แยกกัน โดยเป้าหมายเราจะนำข้อมูลทั้งหมดมาทำให้เหลือเพียง 1 tables เท่านั้น เพื่อให้ง่ายต่อการทำ reports/dashboard

    กำจัดคนที่ไม่ใช่ด้วย outlier detection

    ใน dataset นี้เราจะลองเช็คว่าข้อมูลที่เป็นน้ำหนักพัสดุมี outlier หรือไม่ โดยการคำนวณ IQR หรือเรียกง่ายๆก็คือความยาวของกล่อง boxplot นั่นเอง ด้วยสูตรนี้เลย

    IQR = Q3 - Q1

    โดยที่ Q1 คือ Quartile ที่ 1 ของชุดข้อมูล
    และ Q3 คือ Quartile ที่ 3 ของชุดข้อมูล

    ใน Google Sheets เราสามารถหา quartile ได้ง่ายๆเลยจากสูตร

    =QUARTILE(data, quartile_number)

    หมายเหตุ: เซลล์ D2 คือ Q1 และ เซลล์ D3 คือ Q3

    จากนั้นเราจะคำนวณ lower fence และ upper fence เป็นเหมือนค่าที่จะบอกเราว่าถ้าข้อมูลต่ำหรือสูงกว่า 2 ค่านี้จะถูก detect ว่าเป็น outlier ทันทีด้วยสูตรนี้

    Lower fence = Q1 - 1.5*IQR
    Upper fence = Q3 + 1.5*IQR

    หมายเหตุ: ตัวเลข 1.5 สามารถเปลี่ยนได้ขึ้นอยู่กับความเหมาะสมที่เราจะ detect outlier

    ถ้าข้อมูลต่ำกว่า -6561 หรือสูงกว่า 18783 เราจะ remove ข้อมูลนั้นทิ้ง ซึ่งเราสามารถเช็คได้ง่ายๆจากการหาค่าต่ำสุดและสูงสุดโดยใช้สูตร MIN() และ MAX() ก่อนได้เลย

    จะเห็นว่า ค่าสูงสุดของข้อมูลชุดนี้สูงกว่า upper fence อยู่มาก
    แสดงว่า ข้อมูลชุดนี้มี outlier อย่างแน่นอน ทำให้ในขั้นต่อไปเราจะดึงข้อมูล SHIPMENT ที่มีน้ำหนักไม่เกิน upper fence

    การตั้งชื่อให้ table

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

    ดังนั้น เราจะตั้งชื่อข้อมูลแต่ละ table ก่อนเพื่อให้ง่ายต่อการเรียกใช้งาน โดยให้เรา highlight ข้อมูลของเราก่อน จากนั้นไปที่แถบ menu bar เลือก Data > Named range แล้วตั้งชื่อข้อมูลได้เลย เช่น CUSTOMERS, TRUCKS, DRIVERS เป็นต้น

    ต่อไป เราจะสร้าง sheet ใหม่ขึ้นมาเพื่อเก็บ data ที่รวมทุก tables ไว้ด้วยกัน โดยเราจะใช้ฟังก์ชันในตำนานที่ชื่อว่า QUERY ซึ่งทำหน้าที่เหมือนการเขียน SQL เลย (มีเฉพาะใน Google Sheets นะ) โดยฟังก์ชันนี้จะรับ input 2 ตัว นั่นคือ

    1. Required argument 1 ตัว คือ dataset
    2. Optional argument 1 ตัว คือ การเขียน query เพื่อดึงข้อมูลที่เราต้องการ ซึ่ง syntax ตรงนี้จะเหมือนการเขียน SQL ปกติเลย โดยอยู่ภายใต้เครื่องหมาย double quotes หรือฟันหนูที่คนไทยเรียกกัน (” “)

    เช่น เราจะดึงข้อมูลทุกคอลัมน์เลยจาก SHIPMENT แต่จะเรียงคอลัมน์เป็น
    ship_id, weight, ship_date, cust_id, truck_id, driver_id, city_id

    =QUERY(SHIPMENT, "select A,C,G,B,D,E,F where C > 0 and C <= 18783 label C 'ship_weight'")

    สังเกตว่าเขียนเหมือน SQL เป๊ะเลย แต่ต่างจาก SQL นิดนึงตรงที่

    1. ชื่อคอลัมน์จะใช้ตามตัวอักษรภาษาอังกฤษ
    2. ใช้ where clause ในการ filter เฉพาะพัสดุที่มีน้ำหนักมากกว่า 0 และมีค่าไม่เกิน upper fence
    3. การตั้งชื่อคอลัมน์ใหม่ใน SQL ปกติจะใช้ AS หรือเคาะ 1 whitespace แล้วพิมพ์ชื่อใหม่ แต่ใน Google Sheets จะใช้เป็น label clause แทน

    VLOOKUP = JOIN tables in SQL

    เราจะเชื่อม table เข้าด้วยกัน เราใช้ฟังก์ชัน VLOOKUP ซึ่งทำหน้าที่เหมือนการ JOIN tables ใน SQL เลย โดยฟังก์ชันนี้จะรับ input 4 ตัว เช่น

    =ArrayFormula(VLOOKUP(D2:D961, CUSTOMERS, {2,3,4,5,6,7,8,9}, FALSE))

    แปลให้เข้าใจง่ายๆคือ เราจะเชื่อม table SHIPMENT กับ table CUSTOMERS ด้วย column key cust_id (D2:D961) โดยเอามาเฉพาะคอลัมน์ที่ 2 ถึง 9 แบบ exact match (FALSE)

    เช่นเดียวกับ table DRIVERS, TRUCKS, CITIES เราก็ทำการ join tables เข้าด้วยกัน

    จากนั้น highlight ข้อมูลทั้งหมดแล้วกด Command+C ใน macOS (CTRL+C ใน Windows) จากนั้นคลิกขวาเลือก Paste special > Values only เพื่อเปลี่ยนสูตรที่เขียนกลายเป็นข้อมูลดิบจริงๆ

    ลบคอลัมน์ที่ไม่ได้ใช้ทิ้ง

    เราจะนำคอลัมน์ cust_id, truck_id, driver_id, city_id ที่ไม่ได้ใช้แล้วทิ้งโดยการ highlight คอลัมน์ D-G แล้วคลิกขวาเลือก Delete columns D-G

    สร้างคอลัมน์ใหม่สำหรับชื่อคนขับรถ

    ในขั้นตอนนี้เราสามารถทำก่อนหรือหลังจากที่เรา join tables แล้วก็ได้นะคร้าบ

    ขั้นตอนแรก ให้เราสร้างคอลัมน์ใหม่ที่ชื่อว่า driver_name ขึ้นมาก่อน โดยการคลิกขวาที่คอลัมน์ O แล้วเลือก Insert 1 column right

    ขั้นต่อไป เราจะสร้าง form ของชื่อคนขับรถใหม่เป็น “firstname lastname” เช่น Zochery Hicks เป็นต้น ซึ่งทำได้ 2 วิธีคือ ใช้ & ในการเชื่อม string หรือใช้ฟังก์ชัน CONCATENATE ก็ได้

    ข้อดีของวิธีนี้คือ สามารถใช้ร่วมกับ ArrayFormula ได้ เขียนสูตรแค่บรรทัดแรกจบเลย ซึ่งส่วนตัวเราชอบแบบนี้มากกว่านะ

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

    หลังจากนั้นก็คลุมข้อมูลเฉพาะคอลัมน์ที่เราทำเสร็จ แล้วคลิกขวาเลือก Paste special > Values only เหมือนเดิม ลบคอลัมน์ firstname กับ lastname ที่เราไม่ต้องใช้ด้วยนะ

    สุดท้ายก็ตั้งชื่อ tables ที่ถูกเชื่อมทั้งหมดใน sheet นี้ว่า LTC ก็เสร็จแล้วสำหรับการจัดการข้อมูล


    สร้าง reports ด้วย Pivot table

    ก่อนเราจะทำ report เราต้องทำความเข้าใจกับ concept ของ dimension และ measurement ซะก่อน

    1. Dimension คือ ข้อมูลที่เป็นจำพวก category ต่างๆ เช่น เพศ, กลุ่มลูกค้า, ชื่อเมือง
    2. Measurement คือ ข้อมูลที่เป็นตัวเลขที่สามารถคำนวณได้ในทางคณิตศาสตร์ ซึ่งต้องอ้างอิงกับหลักความเป็นจริง เช่น อายุ, ราคาสินค้า, จำนวนสินค้า, ระยะทาง

    ตัวอย่างข้อมูลที่เป็นตัวเลขในทางคณิตศาสตร์สามารถคำนวณได้ แต่ไม่ถูกหลักความเป็นจริง เช่น รหัสไปรษณีย์, ID ของลูกค้า ซึ่งคอลัมน์เหล่านี้จะเป็น measurement ได้ ก็ต่อเมื่อ ใช้การนับจำนวนรหัสไปรษณีย์ หรือ นับ ID ของลูกค้าเท่านั้น

    เราสามารถสร้าง report ได้ง่ายๆโดยฟีเจอร์ Pivot table ที่เป็นเครื่องมือทรงพลังมากของ Google Sheets/Excel โดยมีขั้นตอนง่ายๆอยู่เพียง 4 ขั้นตอนดังนี้

    1. Highlight ข้อมูลที่ต้องการใช้ในการสร้าง report
    2. ไปที่ menu bar เลือก Insert > Pivot table

    3. Google Sheets จะเปิด sheet ใหม่ขึ้นมา พร้อมกับ Pivot table editor ที่มีให้ปรับแต่ง report เราอยู่ด้วยกัน 4 ตัวเลือก (Rows, Columns, Values, Filters)
    4. หลักการทำ report เบื้องต้น คือ การนำ dimension ไปใส่ที่ Rows และนำ measurement ไปใส่ที่ Values

    ที่นี่เราก็พร้อมสำหรับการสร้าง report แล้ว เริ่มลุยกันเลย!

    ลูกค้าของเราส่วนใหญ่เป็นจัดอยู่ใน type อะไร

    การที่เรารู้ว่าลูกค้าของเราเป็นลูกค้า type ไหนก็เป็นเรื่องดีในอนาคตของธุรกิจเราว่าลูกค้าของเรานั้นมีความคิดประมาณไหน ควรออกโปรโมชั่นอะไรดีให้ตรงใจ

    โดยช่อง Rows เราจะใส่ cust_type ไป และช่อง Values ใส่ cust_name แต่ให้นับจำนวนลูกค้าแบบ COUNTUNIQUE เพราะเราจะนับลูกค้า 1 เจ้าแค่ 1 ครั้งเท่านั้น เพื่อจะได้รู้สัดส่วนจำนวนลูกค้าจริงๆในแต่ละ type

    จาก report จะเห็นว่า ลูกค้าของเราส่วนใหญ่อยู่ในกลุ่ม manufacturer และ retailer ในสัดส่วนที่ใกล้เคียงกัน

    ลูกค้าของเราส่วนใหญ่อยู่ในรัฐใด

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

    โดยช่อง Rows เราเปลี่ยนจาก cust_state และช่อง Values เหมือนกับ reports ก่อนหน้านี้เลย

    จาก report จะเห็นว่า ลูกค้าของเราส่วนใหญ่อยู่ในรัฐแคลิฟอร์เนีย (CA) แต่จำนวนลูกค้าในรัฐเทกซัส (TX) ก็ถือว่ามีจำนวนที่ไม่น้อยไปกว่ารัฐแคลิฟอร์เนียเลย

    ลูกค้าที่มีจำนวน order มากที่สุด 3 คนแรกของ LTC

    สิ่งที่เราต้องมีใน report นี้เลยคือ ชื่อลูกค้าและจำนวน order ของลูกค้าแต่ละเจ้าว่าสั่งซื้อทั้งหมดเท่าไหร่

    ดังนั้น ในช่อง Rows เราจะใส่ cust_name ลงไป ส่วนช่อง Values เราจะใส่ cust_name และตั้งค่าให้นับแบบ COUNTA

    จะเห็นว่า Top 3 ลูกค้าที่มีจำนวน order มากที่สุด คือ Ziebart, Autoware Inc, NW RV Supply

    โดยเฉลี่ยแล้วน้ำหนักของพัสดุที่ต้องไปส่งอยู่ที่เท่าใด

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

    อันนี้ง่ายมาก ใช้คอลัมน์ ship_weight มาคำนวณแบบ AVERAGE แต่เราสังเกตข้อมูล จะเห็นว่า ข้อมูลของเรามีหน่วยเป็นกรัม (g) ซึ่งตัวเลขจะดูเยอะเกินไป

    ดังนั้นในช่อง Values ให้เราคลิก Add แล้วเลือก Calculated Field

    จากนั้นเราจะพิมพ์สูตรหาค่าเฉลี่ยและแปลงหน่วยจากกรัมเป็นกิโลกรัม (kg)

    =AVERAGE(ship_weight/1000)

    หรือจะใช้สมบัติการแจกแจง (distributive property) ในคณิตศาสตร์ที่เราเคยเรียนกัน เพื่อให้การคำนวณรวดเร็วกว่าสูตรข้างบน หลอนเลย 555555555

    =AVERAGE(ship_weight)/1000

    จะเห็นว่า โดยเฉลี่ยแล้วน้ำหนักของพัสดุที่ลูกค้าส่งอยู่ที่ 6.92 กิโลกรัม

    รถบรรทุกคันไหนที่ออกไปส่งพัสดุบ่อยที่สุด

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

    โดยในช่อง Rows เราจะใช้คอลัมน์ truck_band และ truck_model_year ส่วนช่อง Values เราใช้คอลัมน์ ship_id มานับแบบ COUNT หรือ COUNTA เพื่อนับจำนวนพัสดุที่รถบรรทุกแต่ละ model ส่ง

    จะเห็นว่า รถบรรทุกที่ออกไปส่งพัสดุบ่อยที่สุด คือ Mack 2009 และสังเกตว่ารถบรรทุกคันอื่นมีจำนวนพัสดุที่ต้องส่งเท่าๆกัน

    Driver คนไหนที่ต้องส่งพัสดุที่หนักมากที่สุดต่อวัน

    เรารู้ว่า driver คนไหนมีของที่ต้องไปส่งเยอะหรือไม่เยอะ ไม่ได้อยู่ที่จำนวนพัสดุเพียงอย่างเดียว แต่ต้องคำนึงถึงน้ำหนักพัสดุโดยรวมด้วย สิ่งนี้จะพอบอกได้ว่าพนักงานคนไหนได้ปริมาณงานที่เหมาะสมหรือไม่ตามที่เราจ่ายงาน

    ซึ่งหากปริมาณงานไม่เหมาะสมก็อาจจะส่งผลต่อปัญหาต่างๆที่ตามมา เช่น สุขภาพ การปรับตำแหน่ง ความคิดที่จะลาออกของพนักงานเอง เป็นต้น

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

    =(SUM(ship_weight)/1000)/(MAX(ship_date)-MIN(ship_date))

    จะเห็นว่า คนขับที่ต้องส่งพัสดุมากที่สุดโดยเฉลี่ยต่อวัน คือ Roger McHaney, Sue Newell, Holger Nohr

    ข้อสังเกตคือ หัวหน้างานจะต้องมี baseline ที่ชัดเจนว่าแต่ละคนควรรับงานเท่าใดแล้วเปรียบเทียบกับตัวเลขใน report นี้

    จำนวนพัสดุทั้งหมดที่ต้องจัดส่ง

    หากเรารู้จำนวนพัสดุทั้งหมดที่ต้องจัดส่งอยู่ตลอดเวลาก็พอจะทำให้เราประเมินเรื่องของรายได้หรือสถานการณ์ที่อาจจะเกิดขึ้นระหว่างดำเนินกิจการได้

    อันนี้ง่ายมาก เราเพียงแค่นับคอลัมน์ ship_id ปกติเลยว่ามีกี่แถว ก็เป็นจำนวนพัสดุทั้งหมดที่ต้องจัดส่ง

    วันและเดือนไหนของสัปดาห์ที่มีการส่งพัสดุมากที่สุด

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

    เราใช้คอลัมน์ ship_date และ ship_id ในการสร้าง reports นี้ขึ้นมา แล้วใช้ COUNT ปกติกับ ship_id

    สังเกตว่า report นี้จะยังจับกลุ่มตามวันที่จัดส่งแบบรายวัน ยังไม่รวมเป็นวันจันทร์-วันอาทิตย์ หรือรวมเป็นเดือนมกราคม-ธันวาคม

    ดังนั้น ให้เราคลิกขวาที่ Shipping Day ใน report แล้วเลือก Create pivot date group > Day of the week เพื่อทำเป็น Monday-Sunday ถ้าเลือก Month ก็จะเป็น Jan-Dec โดยอัตโนมัติเลย

    ไม่ทันกะพริบตาก็มาเลย ง่ายจนงงเลยจริงๆ > <

    จะเห็นว่า วันที่มีการส่งพัสดุมากที่สุดในสัปดาห์คือ วันจันทร์
    และ เดือนที่มีการส่งพัสดุมากที่สุดของปี คือ เดือนกรกฎาคม และ ช่วง Q4 ของปี (ตุลาคม-ธันวาคม)


    สรุป insights ที่ได้จาก reports

    • ลูกค้าของเราส่วนใหญ่อยู่ในกลุ่ม manufacturer และ retailer ทางรัฐแคลิฟอร์เนีย (CA) และรองลงมาเป็นทางรัฐเทกซัส (TX)
    • Top 3 ลูกค้าที่มีจำนวน order มากที่สุด คือ Ziebart, Autoware Inc, NW RV Supply
    • น้ำหนักของพัสดุโดยเฉลี่ยที่ลูกค้าส่งอยู่ที่ 6.92 กิโลกรัม
    • รถบรรทุกที่ออกไปส่งพัสดุบ่อยที่สุด คือ Mack 2009 แต่รถบรรทุกคันอื่นมีจำนวนพัสดุที่ต้องส่งเท่าๆกัน
    • คนขับที่ต้องส่งพัสดุมากที่สุดโดยเฉลี่ยต่อวัน คือ Roger McHaney, Sue Newell, Holger Nohr แต่ภาพรวมพัสดุที่ต้องส่งต่อ 1 คนขับไม่ต่างกันมาก
    • วันที่มีการส่งพัสดุมากที่สุดในสัปดาห์คือ วันจันทร์
      และ เดือนที่มีการส่งพัสดุมากที่สุดของปี คือ เดือนกรกฎาคม และ ช่วง Q4 ของปี (ตุลาคม-ธันวาคม)

    นำ Insights มาวางแผนการบริการ

    • ทำ Loyalty Programs เพื่อรักษาฐานลูกค้าเก่า และดึงลูกค้าที่เป็น wholesaler ให้ยังใช้บริการของเรา ด้วยการเสนอโปรโมชั่นบางอย่าง เช่น การให้ส่วนลดต่างๆ หรือการมีระบบ membership
    • ปรับปรุงในด้าน Customer Support / Tracking System เพื่ออำนวยความสะดวกให้กับลูกค้าเมื่อเกิดปัญหาต่างๆที่ตามมา มีระบบที่ให้ลูกค้าสามารถติดต่อสอบถามได้ หรือการส่ง feedback กลับมาเพื่อปรับปรุงการให้บริการในครั้งต่อๆไป
    • ปรับปรุงในด้านการขนส่ง เพื่อความรวดเร็วและประหยัดต้นทุนและเวลาในการขนส่ง วางแผนการจัดระบบรถบรรทุกในช่วงที่มีพัสดุเข้ามาเป็นจำนวนมาก เช่น ในช่วงทุกวันจันทร์ของสัปดาห์ หรือช่วงไตรมาสที่ 4 ของปีนั้นๆ ซึ่งเป็นช่วงสิ้นปีที่มีการเฉลิมฉลอง ทำให้อาจจะมีการซื้อของและส่งของชิ้นนั้นในช่วงเทศกาล

    จาก reports สู่ 1 dashboard

    ได้เวลาเปลี่ยน report ที่เราสร้างกันมาให้กลายเป็น dashboard กันแล้ว เย้ๆๆ

    Dashboard คือ การนำ chart จาก report หลายๆอันมารวมให้อยู่ใน 1 หน้า โดยจะแสดงเฉพาะสิ่งที่ user ต้องการจะเห็นหรือติดตามดูอยู่ตลอดเวลา เช่น KPI ที่บริษัทตั้งเป้าไว้, ลูกค้าที่ทำยอดขายสูงสุด, สินค้าตัวไหนขายดีสุด

    หัวใจหลักของการสร้าง dashboard คือการเปลี่ยนจาก text เป็นรูปภาพ เพื่อให้คนที่เข้ามาดูข้อมูลสามารถเข้าใจได้ง่าย การจำทุกอย่างเป็นภาพย่อมง่ายกว่าตัวหนังสืออยู่แล้วจริงมั้ย

    ดังนั้น หลักการสร้าง dashboard นั้นง่ายมาก เราแค่ highlight report ที่ต้องการสร้าง chart แล้วไปที่ menu bar เลือก Insert > Chart

    เราสามารถตั้งค่าหรือปรับแต่งทุก chart ที่เราสร้าง ได้จากการคลิกที่ 3 จุดแล้วเลือก Edit chart ก็จะมีหน้าต่าง Chart editor ทางขวามือให้เราเล่นได้ เหมือนกับเราทำ presentation ใน MS PowerPoint/Keynote เลย

    Chart หลักๆที่เรามักจะใช้อยู่บ่อยๆมีทั้งหมด 4 charts ด้วยกัน

    1. Scorecard สำหรับแสดงตัวเลขสำคัญๆอย่างเช่น KPIs ของบริษัท
    2. Pie chart เป็นกราฟวงกลมที่แบ่งสัดส่วนตาม dimension ที่มีไม่เยอะเกินไป
    3. Bar chart เป็นกราฟแท่งที่เหมาะกับการแสดงผลแบบเปรียบเทียบ
    4. Line chart เป็นกราฟเส้นแสดงตาม Timeline / Time Series

    แต่ใน dashboard มีเราจะมี chart พิเศษเพิ่มมาอย่าง Treemap สำหรับสร้าง chart ที่มีคอลัมน์ที่เป็น dimension 2 คอลัมน์และ measurement อีก 1 คอลัมน์

    โดยเราจะต้องเปลี่ยนหน้าตา report ที่แสดงความสัมพันธ์ระหว่างรถบรรทุกกับจำนวนพัสดุที่ต้องส่งเป็นแบบนี้ก่อนที่จะเริ่มสร้าง treemap ก่อนนะครับ

    และเราก็จะได้ dashboard สำหรับ tracking สิ่งที่เราสนใจในธุรกิจของเราเรียบร้อย!

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

    หากใครรู้สึกว่าการสร้าง dashboard ใน Google Sheets ยังตั้งค่าหรือปรับแต่งได้ไม่จุใจ เราขอแนะนำให้ลองใช้ Looker Studio หรือ Tableau Public สามารถใช้งานได้ฟรีเหมือนกัน

    ส่วนตัวเราชอบ Looker Studio ที่สุดเลย ปรับแต่งได้เยอะ ใช้งานง่าย ถ้าเทียบกับ free version กับ software ตัวอื่น 5555555

    สุดท้ายนี้เหมือนเดิม ถ้าชอบฝากกด like ใช่กด share ให้เพื่อนของทุกๆคนได้อ่านต่อกันด้วยนะ บทความหน้าจะเป็นเรื่องอะไร รอติดตามกันได้เลยค้าบ : )


    Comments

    Leave a comment

  • Coffee & Code: สร้างฐานข้อมูลคาเฟ่พร้อมหา insight ช่วยธุรกิจ

    Coffee & Code: สร้างฐานข้อมูลคาเฟ่พร้อมหา insight ช่วยธุรกิจ

    ในธุรกิจหลายๆเจ้าไม่ว่าจะเป็นร้านอาหาร, ร้านกาแฟ, retail หรือจะเป็นบริษัทต่างๆที่มีพนักงาน มี product/service ที่ต้องขายให้กับลูกค้า เกือบจะทุกวงการจะต้องมีการเก็บข้อมูลทุกอย่างเอาไว้เพื่อเป็นหลักฐาน

    ประเด็นคือเราเคยจัดการกับข้อมูลเหล่านี้ให้เป็นระเบียบและเป็นระบบหรือเปล่า มีข้อมูลเยอะแต่เคยเอาข้อมูลเหล่านั้นมาวิเคราะห์เพื่อสร้าง value ให้กับธุรกิจเราต่อมั้ย

    สำหรับธุรกิจขนาดเล็กอาจจะไม่จำเป็นต้องทำฐานข้อมูล (database) ก็ได้ แต่ในธุรกิจขนาดกลางจนถึงขนาดใหญ่น่าจะต้องมีอย่างแน่นอน

    ถ้าธุรกิจไม่ว่าจะขนาดไหนหากไม่มี database ก็เหมือนไม่มี resource ที่จะอาศัยอยู่ได้หรืออยู่ได้แบบลำบาก

    ในยุคที่มีเทคโนโลยีและ AI ที่เริ่มมาไกลมากๆ คงจะเสียเปรียบที่ธุรกิจเราจะเติบโตขึ้นมากๆเมื่อเทียบกับคู่แข่งเจ้าอื่นที่พร้อมจะปรับตัวให้ทันโลก

    ดังนั้น วันนี้เราจะมาให้ทุกคนเห็นวิธีสร้าง/จัดการ/วิเคราะห์ database อย่างง่ายกัน เพื่อที่ทุกคนจะสามารถไปปรับใช้กับธุรกิจหรือชีวิตของตัวเองได้

    1. ออกแบบ database ให้ดี
    2. สร้างไฟล์ database
    3. ทำความรู้จักกับ SQL
    4. สร้าง table เพื่อเก็บ data
      1. สร้าง table สำหรับเก็บข้อมูล
      2. Modify กับ table ที่เรามีง่ายๆด้วย ALTER
      3. Insert ข้อมูลลง database
      4. Update ข้อมูลเพิ่มเติม
      5. Delete data ที่เราไม่ต้องการ
      6. Delete table ที่เราไม่ต้องการ
    5. เจาะ data หา insights!
      1. การ join tables โดยใช้ WHERE clause
      2. Subqueries
      3. Common Table Expression (CTEs)
    6. More posts

    ออกแบบ database ให้ดี

    การออกแบบ database ให้ดีก็เหมือนออกแบบบ้านให้ดีซักหลังนึง เราอยากจะมีบ้านที่มีโครงสร้างแข็งแรง อยู่กับเราได้นานๆไม่ว่าจะเจอสภาพอากาศแบบไหนก็ทนได้

    ***เราก็ต้องเข้าใจก่อนด้วยว่าผู้ที่จะเข้ามาอาศัยในบ้านหลังนี้เป็นคนแบบไหน daily routine เป็นอย่างไร เพื่อให้การออกแบบตอบโจทย์ลูกบ้านด้วย

    ดังนั้น สิ่งสำคัญเป็นอันดับแรกเลยคือ ทำความเข้าใจธุรกิจของตัวเองซะก่อนว่า ภายในธุรกิจเรามีโครงสร้างและการทำงานภายในและภายนอกองค์กรเป็นอย่างไร

    จากนั้นเราก็มาออกแบบว่าใน database เราจะเก็บข้อมูลอะไรบ้าง ควรแบ่งข้อมูลให้ดี เหมือนกับการ partition บ้านออกเป็นแต่ละห้อง ถ้าแบ่งไม่ดีเวลาเราจะหาของชิ้นไหนก็หาไม่เจอ ดังนั้นบ้านหลังนี้จะเป็นระเบียบหรือรกก็ขึ้นอยู่กับเราแล้วนะ

    ในบทความนี้เราลองสร้าง 4 tables เพื่อให้เห็นภาพ ยิ่งธุรกิจเราใหญ่มีความซับซ้อนมาก จำนวน tables ก็เยอะตามไปด้วยนะ

    • menus เพราะลูกค้ามาร้านเราก็อยากมาสั่งเครื่องดื่ม ขนมใช่มั้ย เป็น table ที่ขาดไม่ได้เลย
    • staffs ร้านจะขาดพนักงานไม่ได้เลย ไม่อย่างนั้นใครจะเป็นช่วยรันงานในร้านให้เรา ;-;
    • customers และร้านจะขาดลูกค้าไม่ได้เช่นกัน ลูกค้าคือพระเจ้า กำไรธุรกิจจะมากหรือน้อยก็ขึ้นอยู่กับตัวแปรนี้เลย
    • transactions สิ่งที่เก็บข้อมูลระหว่างลูกค้า รายการที่ลูกค้าสั่ง และพนักงานที่รับผิดชอบ ก็คือ บิล/ใบเสร็จที่จะเป็นหลักฐานให้เราเช็คย้อนหลังได้

    แล้วทุกคนล่ะ คิดว่าในธุรกิจเกี่ยวกับคาเฟ่ ร้านกาแฟควรมี table อะไรเพิ่มเติมอีกนะ

    โดยสิ่งที่ช่วยให้เราเห็นภาพรวมของ database เราได้ดีขึ้น นั่นคือ ER diagram ย่อมาจาก Etity-Relationship diagram

    • Etity ก็หมายถึง table ทั้งหมดใน database
    • Relationship ก็คือ ความสัมพันธ์ระหว่าง table หนึ่งกับ table หนึ่ง ซึ่งความสัมพันธ์ก็มีหลายแบบ โดยส่วนใหญ่จะเป็นแบบ one-to-many

    ER diagram แสดงความสัมพันธ์สำหรับทุก table ในไฟล์ my_cafe.db

    Note: แต่ละ table ควรจะมีหนึ่งคอลัมน์เป็น id ของ table นั้นๆสำหรับการ join tables เข้าด้วยกัน

    ทุกคนสามารถลองออกแบบ database ของตัวเองได้ง่ายๆที่ dbdiagram.io บนเว็บ browser ฟรีๆ ใช้งานง่าย ทำเสร็จโหลดออกมาเป็นไฟล์ .pdf หรือ .png ไปใช้งานต่อได้เลย


    สร้างไฟล์ database

    เราจะสร้าง database ผ่านเว็บ browser ที่มีชื่อว่า replit.com กัน ใช้งานฟรีด้วย (แต่สร้างได้แค่ 3 projects น้า)

    สมัคร account เสร็จแล้ว กด Create Repl แล้วเลือก SQLite ได้เลย

    Keyword ที่ใช้ในการสร้างไฟล์ database คือ .open แล้วตามด้วยชื่อไฟล์ โดยนามสกุลไฟล์เป็น .db เช่น

    .open ports_coffee.db

    หรือใครอยากจะลองติดตั้ง software ลง local computer / laptop เป็นของตัวเอง เราขอแนะนำเป็น DB Browser for SQLite โหลดใช้ได้ฟรีทั้ง Windows / macOS เลย


    ทำความรู้จักกับ SQL

    SQL ย่อมาจาก Structured Query Language เป็นภาษาที่เราใช้สำหรับสื่อสารระหว่างเรากับ database เพื่อจัดการและดึงข้อมูลที่เราต้องการออกมาจาก database

    โดย SQL จะมีอยู่หลายแบบ ไม่ว่าจะเป็น SQLite, MySQL, PostgreSQL, Microsoft SQL Server เป็นต้น โดยตัวที่เราเลือกจะเป็น SQLite ซึ่งเป็น standard SQL เหมาะสำหรับผู้เริ่มต้นเรียนภาษา SQL


    สร้าง table เพื่อเก็บ data

    สร้าง table สำหรับเก็บข้อมูล

    ถ้า เราบอกว่า database เปรียบเสมือนบ้าน 1 หลัง แล้ว table กับ data ก็เป็นเหมือนห้องต่างๆภายในบ้าน และ เฟอร์นิเจอร์ในแต่ละห้องที่ถูก partition แล้วนั่นเอง

    ดังนั้น database หลังนี้จะดีหรือไม่ดีก็ขึ้นอยู่กับการวางแผนของเราด้วย ก็เหมือนกับบ้านของเรา ถ้าแบ่งสัดส่วนแต่ละห้องได้เหมาะสมและเลือกเฟอร์นิเจอร์ได้ดี บ้านเราก็น่าอยู่ ใช้งานได้ไปอีกนาน

    โดย syntax ในการสร้าง table เราจะใช้ keyword ดังนี้

    CREATE TABLE table_name (
       column_name1 data_type,
       column_name2 data_type,
       .
       .
       .
    );

    Data type ที่เราใช้กันเป็นส่วนใหญ่ ได้แก่

    • int คือ จำนวนเต็ม (Integer)
    • real / float คือ จำนวนที่สามารถมีทศนิยมได้ ในทางคณิตศาสตร์ คือ Real Number
    • text / varchar คือ ข้อความซึ่งอยู่ภายใต้เครื่องหมาย double quote (“…….”)
    • date / datetime คือ วันและเวลา
    -- create table
    CREATE TABLE menus (
      menu_id int PRIMARY KEY,
      name text,
      price real,
      category text
    );
    
    CREATE TABLE staffs (
      staff_id int PRIMARY KEY,
      name text,
      position text
    );
    
    CREATE TABLE customers (
      customer_id int PRIMARY KEY,
      name text
    );
    
    CREATE TABLE transactions (
      transaction_id int PRIMARY KEY,
      customer_id int,
      staff_id int,
      menu_id int,
      quantity int,
      invoicedate date 
    );

    Modify กับ table ที่เรามีง่ายๆด้วย ALTER

    ALTER เป็น keyword ที่ใช้สำหรับปรับแต่ง table ได้ เช่น add new columns, rename tables, rename columns

    1. เพิ่มคอลัมน์ใหม่ใน table ที่มีอยู่

    Syntax ในการ add new columns

    ALTER TABLE table_name
    ADD column_name_to_added data_type;

    ตัวอย่างการใช้งาน เช่น เราอยากจะเพิ่ม column hiredate ลงไปใน table staffs

    ALTER TABLE staffs
    ADD hiredate date;

    2. เปลี่ยนชื่อ table ที่มีอยู่

    Syntax ในการ rename tables

    ALTER TABLE old_table_name
    RENAME TO new_table_name;

    ตัวอย่างการใช้งาน เช่น เราอยากเปลี่ยนชื่อ table customers เป็น employees

    ALTER TABLE customers
    RENAME TO employees;

    3. เปลี่ยนชื่อคอลัมน์ที่มีอยู่

    Syntax ในการ rename columns

    ALTER TABLE table_name
    RENAME old_column_name TO new_column_name;

    ตัวอย่างการใช้งาน เช่น เราอยากเปลี่ยนชื่อ column name ใน table customers เป็น nickname

    ALTER TABLE customers
    RENAME name TO nickname;

    Insert ข้อมูลลง database

    ขั้นต่อไป ถ้าสร้างบ้าน แบ่งห้องแล้ว แต่ไม่มีเฟอร์นิเจอร์ก็อยู่ไม่ได้สิใช่มั้ย
    ดังนั้น เราจะมาใส่ data ลงไปในแต่ละ table กัน โดยการใช้คำว่า INSERT INTO กัน

    Syntax ในการเพิ่มข้อมูลลง table

    INSERT INTO table_name VALUES 
    (row1_value1, row1_value2, ...),
    (row2_value1, row2_value2, ...),
    .
    .
    .

    ตัวอย่างการเพิ่มข้อมูลเมนูทั้งหมดในคาเฟ่ของเรา

    -- insert data
    INSERT INTO menus VALUES 
      (1,'Single Espresso',60,'coffee'),
      (2,'Double Espresso',70,'coffee'),
      (3,'Hot Americano',80,'coffee'),
      (4,'Iced Americano',90,'coffee'),
      (5,'Hot Latte',90,'coffee'),
      (6,'Iced Latte',100,'coffee'),
      (7,'Hot Cappuccino',90,'coffee'),
      (8,'Iced Cappuccino',100,'coffee'),
      (9,'Hot Mocha',100,'coffee'),
      (10,'Iced Mocha',110,'coffee'),
      (11,'Hot Caramel Macchiato',100,'coffee'),
      (12,'Iced Caramel Macchiato',110,'coffee'),
      (13,'Thai Milk Tea',90,'non_coffee'),
      (14,'Matcha Latte',100,'non_coffee'),
      (15,'Hojicha Latte',100,'non_coffee'),
      (16,'Dark Chocolate',100,'non_coffee'),
      (17,'Yuzulemonade Sparkling',100,'non_coffee'),
      (18,'Honey Lemon Tea',100,'non_coffee'),
      (19,'Honey Lemon Sparkling',100,'non_coffee'),
      (20,'Dirty',110,'special_drink'),
      (21,'Orangano',100,'special_drink'),
      (22,'Dalgona Latte',120,'special_drink'),
      (23,'Sesame Latte',120,'special_drink'),
      (24,'Einspanner',120,'special_drink'),
      (25,'Canele',75,'dessert'),
      (26,'Butter Croissant',80,'dessert'),
      (27,'Butter Chocolate Croissant',95,'dessert'),
      (28,'Croffle',85,'dessert'),
      (29,'Lemon Cake',95,'dessert'),
      (30,'Choc Chip Cookie',85,'dessert'),
      (31,'Pain Aux Raisin',95,'dessert'),
      (32,'Pain Aux Chocolate',95,'dessert');

    ตัวอย่างการเพิ่มข้อมูลพนักงานทุกคนในคาเฟ่

    INSERT INTO staffs VALUES 
      (1,'Pon','CEO'),
      (2,'James','Manager'),
      (3,'Tuanote','Senior Barista'), 
      (4,'Ice','Senior Barista'),
      (5,'Bee','Accounting'),
      (6,'Fern','RD'),
      (7,'Nut','Marketing'),
      (8,'Ling','HR');

    ตัวอย่างการเพิ่มข้อมูลลูกค้าทุกคนในคาเฟ่

    INSERT INTO customers VALUES
      (1,'Tan'),
      (2,'Peach'),
      (3,'Jane'),
      (4,'Dith'),
      (5,'Kao'),
      (6,'Wa'),
      (7,'Tee'),
      (8,'Pan'),
      (9,'New'),
      (10,'Toey'),
      (11,'Fai'),
      (12,'Dew'),
      (13,'Boss'),
      (14,'Ta');

    ตัวอย่างการเพิ่มข้อมูลรายการสั่งซื้อทุกรายการในคาเฟ่

    INSERT INTO transactions VALUES
      (1,9,5,10,1,'2024-06-22'),
      (2,10,2,15,3,'2024-06-22'),
      (3,4,4,28,1,'2024-06-22'),
      (4,2,4,13,3,'2024-06-22'),
      (5,13,5,11,1,'2024-06-22'),
      (6,8,4,5,1,'2024-06-22'),
      (7,8,5,12,1,'2024-06-23'),
      (8,8,4,24,2,'2024-06-23'),
      (9,3,4,32,3,'2024-06-23'),
      (10,1,4,4,2,'2024-06-23'),
      (11,2,5,27,1,'2024-06-23'),
      (12,3,4,20,2,'2024-06-24'),
      (13,7,2,17,1,'2024-06-24'),
      (14,13,3,30,1,'2024-06-24'),
      (15,8,2,9,1,'2024-06-24'),
      (16,13,4,27,3,'2024-06-25'),
      (17,8,4,12,2,'2024-06-25'),
      (18,1,2,12,1,'2024-06-25'),
      (19,1,3,14,1,'2024-06-27'),
      (20,5,4,19,3,'2024-06-28'),
      (21,9,2,1,1,'2024-06-28'),
      (22,14,1,26,2,'2024-06-28'),
      (23,14,4,3,1,'2024-06-29'),
      (24,4,4,5,3,'2024-06-29'),
      (25,12,4,20,3,'2024-06-29'),
      (26,12,1,26,3,'2024-06-29'),
      (27,6,3,21,3,'2024-06-29'),
      (28,7,2,21,1,'2024-06-30'),
      (29,2,1,19,1,'2024-06-30'),
      (30,14,4,22,1,'2024-06-30');

    หากต้องการแก้ไขข้อมูลหลังจากขั้นตอนนี้ ให้ใช้ keyword ในหัวข้อถัดไป

    Update ข้อมูลเพิ่มเติม

    ในบางครั้ง เราก็อาจจะใส่ข้อมูลผิด เช่น พิมพ์ชื่อพนักงานผิดไปตัวอักษรนึง กรอกราคาสินค้าผิด ทุกอย่างล้วนเกิดขึ้นได้จาก human error

    Syntax ในการ update data ใน table

    UPDATE table_name
    SET column_name1 = value1, column_name2 = value2
    WHERE condition;

    เช่น เราต้องการเปลี่ยนชื่อเมนูจาก Hot Latte เป็น Hot Caffe Latte ซึ่งเป็นข้อมูลจาก table menus ที่มี menu_id = 5 พร้อมปรับขึ้นราคาจาก 90 บาทเป็น 95 บาท

    UPDATE menus
    SET name = "Hot Caffe Latte", price = 95
    WHERE menu_id = 5;

    Delete data ที่เราไม่ต้องการ

    Syntax ในการลบข้อมูลออกจาก table

    DELETE FROM table_name WHERE condition;

    เช่น ณ วันนี้มีพนักงานคนหนึ่งที่ชื่อ Fern แผนก RD ลาออก เราเลยต้องนำข้อมูลของพนักงานคนนี้ออกจาก table staffs

    DELETE FROM staffs WHERE name = "Fern"

    Delete table ที่เราไม่ต้องการ

    สร้าง table ได้ ก็ต้องลบได้ บางครั้งเราอาจจะเผลอสร้าง table นั้นขึ้นมาโดยไม่ได้ตั้งใจ ดังนั้น เราจึงขอแนะนำวิธีการลบ table ที่ easy มากๆแค่ keyword เดียวเลย นั่นคือ

    DROP TABLE table_name;

    ตัวอย่างเช่น เราจะสร้าง table ที่ชื่อว่า branch ไปใส่ใน database เฉยเลย ทั้งที่จริงคาเฟ่เรามีแค่สาขาเดียว ร้องไห้แล้ว ;-;

    CREATE TABLE branches (
      branch_id int PRIMARY KEY,
      name text,
      address text,
      street text,
      sub_district text,
      district text,
      province text,
      country text,
      latitude real,
      longitude real
    );
    DROP TABLE branches

    เห็นมั้ยว่าง่ายนิดเดียวเอง หมายถึง ทิ้งของที่เค้าให้มาง่าย แต่สร้างความสัมพันธ์ให้เค้ากลับมาหาอะยาก เดี๋ยวๆๆๆๆเริ่มออกทะเลไปไกลละ ;-;


    เจาะ data หา insights!

    เมื่อเรามีบ้านที่มั่นคงแข็งแรง มีห้องและเฟอร์นิเจอร์ต่างๆพร้อมใช้งานกันแล้ว หลังจากนี้ก็ถึงเวลาสร้างครอบครัวที่มีความสุขและอบอุ่นกันแล้ว นั่นก็คือ การสร้าง value กลับมาให้ธุรกิจของเรา โดยการหา insight จาก data นั่นเอง

    และ insight ที่ดี มักเริ่มต้นจากการตั้งคำถามที่ดี โดยเทคนิคที่เราจะใช้หา insight กันในครั้งนี้ เราจะใช้อยู่ด้วยกัน 3 เทคนิคด้วยกัน

    การ join tables โดยใช้ WHERE clause

    โดยปกติการ join tables ใน SQL เราจะใช้คำว่า JOIN ON เป็นหลัก ตัวอย่างเช่น

    SELECT * FROM customers AS cu 
    JOIN transactions AS tr
    ON cu.customer_id = tr.customer_id

    แต่เราสามารถปรับ syntax ด้านบนมาเป็นตัวอย่าง code ด้านล่างได้

    SELECT * 
    FROM customers AS cu,
         transactions AS tr
    WHERE cu.customer_id = tr.customer_id

    Code ของเราสั้นลงเยอะเลย แถมได้ result เหมือนกันเป๊ะ!
    ต่อจากนี้เดี๋ยวเรามาหา insight จาก data ที่เรา mock up ไว้แล้วด้วยวิธีนี้กัน

    1. เมนูที่ขายดีที่สุด 3 อันดับแรกของคาเฟ่นี้

    สิ่งที่เราอยากจะได้ใน query result นี้คือ ชื่อเมนู (menus.name) และ ยอดขายรวมทั้งหมดในแต่ละเมนู

    แต่เนื่องจาก ยอดขายทั้งหมด (total sales) จะเกิดจากผลรวม (SUM) ของราคาขาย (menus.price) x จำนวนที่ขายได้ (transactions.quantity)

    ทำให้เราต้อง join table menus กับ table transaction ด้วยคีย์ที่เป็น menu_id นั่นเอง และจับกลุ่มยอดขายตามชื่อเมนู เรียงข้อมูลจากมากไปน้อยตามยอดขาย

    -- Top 3 Most Popular Menus at the cafe
      
    SELECT 
      me.name AS Menu_Name,
      SUM(me.price * tr.quantity) AS Total_Sale
    FROM menus AS me, 
         transactions AS tr
    WHERE tr.menu_id = me.menu_id
    GROUP BY 1
    ORDER BY 2 DESC
    LIMIT 3;

    จาก result ที่ได้ จะเห็นว่า Dirty ขายดีที่สุด รองลงมา คือ Iced Caramel Macchiato และ Orangano (iced americano + orange juice)

    2. วันไหนในเดือนมิถุนายน 2024 ที่มียอดขายต่ำที่สุด

    Case นี้จะคล้ายๆกับการ query ก่อนหน้านี้เลย แต่เปลี่ยนการจับกลุ่มตามชื่อเมนูเป็นวันที่ในเดือนมิถุนายน 2024 และเรียงยอดขายจากน้อยไปมาก

    ใน query นี้จะมีฟังก์ชันที่ใช้ดึงค่าต่างๆกับข้อมูลที่เป็น date ด้วย นั่นคือ STRFTIME()

    -- Which day in June 2024 had the lowest sales?
    
    SELECT
      STRFTIME('%d', invoicedate) AS Day_of_June_2024,
      SUM(price * quantity) AS Total_Sale
    FROM transactions AS tr, menus AS me
    WHERE tr.menu_id = me.menu_id
    GROUP BY 1
    ORDER BY 2;

    จาก result จะเห็นว่า วันที่ขายได้น้อยที่สุดของเดือนมิถุนายน คือ วันที่ 27 รองลงมา คือ วันที่ 30 และวันที่ 24

    3. พนักงานที่ทำยอดขายได้มากที่สุดในช่วงวันที่ 22-30 มิถุนายน 2024

    สังเกตว่า สำหรับการ query ใน case นี้ สิ่งที่ต้องเปลี่ยนจาก query เดิมคือ ชื่อพนักงาน (staffs.name) และต้องจับกลุ่มตามพนักงานแต่ละคน

    ทำให้การ query รอบนี้ต้อง join 3 tables พร้อมกัน โดยใช้คีย์ staff_id เพิ่มเข้าไปจากเดิม (ถ้าเขียน JOIN ON ปกติ code เราจะยาวมาก T T)

    จากนั้นเราเพิ่มเงื่อนไขใน WHERE clause เข้าไปให้ข้อมูลอยู่ในช่วงวันที่ 22-30 มิถุนายน 2024 อีกนิดก็เรียบร้อย

    -- Employees with the Highest Sales (June 26-29, 2024)
    
    SELECT 
      st.name                     AS Staff_Name,
      SUM(me.price * tr.quantity) AS Total_Sale
    FROM staffs AS st,
         transactions AS tr,
         menus AS me
    WHERE st.staff_id = tr.staff_id AND tr.menu_id = me.menu_id
    AND (invoicedate BETWEEN '2024-06-22' AND '2024-06-30')
    GROUP BY 1
    ORDER BY 2 DESC;

    จาก result จะเห็นว่า Ice เป็นคนที่ทำยอดขายในช่วงวันที่ 22-30 มิถุนายน 2024 ได้มากที่สุด รองลงมา คือ James และ Pon

    Subqueries

    ถ้าให้พูดง่ายๆการเขียน subqueries คือ การเขียน query ซ้อน query

    ในการเขียน query บางครั้ง เราจำเป็นต้องรัน query มากกว่า 1 query เพื่อให้ได้ result ที่เราต้องการ แต่จริงๆเราสามารถใช้ subqueries เขียนจบในครั้งเดียวเลย

    รูปภาพจากหนังสือ Practical SQL Data Analytics Series Final version 2.0 – DataRockie

    หลักการทำงานของ subqueries คือ code จะรันจาก inner query ชั้นในสุดก่อนไล่ไปเรื่อยๆจนถึง query ชั้นนอกสุด (outer query)

    โดยส่วนใหญ่เรามักจะ subqueries ได้ที่ WHERE, FROM, JOIN และ SELECT clause ซึ่งตำแหน่งที่มักจะเจอง่ายที่สุดคือ WHERE clause

    แต่จากแผนภาพเราน่าจะเห็นข้อเสียของวิธีนี้แล้ว คือ ถ้ามี query มากเกินไป อาจจะทำให้ code เราอ่านยาก แก้ไขยากมาก

    1. Top Customer 5 คนที่มาคาเฟ่บ่อยที่สุดตั้งแต่วันที่ 25 มิถุนายน 2024

    สิ่งที่เราต้องทราบก่อนเลยคือ จำนวนที่ลูกค้าแต่ละคนเข้ามาใช้บริการ​
    ซึ่งสามารถเขียน query ได้จาก table transactions ตามปกติเลย

    SELECT 
      customer_id, 
      COUNT(*) 
    FROM transactions AS tr
    WHERE tr.invoicedate >= '2024-06-25'
    GROUP BY 1
    ORDER BY 2 DESC
    LIMIT 5;

    แต่สิ่งที่เราอยากรู้จริงๆคือใครคือ 5 คนนั้นบ้าง นั่นคือ ชื่อลูกค้าทั้ง 5 คน
    ทำให้ตอนเรา SELECT ชื่อลูกค้ามา เราจะฟิลเตอร์เฉพาะลูกค้าที่มี id ตาม result ข้างบนนี้

    -- Top 5 customers with the most visits since June 25, 2024
    
    SELECT
      cu.name AS Customer_Name
    FROM customers AS cu
    WHERE customer_id IN (
       SELECT customer_id FROM (
           SELECT customer_id, COUNT(*) 
           FROM transactions AS tr
           WHERE tr.invoicedate >= '2024-06-25'
           GROUP BY 1
           ORDER BY 2 DESC
           LIMIT 5
           )
    );

    สังเกตว่า query นี้ จะเริ่มรันจาก inner query สีเหลืองก่อน แล้วไล่ไปที่ inner query สีม่วง จนถึง outer query ชั้นนอกสุด

    จาก result จะเห็นว่า ลูกค้า 5 คนที่มาใช้บริการบ่อยที่สุด คือ Tan, New, Dew, Boss และ Ta

    2. เมนู category ไหนขายดีที่สุด

    ขั้นแรก เราจะต้องรู้ก่อนว่ายอดขายทั้งหมดของแต่ละ category ก่อน ดังนั้น เรามาลองเขียน query นี้กันก่อนเลย

    SELECT 
      me.category AS Category,
      SUM(me.price * tr.quantity) AS Total_Sales
    FROM 
      menus AS me, 
      transactions AS tr
    WHERE me.menu_id = tr.menu_id
    GROUP BY 1
    ORDER BY 2 DESC;

    แต่เราอยากรู้แค่ว่าเมนู category ไหนขายดีที่สุด เราก็แค่ SELECT เฉพาะ Category มาแล้ว LIMIT แค่อันดับ 1 เท่านั้น

    -- Most popular category menu
    
    SELECT 
      Category
    FROM (
      SELECT 
        me.category AS Category,
        SUM(me.price * tr.quantity) AS Total_Sales
      FROM 
        menus AS me, 
        transactions AS tr
      WHERE me.menu_id = tr.menu_id
      GROUP BY 1
      ORDER BY 2 DESC
    )
    LIMIT 1;

    จาก result เราจะได้ว่า เมนูที่ขายดีที่สุด คือ เมนูประเภท classic coffee นั่นเอง

    ก่อนจะไปที่หัวข้อสุดท้ายกัน อยากให้ทุกคนลองช่วยกันสังเกตหน่อยว่า จากทั้งสองตัวอย่างนี้เราเขียน subqueries ไว้ที่ไหนกันบ้าง?

    Common Table Expression (CTEs)

    Common Table Expression (CTEs) คือ การสร้าง Temporary Result Set เหมือนการประกาศตัวแปรเพื่อเรียกใช้งานต่อภายหลังเลย

    ซึ่งข้อดีของการใช้ CTE เลยคือการ break subqueries ของเราที่เป็นปัญหาของเราก่อนหน้านี้ได้ ทำให้ code ของเราอ่านง่ายขึ้น แต่ยังได้ result เหมือนเดิมเป๊ะ! แถมยังสามารถนำไปใช้ใน query อื่นได้ด้วย

    1. Top Spender 5 คนแรกที่มาคาเฟ่บ่อยที่สุดตั้งแต่วันที่ 25 มิถุนายน 2024

    จากตัวอย่างที่ 1 ในการใช้ subqueries ที่ผ่านมา เราสามารถนำ inner query ชั้นในสุดมาเขียนเป็น CTE โดยใช้ WITH clause ได้

    -- Top 5 customers with the most visits since June 25, 2024
    
    WITH Top5_CustomersID_MostVisit AS (
      SELECT customer_id, COUNT(*)
      FROM transactions AS tr
      WHERE tr.invoicedate >= '2024-06-25'
      GROUP BY 1
      ORDER BY 2 DESC
      LIMIT 5
    )
    
    SELECT
      cu.name AS Customer_Name
    FROM customers AS cu
    WHERE customer_id IN (
       SELECT customer_id FROM Top5_CustomerID_MostVisit
    );

    2. ระหว่างเครื่องดื่มหรือขนม category ไหนขายดีที่สุด

    จากตัวอย่างที่ 2 ก่อนหน้านี้ อันนี้ง่ายเลย เราแค่นำ subqueries ใน FROM clause มาสร้างเป็น CTE ใน WITH clause ก่อน โดยเราตั้งชื่อเป็น Total_Sales_by_Category

    -- Most popular category menu
    
    WITH Total_Sales_by_Category AS (
      SELECT 
        me.category AS Category,
        SUM(me.price * tr.quantity) AS Total_Sales
      FROM 
        menus AS me, 
        transactions AS tr
      WHERE me.menu_id = tr.menu_id
      GROUP BY 1
      ORDER BY 2 DESC
    )
    
    SELECT 
      Category
    FROM Total_Sales_by_Category
    LIMIT 1;

    สรุปสิ่งที่เราได้จากบทความนี้ว่า ก่อนเราจะหา insight ในธุรกิจได้ เริ่มต้นจาก

    • การทำความเข้าใจธุรกิจ
    • ออกแบบ database ให้ดี
    • สร้าง database ที่มั่นคง
    • หา insight จาก database เพื่อสร้าง value ให้กับธุรกิจด้วย 3 เทคนิค

    ทุกคนลองนำแนวทางนี้ที่เราฝากไว้ไปสร้างบ้านของตัวเองให้มั่นคง แข็งแรงนะ

    สุดท้ายนี้ ถ้าชอบฝากกด like ใช่กด share ให้เพื่อนของทุกๆคนได้อ่านต่อกันด้วยนะ บทความหน้าจะเป็นเรื่องอะไร รอติดตามกันได้เลย : )


    Comments

    Leave a comment


  • 7 คำถามตอบโจทย์การวางแผนเที่ยวด้วยพลังของ Data Analysis

    7 คำถามตอบโจทย์การวางแผนเที่ยวด้วยพลังของ Data Analysis

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

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

    ในบทความนี้เราเลยจะลองสวมบทเป็นมนุษย์คนหนึ่งอาศัยอยู่ใน New York City ที่อยากจะวางแผนไปเที่ยวในปีหน้า (2024) แต่ด้วยงบและเวลาที่จำกัด ทำให้เขาคนนี้ไปเที่ยวได้แค่ภายในประเทศเท่านั้น ร้องไห้แล้ว 5555555

    เราจะใช้ข้อมูลจาก nycflights23 และ skills เกี่ยวกับ R Programming การทำ data transformation เพื่อวิเคราะห์ข้อมูลชุดนี้เพื่อช่วยให้พนักงานคนนี้แก้ปัญหาและตัดสินใจสถานการณ์ที่เกิดขึ้นนี้ได้ดียิ่งขึ้น

    สาเหตุที่เราเลือกใช้ภาษา R เพราะ

    • เป็นภาษาที่ง่ายมากสำหรับผู้ที่เริ่มต้นทำงานเกี่ยวกับ data มีฟังก์ชันทางสถิติมากมาย แบบไม่ต้อง def function ขึ้นมาเอง บอกเลยว่านอนไปพิมพ์ไปได้เลย เด๋วววววววววว!!
    • เขียน code เสร็จอ่านแล้วเข้าใจเลยว่า process งานแต่ละขั้นกำลังทำอะไรอยู่
    • ข้อดีของการเขียน code เลยคือ รองรับ data ได้จำนวนมาก รันเร็ว ไม่ยุ่งยากเท่ากับการผูกสูตรใน Google Sheets หรือ Microsoft Excel เลย
    • สามารถเริ่มต้นเขียน code ง่ายๆผ่านเว็บ browser ได้เลย และฟรี! เช่น Google Colab
    1. ติดตั้งและโหลด libraries ที่ต้องการใช้
    2. ทำความเข้าใจกับข้อมูล
      1. Flights dataset
      2. Airports dataset
      3. Airlines dataset
    3. เตรียมข้อมูลก่อนเริ่มวิเคราะห์เสมอ
      1. ค้นหา records ที่ซ้ำกันในทุก dataset
      2. นับจำนวน missing values ที่มี
    4. Let’s start to Analyze data!
      1. สนามบินที่มีประสิทธิภาพมากที่สุดในแง่ความตรงต่อเวลา
      2. LaGuardia Airport มีความตรงต่อเวลามากน้อยแค่ไหน
      3. แล้วเราควรเลือกสายการบินไหนดีนะ?
      4. เราควรเดินทางจาก LGA ช่วงเดือนไหนดีถึงดีที่สุด
      5. สายการบินไหนที่ใช้เวลาเดินทางน้อยที่สุด
      6. สายการบินไหนที่มีระยะทางไกลมากที่สุด
      7. จุดหมายใดที่เป็นที่นิยมมากที่สุด 5 อันดับแรกในปี 2023
    5. แผนการเดินทางในปี 2024
    6. More posts

    ติดตั้งและโหลด libraries ที่ต้องการใช้

    อันดับแรก เราต้องเลือกเครื่องมือให้เหมาะสมกับงานที่เราทำกันก่อน ซึ่งเครื่องมือที่เราใช้กันใน programming เราเรียกว่า library หรือ package นั่นเอง

    โดย library ที่เราเลือกใช้ในครั้งนี้มีทั้งหมด 4 packages ดังนี้

    • glue เป็นเหมือนกาวที่คอยเชื่อมระหว่าง text กับตัวแปรเวลาที่เรา print ข้อความบางอย่างออกมา
    • conflicted ไว้สำหรับช่วยแก้การเรียกใช้ฟังก์ชันหรือตัวแปรที่ซ้ำกันโดยการเรียกใช้ต้องระบุชื่อ package ของฟังก์ชันหรือตัวแปรนั้นๆด้วย
    • tidyverse เป็น package ที่ทรงพลังมากในการทำ data transformation หรือแม้กระทั่งการทำ data visualization เช่น dplyr, stringr, ggplot2 เป็นต้น
    • nycflights23 เป็นการเรียก dataset ที่เกี่ยวกับ flights, planes, airports, weather, airlines ของ New York City ปี 2023 ทั้งหมด
    # Install packages
    install.packages(c("glue", "conflicted", "tidyverse", "nycflights23"))
    # Load packages
    library(glue)
    library(conflicted)
    library(tidyverse)
    library(nycflights23)

    ทำความเข้าใจกับข้อมูล

    และตอนนี้เราก็มีเครื่องมือที่ดีติดตัวแล้ว ต่อมาก็เป็นเรื่องของ material ที่เราจะ create ชิ้นงานออกมา นั่นก็คือ DATA นี่เอง ถ้าเราไม่ทำความรู้จักกับ material ดีพอ ก็อาจจะรีดประสิทธิภาพได้ไม่สุดเท่าไหร่

    ไม่ว่าจะเป็นงาน data analysis หรือ data science ก็ต้องศึกษาข้อมูล (exploration) ให้ดีซะกัน ซึ่ง material ที่เราจะใช้มีอยู่ 3 ตัว นั่นคือ ข้อมูลเที่ยวบิน (flights), ข้อมูลสนามบิน (airports), ข้อมูลสายการบิน (airlines)

    โดยเราจะใช้ฟังก์ชัน summary() เพื่อเป็นการสรุปข้อมูลแต่ละ dataset ว่าแต่ละคอลัมน์มีหน้าตาประมาณไหนกันก่อน

    ER Diagram แสดง relationship ของ NYCflights23 dataset

    Flights dataset

    Flights dataset ให้ข้อมูลต่างๆเกี่ยวกับไฟล์ทที่ถูกบินไปแล้วในช่วงปี 2023 จาก NYC ซึ่งเราจะใช้สำหรับการวิเคราะห์ว่าเราควรจะเดินทางไปไหนดี ขึ้นที่สนามบินไหน ลงที่ไหน ใช้สายการบินไหนดี โดยอิงจากข้อมูลปี 2023

    summary(flights)
    • year: ปีที่ไฟล์ทออกบิน
    • month: เดือนที่ไฟล์ทออกบิน
    • day: วันที่ไฟล์ทออกบิน
    • dep_delay: เวลาที่ล่าช้าหรือเร็วกว่ากำหนดเมื่อเครื่องออกจากสนามบินต้นทาง มีหน่วยเป็น นาที
    • arr_delay: เวลาที่ล่าช้าหรือเร็วกว่ากำหนดเมื่อถึงสนามบินปลายทาง มีหน่วยเป็น นาที
    • carrier: ตัวอักษรย่อ 2 ตัวของสายการบินในไฟล์ทนั้นๆ
    • origin: สนามบินต้นทางที่เครื่องออก
    • dest: สนามบินปลายทางที่เครื่อง landing
    • air_time: เวลาที่ใช้ในการบิน มีหน่วยเป็น นาที
    • distance: ระยะทางระหว่างสนามบินต้นทางและปลายทาง มีหน่วยเป็น ไมล์ (mile)

    Airports dataset

    Airports dataset ให้ข้อมูลต่างๆเกี่ยวกับสนามบินทั้งหมดในทุกเที่ยวบิน เราจะใช้สำหรับการดูรหัสและชื่อของสนามบินที่เราจะเดินทางไป

    summary(airports)
    • faa: FAA airport code
    • name: ชื่อสนามบิน

    Airlines dataset

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

    summary(airlines)
    • carrier: อักษรย่อ 2 ตัวของสายการบิน
    • name: ชื่อเต็มของสายการบิน

    ข้อมูลจาก: https://cran.r-project.org/web/packages/nycflights13/nycflights13.pdf


    เตรียมข้อมูลก่อนเริ่มวิเคราะห์เสมอ

    ทุกครั้งที่มีการวิเคราะห์ข้อมูล เราควรที่จะตรวจสอบก่อนว่าข้อมูลของเรานั้นสมบูรณ์หรือไม่ นั่นคือ กระบวนการเตรียมข้อมูล (preparation) ซึ่งเวลาส่วนใหญ่ในงานของ data analyst / data scientist มักจะอยู่ที่ตรงนี้กันเป็นหลักเลย

    ไม่ว่าจะเป็นการเช็ค data types, มีข้อมูลบาง records ที่ซ้ำกัน หรือ missing values หรือไม่, แม้กระทั่งข้อมูลอยู่ใน format ที่ควรจะเป็น, ข้อมูลมี outliers หรือไม่ เป็นต้น จริงๆมีอีกเยอะมากกกกกกก ร้องไห้แล้ว 55555555555

    โดยอันดับแรกเราจะขอเช็ค data types ของข้อมูลก่อนโดยใช้ฟังก์ชัน glimpse() จาก library tidyverse

    glimpse(flights)
    glimpse(airports)
    glimpse(airlines)

    สังเกตว่า คอลัมน์ hour และ minute ควรจะมี data types เป็น integer ไม่ใช่ numeric
    โดยฟังก์ชันที่ใช้ใน convert data types เป็น integer คือ as.integer()

    Note: แต่เนื่องจากในบทความนี้เราไม่มีความจำเป็นที่จะต้องใช้สองคอลัมน์นี้ เราจึงขอละขั้นตอนนี้ไว้ในฐานที่เข้าใจนะคร้าบบบ

    ค้นหา records ที่ซ้ำกันในทุก dataset

    ใน dataset เราอาจพบ data point บาง record ที่ซ้ำกัน ซึ่งอาจจะเกิดจากความผิดพลาดจาก human error หรือการจัดเก็บข้อมูล

    ดังนั้น เราจึงใช้ฟังก์ชัน duplicated() สำหรับการหาข้อมูลบาง records ที่ซ้ำกัน (full duplicates) หามีข้อมูลที่ซ้ำกัน ฟังก์ชันนี้จะ return ค่าเป็น TRUE โดยเราจะใช้คู่กับฟังก์ชัน sum() เพื่อหาผลรวมว่า dataset ดังกล่าวมีจำนวน full duplicates ทั้งหมดกี่ records

    ก่อนที่จะไปดูการค้นหา full duplicates กัน เราขอแนะนำ 2 ฟังก์ชันให้ทุกคนรู้จักกันก่อน นั่นคือ
    1. print() เป็นฟังก์ชันสำหรับปริ้นข้อความที่เราต้องการไปโชว์ในหน้าต่าง console
    2. glue() เป็นฟังก์ชันจาก library glue ใช้สำหรับเชื่อมข้อความกับตัวแปรเข้าด้วยกัน

    # Finding full duplicates for each datasets
    print(glue("Flights dataset have {sum(duplicated(flights))} full duplicates."))
    
    print(glue("Airports dataset have {sum(duplicated(airports))} full duplicates."))
    
    print(glue("Airlines dataset have {sum(duplicated(airlines))} full duplicates."))

    จากผลการค้นหาข้างต้นพบว่า ไม่มี full duplicates สำหรับทุก dataset เลย เราจึงเข้าสู่ขั้นตอนต่อไป

    นับจำนวน missing values ที่มี

    เราจะใช้อยู่ด้วยกัน 3 ฟังก์ชันหลักๆในการนับจำนวน missing values ออกมาเป็นรูปแบบของ % กัน ได้แก่

    • complete.cases() ฟังก์ชันนี้หากพบเจอว่าแถวใดคอลัมน์ใดมี missing values อยู่ จะ return ค่าเป็น FALSE
    • mean() มีส่วนนี้จะมีหน้าที่คำนวณว่าจากค่า TRUE (1) กับ FALSE (0) ทั้งหมดที่ return จากฟังก์ชัน complete.cases() โดยเฉลี่ยแล้วพบค่า TRUE เป็นร้อยละเท่าไหร่ ซึ่งจะมีค่าอยู่ระหว่าง 0 ถึง 1 เท่านั้น
    • round() เป็นฟังก์ชันที่จะทำให้ตัวเลขนั้นๆมีจำนวนทศนิยมตามที่เราต้องการ
    # Counting missing values
    print(glue("Flights dataset have {round((1 - mean(complete.cases(flights)))*100,2)} % missing values."))
    
    print(glue("Airports dataset have {round((1 - mean(complete.cases(airports)))*100,2)} % missing values."))
    
    print(glue("Airlines dataset have {round((1 - mean(complete.cases(airlines)))*100,2)} % missing values."))

    ซึ่งผลที่ได้ข้างต้นพบว่ามีเพียง Airlines dataset เท่านั้นที่ไม่มี missing values เลย
    ดังนั้น ในบทความนี้เราจะใช้วิธีการ drop missing values ซึ่งฟังก์ชันที่ใช้ก็ตรงตัวมาก นั่นคือ drop_na() หรือจะใช้ na.omit() ก็ได้เหมือนกันนะคร้าบ

    พอมาถึงตรงนี้แล้ว เราขออธิบายการทำ data transformation ซักเล็กน้อยก่อนนะ
    Data Transformation เป็นเหมือนการเอา data มาแปลงร่างตามที่เราต้องการเหมือน transformer เลย 555555

    ซึ่ง library ที่ใช้สำหรับการ transform data นั่นคือ dplyr ใน library tidyverse นี่เอง!! หลักๆแล้ว core function ที่ทุกคนควรทำความรู้จักก่อน 5 ฟังก์ชัน คือ

    1. select() : เลือกคอลัมน์ใน dataframe ที่เราต้องการ
    2. filter() : กรองข้อมูลตามเงื่อนไขที่เรากำหนด
    3. mutate() : สร้างคอลัมน์ใหม่
    4. group_by() : จัดกลุ่มข้อมูลตามคอลัมน์ ซึ่งมักจะใช้คู่กับฟังก์ชันที่ 5 ของเรา
    5. summarise() หรือ summarize() : สรุปผลข้อมูลโดยใช้ aggregate function เช่น n(), sum(), min(), max(), mean(), median(), std() เป็นต้น

    แถมซักอีก 1 ฟังก์ชันซึ่งเราจะแอบๆใช้ในบทความนี้ด้วยหลังจากนี้ นั่นคือ rename() สำหรับการเปลี่ยนชื่อคอลัมน์ใน dataframe

    อีกหนึ่งสิ่งที่ขาดไปไม่ได้เลย นั่นคือ pipe operator ใช้สัญลักษณ์เป็น %>% เหมือนกับการต่อท่อเชื่อมการทำงานของแต่ละฟังก์ชัน สำหรับ base R จะใช้สัญลักษณ์เป็น |>

    # Clean missing values by dropping NA
    clean_flights <- tibble(flights %>%
                              drop_na())
    
    clean_airports <- tibble(airports %>%
                               drop_na())

    และเพื่อให้ชื่อตัวแปรเป็นไปในทิศทางเดียวกัน เราจึงขอเปลี่ยนชื่อ dataset ของ airlines ที่ไม่มี missing values

    clean_airlines <- tibble(airlines)

    Note: tibble() เป็นฟังก์ชันที่ใช้ในการแปลง object ที่เป็น data.frame เป็น tibble ซึ่งต่างจาก data.frame ตรงที่เวลาแสดงผลลัพธ์ใน console จะดูสวย เป็นระเบียบ อ่านง่ายมากขึ้น


    Let’s start to Analyze data!

    สนามบินที่มีประสิทธิภาพมากที่สุดในแง่ความตรงต่อเวลา

    เวลาเป็นสิ่งที่มีค่ามาก แค่การไปสนามบินแล้วยังต้องนั่งรอเวลาขึ้นเครื่อง แล้วต้องเจอกับคำว่า delayed หรือ canceled ก็ทำให้ใจเจ็บได้ สิ่งที่เราอยากเห็นคือคำว่า boarding ที่ตรงเวลาหรือเร็วกว่ากำหนดเท่านั้น

    อย่างนั้นจะดีกว่ามั้ยถ้าเราสามารถวิเคราะห์ได้ว่าสนามบินไหนที่มีระบบการจัดการเรื่องเวลาได้ดีเป็นอันดับต้นๆ เพื่อรักษาเวลาที่เป็นของมีค่าของเรา

    ot_dep_rate <- clean_flights %>%
      mutate(dep_type = ifelse(dep_delay <= 5, "On Time", "Delayed")) %>%
      group_by(origin) %>%
      summarise(ot_dep_rate = sum(dep_type == "On Time") / n()) %>%
      arrange(desc(ot_dep_rate))
    
    ot_dep_rate

    Note: ot ย่อมาจาก On Time

    จากการสังเกตพบว่า LaGuardia Airport (LGA) มีอัตราที่เครื่องบินจะบินได้ตรงกำหนดสูงที่สุดเมื่อเทียบกับ John F. Kennedy International Airport ( JFK) และ Newark Liberty International Airport (EWR)

    LaGuardia Airport มีความตรงต่อเวลามากน้อยแค่ไหน

    เราจะ filter เฉพาะ flights ที่บินออกจาก LGA เท่านั้น และใช้ histogram chart เพื่อแสดงการกระจายตัวของ departure time delayed

    lga_flights <- clean_flights %>%
      dplyr::filter(origin == "LGA")
    ## Preview flights from LGA airport
    lga_flights %>%
      select(carrier, flight, tailnum, origin, dest) %>%
      head()
    dtb_delayed_lga <- lga_flights %>%
      dplyr::filter(dep_delay > 0) %>%
      select(dep_delay) %>%
      ggplot(aes(x = dep_delay)) +
      geom_histogram(bins = 30,
                     fill = "lightblue",
                     color = "black") +
      coord_cartesian(xlim = c(0,900),
                      ylim = c(0,30000)) +
      theme_minimal() +
      labs(title = "Distribution of departure time delayed of LGA",
           x = "Departure Time Delayed",
           y = "Number of Flights",
           caption = "Source: New York City Flights 2023 from nycflights23 package")

    Note: dtb ย่อมาจาก Distribution

    ## Summarise statistical data for this histogram
    lga_flights %>%
      dplyr::filter(dep_delay > 0) %>%
      select(dep_delay) %>%
      summarise(min_delay = min(dep_delay),
                mean_delay = mean(dep_delay),
                median_delay = median(dep_delay),
                sd_delay = sd(dep_delay),
                max_delay = max(dep_delay)
                )

    แล้วเราควรเลือกสายการบินไหนดีนะ?

    หลายครั้งที่เวลาเราจะไปเที่ยวแล้วเลือกการเดินทางโดยใช้เครื่องบิน สายการบินก็มีผลต่อการตัดสินใจของเราเช่นกัน ตัวอย่างเช่น ถ้าเป็นของไทย สายการบินที่เรามักเลือกเป็นอันดับต้นๆ แล้วราคาเป็นมิตรสุดๆ และขึ้นชื่อเป็นสายการบินราคาประหยัดที่ตรงเวลาที่สุด ก็จะเป็น Thai AirAsia เป็นต้น (เค้าไม่เคยสปอนเซอร์เลย แต่ใช้บริการประจำ 55555)

    recommend_airlines_list <- lga_flights %>%
      group_by(carrier) %>%
      summarise(mean_dep_delay = mean(dep_delay),
                median_dep_delay = median(dep_delay),
                sd_dep_delay = sd(dep_delay)) %>%
      arrange(mean_dep_delay)
    
    recommend_airlines_list

    จากการวิเคราะห์พบว่าสายการบิน Republic Airlines (YX) มีค่าเฉลี่ยของเวลาเครื่องออกต่ำที่สุด รองลงมาคือ สายการบิน Endeavor Air (9E) และสายการบิน United Air Lines (UA)

    เราควรเดินทางจาก LGA ช่วงเดือนไหนดีถึงดีที่สุด

    ช่วงเวลาก็เป็นอีกสิ่งที่สำคัญต่อการเดินทาง ว่าเราควรจะไปเที่ยวในช่วงไหนดี โดยในกรณีนี้เราจะขอ based on เวลาเครื่องออก

    สมมติว่า เราจะใช้วันลาพักร้อนที่บริษัทมีให้โดยไม่คำนึงถึงวันหยุดปกติ

    flyout_lga <- lga_flights %>%
      group_by(month) %>%
      summarise(mean_dep_delay = mean(dep_delay),
                median_dep_delay = median(dep_delay),
                sd_dep_delay = sd(dep_delay),
                frequency = n()) %>%
      arrange(desc(mean_dep_delay))
    
    flyout_lga
    lga_flights %>%
      ggplot(aes(x = factor(month), y = dep_delay)) +
      geom_boxplot(outlier.color = "darkred",
                   outlier.alpha = 0.3) +
      theme_minimal() +
      labs(title = "Distribution of departure time delayed of LGA by Months",
           x = "Months",
           y = "Departure Time Delayed",
           caption = "Source: New York City Flights 2023 from nycflights23 package")

    จากตารางสรุปและ chart พบว่า flights ทั้งหมดจาก LaGuardia Airport ในเดือนพฤศจิกายนของปี 2023 ใช้เวลาเครื่องออกจากสนามบินน้อยที่สุดเมื่อเทียบกับทุกเดือน รองลงมา คือ เดือนตุลาคม 2023 และ เดือนพฤษภาคม 2023

    สายการบินไหนที่ใช้เวลาเดินทางน้อยที่สุด

    การไปถึงจุดหมายได้เร็วที่สุดก็ทำให้เรามีเวลาพักผ่อนเมื่อถึงจุดหมายได้มากขึ้นเท่านั้น เพราะเวลาคือสิ่งที่มีค่ามากที่สุด

    ฉะนั้นแล้ว เราก็ขอมารื้อฟื้นความรู้วิชาคณิตศาสตร์และวิทยาศาสตร์กันซักเล็กน้อย หลายคนน่าจะคุ้นๆกับสมการนี้กัน v = d/t

    เมื่อ v คือ อัตราเร็ว (velocity) หรือ ความเร็ว (speed)
    d คือ ระยะทาง (distance) หรือ การกระจัด (displacement)
    และ t คือ เวลา (time)

    สิ่งที่เราสามารถเห็นได้ชัดจากสมการเลยคือ
    1. หากเราต้องการรู้อัตราเร็ว/ความเร็ว จำเป็นต้องหา ระยะทาง/การกระจัด และ เวลา ซะก่อน
    2. อัตราเร็ว/ความเร็ว จะสูง ถ้า เราใช้เวลาในการเดินทางน้อยกับระยะทางที่ไกลๆ

    ขั้นแรก เราจะทำการแปลงเวลาที่ใช้ในการเดินทาง (air_time_hour) จากนาทีเป็นชั่วโมงกันก่อน ซึ่งใช้ความรู้ที่ง่ายมากๆว่า 1 ชั่วโมง เท่ากับ 60 นาที

    lga_flights$air_time_hour = round(lga_flights$air_time / 60, 1)

    ขั้นต่อไป เรามาคำนวณ speed จากสมการเมื่อสักครู่นี้กัน!!

    avg_lga_flights <- lga_flights %>%
      mutate(avg_speed = distance / air_time_hour) %>%
      arrange(desc(avg_speed)) %>%
      select(carrier, tailnum, avg_speed, distance)
    
    avg_lga_flights %>%
      head()

    จากการวิเคราะห์พบว่า สายการบินที่มีโอกาสจะใช้เวลาในการเดินทางน้อยที่สุด คือ Southwest Airlines (WN) รองลงมาคือ Delta Airlines (DL) และ American Airlines (AA)

    สายการบินไหนที่มีระยะทางไกลมากที่สุด

    อีกหนึ่งปัจจัยที่จะทำให้เราตัดสินใจว่าไม่อยากเดินทางไปที่นี่เลย นั่นคือเรื่องของระยะทางที่มากเกินไป แค่เราเปิด Google Maps แล้วรู้สึกว่าอยู่ไกลจากที่เราต้องออกเดินทางมากเกินไปก็เป็นท้อแล้ว

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

    โดยเราจะวิเคราะห์จากสายการบินที่มี flights การบินเกินกว่า 1000 km เป็นต้นไป

    lga_long_haul_flights <- lga_flights %>%
      dplyr::filter(distance > 1000) %>%
      group_by(carrier) %>%
      summarise(n_flights = n(),
                mean_distance = mean(distance)) %>%
      arrange(desc(mean_distance))
    
    lga_long_haul_flights

    จากการวิเคราะห์พบว่า สายการบิน United Air Lines (UA) มีระยะทางการบินเฉลี่ยทุกไฟล์ทสูงที่สุด รองลงมา คือ สายการบิน Southwest Airlines (WN) และ Skywest Airlines (OO) ตามลำดับ

    จุดหมายใดที่เป็นที่นิยมมากที่สุด 5 อันดับแรกในปี 2023

    ทุกวันนี้เรามีแหล่งข้อมูลหรือ social media ต่างๆมากมายให้ได้หาข้อมูลต่างๆ ไม่ใช่แค่เรื่องการท่องเที่ยวและการเดินทางเท่านั้น อีกหนึ่งสิ่งที่ผลมากๆต่อคนรุ่นใหม่คือ influencer ที่หลายคน follow หรือติดตามผลงานกัน หลายคนมี inspire หลายอย่างที่บางทีก็จินตนาการอยากไปอยู่ในจุดๆเดียวกับคนๆนั้น

    แต่อย่างไรก็ตามถ้าเรามีข้อมูลต่างๆที่บอกเราได้ว่าตอนนี้คนทั่วไปเค้าไปที่ไหนกัน (ดูจากสนามบินปลายทางที่ไป landing กัน; dest) ก็คงเอามาเป็นอีกทางเลือกในการตัดสินใจที่ดีเลย

    pop_dest_2023 <- lga_flights %>%
      count(dest) %>%
      arrange(desc(n))
    
    pop_dest_2023 %>%
      head(5)

    จากผลการวิเคราะห์พบว่า สนามบินที่คนส่วนใหญ่เลือกไปลงมากที่สุด คือ Chicago O’Hare International Airport (ORD)
    รองลงมาคือ Boston Logan International Airport (BOS) และ Hartsfield-Jackson Atlanta International Airport (ATL)


    แผนการเดินทางในปี 2024

    จากข้อมูลต่างๆที่ได้วิเคราะห์มาแล้ว เราต้องเช็คก่อนว่าสนามบินปลายทางที่เราจะไปลงมีสายการบินรองรับจาก LaGuardia Airport หรือไม่

    lga_flights %>%
      dplyr::filter(dest %in% c("ORD", "BOS", "ATL") & month %in% c(10,11) & carrier %in% c("WN","DL","AA")) %>%
      group_by(dest, carrier) %>%
      summarise(num_of_flight = n()) %>%
      inner_join(clean_airlines, by = "carrier") %>%
      inner_join(clean_airports, by = c("dest" = "faa")) %>%
      select(dest, name.y, carrier, name.x, num_of_flight) %>%
      rename(dest_airport = name.y,
             airline_name = name.x)

    สังเกตว่า code ด้านบนเราจะมีการแอบใช้ฟังก์ชัน inner_join() ด้วย ซึ่งเป็นฟังก์ชันสำหรับการนำ data จาก 2 table มาเชื่อมกันด้วย key บางอย่าง ซึ่งเราต้องดู relationship จาก ER diagram

    ดังนั้น เราจึงมีแผนการเดินทางไปท่องเที่ยวออกเป็น 3 ตัวเลือก ดังนี้

    1. ไปเที่ยว Chicago ด้วยการนั่งเครื่องบินจาก LaGuardia Airport ไปลง Chicago O’Hare International Airport (ORD) สามารถใช้บริการสายการบิน Delta Airlines (DL) และ American Airlines (AA)

    2. ไปเที่ยว Boston ด้วยการนั่งเครื่องบินจาก LaGuardia Airport ไปลง Boston Logan International Airport (BOS) สามารถใช้บริการสายการบิน Delta Airlines (DL) และ American Airlines (AA)

    3. ไปเที่ยวเมือง Atlanta ด้วยการนั่งเครื่องบินจาก LaGuardia Airport ไปยัง Hartsfield-Jackson Atlanta International Airport (ATL) ซึ่งสามารถใช้บริการสายการบิน Southwest Airlines (WN) และ Delta Airlines (DL)

    โดยทั้ง 3 ตัวเลือกนี้ ช่วงที่ควรเหมาะกับการเที่ยวมากที่สุดคือช่วงเดือนตุลาคมถึงพฤศจิกายน ซึ่งเป็นช่วงฤดูใบไม้ร่วงกำลังจะเข้าช่วงฤดูหนาวพอดี

    อ่านจบแล้ว คิดเห็นยังไงกันบ้างว่าการมี data + programming นั้นทรงพลังสุดๆไปเลย ถ้าชอบฝากกด like ใช่กด share ให้เพื่อนของทุกๆคนได้อ่านต่อกันด้วยนะคร้าบ : )


    Comments

    Leave a comment