Author: Shinin Varongchayakul

  • dbplyr: แนะนำ package และ 6 ขั้นตอนในการทำงานกับ database ด้วย dplyr syntax ในภาษา R — ตัวอย่างการทำงานกับ Chinook database

    dbplyr: แนะนำ package และ 6 ขั้นตอนในการทำงานกับ database ด้วย dplyr syntax ในภาษา R — ตัวอย่างการทำงานกับ Chinook database

    ในบทความนี้ เราจะไปดูวิธีใช้ dbplyr ซึ่งเป็น package สำหรับทำงานกับ database ในภาษา R และเหมาะกับคนที่ต้องการทำงานโดยใช้ภาษา R เป็นหลักกัน

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 🤔 What Is dbplyr?
    2. 🏁 Getting Started
    3. 🏃‍♂️‍➡️ Using dbplyr
      1. 1️⃣ Connect to the Database
      2. 2️⃣ Create a Lazy Tibble
      3. 3️⃣ Create a Query
      4. 4️⃣ Show the Query
      5. 5️⃣ Collect the Result
      6. 6️⃣ Disconnect the Database
    4. 💪 Summary
    5. 😺 GitHub
    6. 📃 References
    7. ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    🤔 What Is dbplyr?

    dbplyr เป็น package ในภาษา R สำหรับทำงานกับ database โดยใช้ dplyr syntax แทน SQL เช่น แทนที่เราเขียน:

    SELECT * FROM table
    

    เราสามารถใช้ dplyr syntax ได้แบบนี้:

    select(table, everything())
    

    (Note: อ่านวิธีใช้ dplyr ได้ที่นี่)


    🏁 Getting Started

    เราสามารถเริ่มใช้งาน dbplyr ได้โดยติดตั้งและโหลด 4 packages ดังนี้:

    1. DBI: สำหรับเชื่อมต่อกับ database (อ่านวิธีใช้เพิ่มเติมได้ที่นี่)
    2. RSQLite: สำหรับเชื่อมต่อกับ SQLite database (เราจะเปลี่ยน package นี้ตาม database ที่เราใช้ เช่น RPostgres สำหรับ Postgres database)
    3. dplyr: สำหรับ dplyr syntax เช่น select(), filter(), arrange()
    4. dbplyr: สำหรับทำงานกับ database ด้วย dplyr syntax
    # Install packages
    install.packages("DBI")
    install.packages("RSQLite")
    install.packages("dplyr")
    install.packages("dbplyr")
    
    # Load packages
    library(DBI)
    library(RSQLite)
    library(dplyr)
    library(dbplyr)
    

    🏃‍♂️‍➡️ Using dbplyr

    เราสามารถใช้ dbplyr เพื่อทำงานกับ database ได้ใน 6 ขั้นตอน:

    1. Connect to the database
    2. Create a lazy tibble
    3. Create a query
    4. Show the query
    5. Get the result

    .

    1️⃣ Connect to the Database

    ในขั้นแรก เราจะเชื่อมต่อกับ local database ด้วย DBI::dbConnect และ RSQLite::SQLite():

    # Connect to database
    con <- dbConnect(RSQLite::SQLite(),
                     "chinook.sqlite")
    

    Note: โหลด “chinook.sqlite” ได้จาก GitHub

    .

    2️⃣ Create a Lazy Tibble

    ในขั้นที่ 2 เราจะสร้าง lazy tibble หรือ object ที่ใช้แทน database table ซึ่งทำได้ใน 2 steps:

    Step 1. ดูรายชื่อ table ทั้งหมด ใน database ด้วย DBI::dbListTables():

    # View all tables
    dbListTables(con)
    

    ผลลัพธ์:

     [1] "Album"         "Artist"        "Customer"      "Employee"     
     [5] "Genre"         "Invoice"       "InvoiceLine"   "MediaType"    
     [9] "Playlist"      "PlaylistTrack" "Track" 
    

    Step 2. สร้าง lazy tibble จากชื่อ table ที่ต้องการ ด้วย dplyr::tbl():

    # Create lazy tibble
    tracks <- tbl(con,
                  "Track")
    
    # View tibble
    tracks
    

    ผลลัพธ์:

    # Source:   table<`Track`> [?? x 9]
    # Database: sqlite 3.50.1 [C:\\My Code\\RStudio\\chinook.sqlite]
       TrackId Name           AlbumId MediaTypeId GenreId Composer Milliseconds  Bytes UnitPrice
         <int> <chr>            <int>       <int>   <int> <chr>           <int>  <int>     <dbl>
     1       1 For Those Abo…       1           1       1 Angus Y…       343719 1.12e7      0.99
     2       2 Balls to the …       2           2       1 NA             342562 5.51e6      0.99
     3       3 Fast As a Sha…       3           2       1 F. Balt…       230619 3.99e6      0.99
     4       4 Restless and …       3           2       1 F. Balt…       252051 4.33e6      0.99
     5       5 Princess of t…       3           2       1 Deaffy …       375418 6.29e6      0.99
     6       6 Put The Finge…       1           1       1 Angus Y…       205662 6.71e6      0.99
     7       7 Let's Get It …       1           1       1 Angus Y…       233926 7.64e6      0.99
     8       8 Inject The Ve…       1           1       1 Angus Y…       210834 6.85e6      0.99
     9       9 Snowballed           1           1       1 Angus Y…       203102 6.60e6      0.99
    10      10 Evil Walks           1           1       1 Angus Y…       263497 8.61e6      0.99
    # ℹ more rows
    # ℹ Use `print(n = ...)` to see more rows
    

    .

    3️⃣ Create a Query

    ในขั้นที่ 3 เราจะเขียน dplyr syntax เพื่อ query table ที่ต้องการ

    เช่น สรุปข้อมูลจำนวนเพลง ค่าเฉลี่ยความยาวเพลง (Milliseconds) และขนาดเพลง (Bytes) ของแต่ละ album:

    # Create query
    album_info <- tracks |>
      
      # Group by album
      group_by(AlbumId) |>
      
      # Summarise
      summarise(
        
        # Number of tracks
        tracks = n(),
        
        # Average duration
        mean_millisec = mean(Milliseconds,
                             na.rm = TRUE),
        
        # Total size
        total_bytes = sum(Bytes)
      ) |>
      
      # Sort by duration
      arrange(desc(mean_millisec))
    

    ตอนนี้ code ของเราจะยังไม่ถูกส่งไปยัง database เพราะ lazy tibble จะเก็บคำสั่งไว้จนกว่าเราจะมีคำสั่งให้ส่ง

    เราไปดูคำสั่งที่เราสามารถใช้กับ code ที่ยังไม่ถูกส่งไปกัน

    .

    4️⃣ Show the Query

    เราสามารถใช้ dbplyr::show_query() เพื่อดู SQL ที่จะถูกส่งไปยัง database (ซึ่งแปลงมาจาก dplyr syntax ของเรา) ได้:

    # Show query
    show_query(album_info)
    

    ผลลัพธ์:

    <SQL>
    SELECT
      `AlbumId`,
      COUNT(*) AS `tracks`,
      AVG(`Milliseconds`) AS `mean_millisec`,
      SUM(`Bytes`) AS `total_bytes`
    FROM `Track`
    GROUP BY `AlbumId`
    ORDER BY `mean_millisec` DESC
    

    .

    5️⃣ Collect the Result

    เราสามารถส่ง code เพื่อไป query database ได้ด้วย dbplyr::collect():

    # Get result
    album_info_tb <- collect(album_info)
    
    # View the result
    album_info_tb
    

    ผลลัพธ์:

    # A tibble: 347 × 4
       AlbumId tracks mean_millisec total_bytes
         <int>  <int>         <dbl>     <int64>
     1     253     24      2925574. 12872621850
     2     227     19      2778265. 10059916535
     3     229     26      2717907  13917603291
     4     231     24      2637068. 12344960921
     5     226      1      2622250    490750393
     6     228     23      2599142. 11781321607
     7     230     25      2594197.  5280909854
     8     254      1      2484567    492670102
     9     261     17      2321673.  7708725642
    10     251     25      1532684.  7652731262
    # ℹ 337 more rows
    # ℹ Use `print(n = ...)` to see more rows
    

    .

    6️⃣ Disconnect the Database

    สุดท้าย เมื่อเราทำงานเสร็จแล้ว เราจะปิดการเชื่อมต่อกับ database ด้วย DBI::dbDisconnect():

    # Disconnect from database
    dbDisconnect(con)
    

    เป็นการจบ loop การทำงานกับ database ด้วย dbplyr


    💪 Summary

    ในบทความนี้ เราได้ไปทำความรู้จัก 6 ขั้นตอนในการใช้ dbplyr เพื่อทำงานกับ database ในภาษา R กัน:

    1. Connect to the database: DBI::dbConnect() และ RSQLite::SQLite()
    2. Create a lazy tibble: dplyr::tbl()
    3. Create a query: ใช้ dplyr syntax คู่กับ lazy tibble
    4. Show the query: dbplyr::show_query()
    5. Collect the result: dbplyr::collect()
    6. Disconnect the database: DBI::dbDisconnect()

    😺 GitHub

    ดูตัวอย่าง code และ database ในบทความนี้ได้ที่ GitHub


    📃 References


    ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    📕 ขอฝากหนังสือเล่มแรกในชีวิตด้วยนะครับ 😆

    🙋 ใครที่กำลังเรียนจิตวิทยาหรือทำงานสายจิตวิทยา และเบื่อที่ต้องใช้ software ราคาแพงอย่าง SPSS และ Excel เพื่อทำข้อมูล

    💪 ผมขอแนะนำ R Book for Psychologists หนังสือสอนใช้ภาษา R เพื่อการวิเคราะห์ข้อมูลทางจิตวิทยา ที่เขียนมาเพื่อนักจิตวิทยาที่ไม่เคยมีประสบการณ์เขียน code มาก่อน

    ในหนังสือ เราจะปูพื้นฐานภาษา R และพาไปดูวิธีวิเคราะห์สถิติที่ใช้บ่อยกัน เช่น:

    • Correlation
    • t-tests
    • ANOVA
    • Reliability
    • Factor analysis

    🚀 เมื่ออ่านและทำตามตัวอย่างใน R Book for Psychologists ทุกคนจะไม่ต้องพึง SPSS และ Excel ในการทำงานอีกต่อไป และสามารถวิเคราะห์ข้อมูลด้วยตัวเองได้ด้วยความมั่นใจ

    แล้วทุกคนจะแปลกใจว่า ทำไมภาษา R ง่ายขนาดนี้ 🙂‍↕️

    👉 สนใจดูรายละเอียดหนังสือได้ที่ meb:

  • DBI: แนะนำ 4 ขั้นตอนในการเชื่อมต่อและ query ข้อมูลจาก database โดยใช้ภาษา R — ตัวอย่างการทำงานกับ Chinook database

    DBI: แนะนำ 4 ขั้นตอนในการเชื่อมต่อและ query ข้อมูลจาก database โดยใช้ภาษา R — ตัวอย่างการทำงานกับ Chinook database

    ในบทความนี้ เราจะมาดู 4 ขั้นตอนในการเชื่อมต่อและทำงานกับ database ในภาษา R ด้วย DBI package กัน:

    1. Get started
    2. Explore the database
    3. Query the database
    4. Close the connection

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 💻 Step 1. Get Started
      1. 📦 DBI Package
      2. ⬇️ Install & Connect
    2. 👀 Step 2. Explore the Database
      1. 1️⃣ dbListTable()
      2. 2️⃣ dbGetQuery()
    3. 🔍 Step 3. Query the Database
      1. 1️⃣ dbReadTable()
      2. 2️⃣ dbGetQuery()
      3. 3️⃣ dbSendQuery()
    4. 🤚 Step 4. Close the Connection
    5. 💪 Summary
    6. 😺 GitHub
    7. 📃 References
    8. ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    💻 Step 1. Get Started

    📦 DBI Package

    DBI (Database Interface) เป็น package สำหรับเชื่อมต่อกับ database ซึ่งทำให้เราทำงานกับ database ในภาษา R ได้โดยตรง

    ในบทความนี้ เรามาลองดูการใช้งาน DBI ผ่านการทำงานกับ Chinook SQLite database กัน (เราสามารถโหลด Chinook เพื่อลองทำตามได้จาก GitHub)

    .

    ⬇️ Install & Connect

    ในขั้นแรกของการใช้งาน เราจะติดตั้งและโหลด DBI พร้อมกับ package สำหรับ database ที่เราจะทำงานด้วย

    อย่างในกรณีนี้ เราจะติดตั้งและโหลด RSQLite package เพราะเราจะทำงานกับ SQLite database

    Note: ถ้าเราทำงานกับ database อื่น เราจะต้องติดตั้งและโหลด package อื่น เช่น:

    • MySQL → RMySQL
    • PostgresSQL → RPostgresSQL
    • Oracle → ROracle

    ติดตั้ง packages:

    # Install
    install.packages("DBI")
    install.packages("RSQLite")
    

    โหลด packages:

    # Load
    library(DBI)
    library(RSQLite)
    

    หลังติดตั้งและโหลด packages แล้ว เราจะเชื่อมต่อกับ database ด้วย dbConnect() แบบนี้:

    # Connect to database
    con <- dbConnect(RSQLite::SQLite(),
                     "chinook.sqlite")
    

    Note: ในกรณีที่ database ไม่ได้อยู่ใน working directory เราจะต้องใช้ absolute file path แทนชื่อไฟล์ เช่น:

    # Connect to database
    con <- dbConnect(RSQLite::SQLite(),
                     "C:/Users/YourUser/Documents/R_Projects/my_data/chinook.sqlite")
    

    เท่านี้ เราก็พร้อมที่จะทำงานกับ database กันแล้ว


    👀 Step 2. Explore the Database

    เริ่มแรก เราจะสำรวจ database เพื่อทำความเข้าใจโครงสร้างข้อมูลกันก่อน

    เรามี 2 functions ที่ช่วยเราได้ ได้แก่:

    1. dbListTables(): ดูรายชื่อ tables ทั้งหมดใน database
    2. dbGetQuety(): ดู columns ใน table ที่ต้องการ

    .

    1️⃣ dbListTable()

    ตัวอย่าง:

    # List tables in the database
    dbListTables(con)
    

    ผลลัพธ์:

     [1] "Album"         "Artist"        "Customer"      "Employee"     
     [5] "Genre"         "Invoice"       "InvoiceLine"   "MediaType"    
     [9] "Playlist"      "PlaylistTrack" "Track"  
    

    .

    2️⃣ dbGetQuery()

    ตัวอย่าง:

    # List columns in a table
    dbGetQuery(con,
               "PRAGMA table_info(Artist)")
    

    ผลลัพธ์:

      cid     name          type notnull dflt_value pk
    1   0 ArtistId       INTEGER       1         NA  1
    2   1     Name NVARCHAR(120)       0         NA  0
    

    ในกรณีที่เราต้องการดู columns ในทุก table เราสามารถใช้ for loop ช่วยได้แบบนี้:

    # Get the table list
    tables <- dbListTables(con)
    
    # Get all columns
    for (table_name in tables) {
      
      # Print the table name
      message(paste0("\\n👉 Table: ", table_name))
      
      # Get the columns
      column_info <- dbGetQuery(con,
                                paste0("PRAGMA table_info(",
                                       table_name, 
                                       ")"))
      
      # Print the columns
      print(column_info)
    }
    

    ผลลัพธ์:

    👉 Table: Album
      cid     name          type notnull dflt_value pk
    1   0  AlbumId       INTEGER       1         NA  1
    2   1    Title NVARCHAR(160)       1         NA  0
    3   2 ArtistId       INTEGER       1         NA  0
    👉 Table: Artist
      cid     name          type notnull dflt_value pk
    1   0 ArtistId       INTEGER       1         NA  1
    2   1     Name NVARCHAR(120)       0         NA  0
    👉 Table: Customer
       cid         name         type notnull dflt_value pk
    1    0   CustomerId      INTEGER       1         NA  1
    2    1    FirstName NVARCHAR(40)       1         NA  0
    3    2     LastName NVARCHAR(20)       1         NA  0
    4    3      Company NVARCHAR(80)       0         NA  0
    5    4      Address NVARCHAR(70)       0         NA  0
    6    5         City NVARCHAR(40)       0         NA  0
    7    6        State NVARCHAR(40)       0         NA  0
    8    7      Country NVARCHAR(40)       0         NA  0
    9    8   PostalCode NVARCHAR(10)       0         NA  0
    10   9        Phone NVARCHAR(24)       0         NA  0
    11  10          Fax NVARCHAR(24)       0         NA  0
    12  11        Email NVARCHAR(60)       1         NA  0
    13  12 SupportRepId      INTEGER       0         NA  0
    👉 Table: Employee
       cid       name         type notnull dflt_value pk
    1    0 EmployeeId      INTEGER       1         NA  1
    2    1   LastName NVARCHAR(20)       1         NA  0
    3    2  FirstName NVARCHAR(20)       1         NA  0
    4    3      Title NVARCHAR(30)       0         NA  0
    5    4  ReportsTo      INTEGER       0         NA  0
    6    5  BirthDate     DATETIME       0         NA  0
    7    6   HireDate     DATETIME       0         NA  0
    8    7    Address NVARCHAR(70)       0         NA  0
    9    8       City NVARCHAR(40)       0         NA  0
    10   9      State NVARCHAR(40)       0         NA  0
    11  10    Country NVARCHAR(40)       0         NA  0
    12  11 PostalCode NVARCHAR(10)       0         NA  0
    13  12      Phone NVARCHAR(24)       0         NA  0
    14  13        Fax NVARCHAR(24)       0         NA  0
    15  14      Email NVARCHAR(60)       0         NA  0
    👉 Table: Genre
      cid    name          type notnull dflt_value pk
    1   0 GenreId       INTEGER       1         NA  1
    2   1    Name NVARCHAR(120)       0         NA  0
    👉 Table: Invoice
      cid              name          type notnull dflt_value pk
    1   0         InvoiceId       INTEGER       1         NA  1
    2   1        CustomerId       INTEGER       1         NA  0
    3   2       InvoiceDate      DATETIME       1         NA  0
    4   3    BillingAddress  NVARCHAR(70)       0         NA  0
    5   4       BillingCity  NVARCHAR(40)       0         NA  0
    6   5      BillingState  NVARCHAR(40)       0         NA  0
    7   6    BillingCountry  NVARCHAR(40)       0         NA  0
    8   7 BillingPostalCode  NVARCHAR(10)       0         NA  0
    9   8             Total NUMERIC(10,2)       1         NA  0
    👉 Table: InvoiceLine
      cid          name          type notnull dflt_value pk
    1   0 InvoiceLineId       INTEGER       1         NA  1
    2   1     InvoiceId       INTEGER       1         NA  0
    3   2       TrackId       INTEGER       1         NA  0
    4   3     UnitPrice NUMERIC(10,2)       1         NA  0
    5   4      Quantity       INTEGER       1         NA  0
    👉 Table: MediaType
      cid        name          type notnull dflt_value pk
    1   0 MediaTypeId       INTEGER       1         NA  1
    2   1        Name NVARCHAR(120)       0         NA  0
    👉 Table: Playlist
      cid       name          type notnull dflt_value pk
    1   0 PlaylistId       INTEGER       1         NA  1
    2   1       Name NVARCHAR(120)       0         NA  0
    👉 Table: PlaylistTrack
      cid       name    type notnull dflt_value pk
    1   0 PlaylistId INTEGER       1         NA  1
    2   1    TrackId INTEGER       1         NA  2
    👉 Table: Track
      cid         name          type notnull dflt_value pk
    1   0      TrackId       INTEGER       1         NA  1
    2   1         Name NVARCHAR(200)       1         NA  0
    3   2      AlbumId       INTEGER       0         NA  0
    4   3  MediaTypeId       INTEGER       1         NA  0
    5   4      GenreId       INTEGER       0         NA  0
    6   5     Composer NVARCHAR(220)       0         NA  0
    7   6 Milliseconds       INTEGER       1         NA  0
    8   7        Bytes       INTEGER       0         NA  0
    9   8    UnitPrice NUMERIC(10,2)       1         NA  0
    

    🔍 Step 3. Query the Database

    หลังสำรวจ database แล้ว เราสามารถ query ข้อมูลได้ด้วย 3 functions ได้แก่:

    1. dbReadTable()
    2. dbGetQuery()
    3. dbSendQuery()

    .

    1️⃣ dbReadTable()

    เราจะใช้ dbReadTable() เมื่อต้องการดึงข้อมูลทั้งหมดมาจาก table ที่ต้องการ

    ตัวอย่างเช่น ดูข้อมูลทั้งหมดใน Genre:

    # Query with dbReadTable()
    dbReadTable(con,
                "Genre")
    

    ผลลัพธ์:

       GenreId               Name
    1        1               Rock
    2        2               Jazz
    3        3              Metal
    4        4 Alternative & Punk
    5        5      Rock And Roll
    6        6              Blues
    7        7              Latin
    8        8             Reggae
    9        9                Pop
    10      10         Soundtrack
    11      11         Bossa Nova
    12      12     Easy Listening
    13      13        Heavy Metal
    14      14           R&B/Soul
    15      15  Electronica/Dance
    16      16              World
    17      17        Hip Hop/Rap
    18      18    Science Fiction
    19      19           TV Shows
    20      20   Sci Fi & Fantasy
    21      21              Drama
    22      22             Comedy
    23      23        Alternative
    24      24          Classical
    25      25              Opera
    

    .

    2️⃣ dbGetQuery()

    ในกรณีที่เราต้องการดูข้อมูลแบบเจาะจง เราจะใช้ dbGetQuery() ซึ่งต้องการ 2 arguments:

    1. Connection ที่เชื่อมต่อกับ database
    2. SQL query ที่กำหนดข้อมูลที่ต้องการจาก database

    ตัวอย่างการใช้งาน #1 – ดึงข้อมูลลูกค้าที่มาจากบราซิล:

    # Query with dbGetQuery() - example 1
    dbGetQuery(con,
               "SELECT
                  CustomerId,
                  FirstName,
                  LastName, Email
                FROM
                  Customer
                WHERE
                  country = 'Brazil';")
    

    ผลลัพธ์:

      CustomerId FirstName  LastName                         Email
    1          1      Luís Gonçalves          luisg@embraer.com.br
    2         10   Eduardo   Martins      eduardo@woodstock.com.br
    3         11 Alexandre     Rocha              alero@uol.com.br
    4         12   Roberto   Almeida roberto.almeida@riotur.gov.br
    5         13  Fernanda     Ramos      fernadaramos4@uol.com.br
    

    ตัวอย่าง #2 – คำนวณยอดขายรวมของแต่ละประเทศ โดยเรียงจากมากไปน้อย:

    # Query with dbGetQuery() - example 2
    dbGetQuery(con,
               "SELECT
                  BillingCountry,
                  SUM(Total) AS TotalSales
                FROM
                  Invoice
                GROUP BY
                  BillingCountry
                ORDER BY
                  TotalSales DESC;")
    

    ผลลัพธ์:

       BillingCountry TotalSales
    1             USA     523.06
    2          Canada     303.96
    3          France     195.10
    4          Brazil     190.10
    5         Germany     156.48
    6  United Kingdom     112.86
    7  Czech Republic      90.24
    8        Portugal      77.24
    9           India      75.26
    10          Chile      46.62
    11        Ireland      45.62
    12        Hungary      45.62
    13        Austria      42.62
    14        Finland      41.62
    15    Netherlands      40.62
    16         Norway      39.62
    17         Sweden      38.62
    18          Spain      37.62
    19         Poland      37.62
    20          Italy      37.62
    21        Denmark      37.62
    22        Belgium      37.62
    23      Australia      37.62
    24      Argentina      37.62
    

    ตัวอย่าง #3 – ดึงชื่อเพลงและชื่ออัลบัม 10 อันดับแรก:

    # Query with dbGetQuery() - example 3
    dbGetQuery(con,
               "SELECT
                  T.Name AS TrackName,
                  A.Title AS AlbumTitle
                FROM
                  Track AS T
                JOIN
                  Album AS A ON T.AlbumID = A.AlbumID
                LIMIT 10;")
    

    ผลลัพธ์:

                                     TrackName                            AlbumTitle
    1  For Those About To Rock (We Salute You) For Those About To Rock We Salute You
    2                        Balls to the Wall                     Balls to the Wall
    3                          Fast As a Shark                     Restless and Wild
    4                        Restless and Wild                     Restless and Wild
    5                     Princess of the Dawn                     Restless and Wild
    6                    Put The Finger On You For Those About To Rock We Salute You
    7                          Let's Get It Up For Those About To Rock We Salute You
    8                         Inject The Venom For Those About To Rock We Salute You
    9                               Snowballed For Those About To Rock We Salute You
    10                              Evil Walks For Those About To Rock We Salute You
    

    .

    3️⃣ dbSendQuery()

    dbSendQuery() ทำงานเหมือนกับ dbGetQuery() แต่ต่างกันที่ dbGetQuery() จะยังส่งข้อมูลใด ๆ กลับมาจนกว่าเราจะเรียกดูด้วย dbFetch()

    ยกตัวอย่างเช่น ดูข้อมูลลูกค้า 10 รายชื่อแรกเมื่อเรียงตามนามสกุล:

    # Send query
    res <- dbSendQuery(con,
                       "SELECT
                          CustomerId,
                          LastName,
                          FirstName,
                          Email
                        FROM
                          Customer
                        ORDER BY
                          LastName
                        LIMIT 10;")
    
    # Fetch results
    dbFetch(res)
    

    ผลลัพธ์:

       CustomerId   LastName FirstName                         Email
    1          12    Almeida   Roberto roberto.almeida@riotur.gov.br
    2          28    Barnett     Julia           jubarnett@gmail.com
    3          39    Bernard   Camille      camille.bernard@yahoo.fr
    4          18     Brooks  Michelle             michelleb@aol.com
    5          29      Brown    Robert              robbrown@shaw.ca
    6          21      Chase     Kathy           kachase@hotmail.com
    7          26 Cunningham   Richard      ricunningham@hotmail.com
    8          41     Dubois      Marc       marc.dubois@hotmail.com
    9          34  Fernandes      João           jfernandes@yahoo.pt
    10         30    Francis    Edward           edfrancis@yachoo.ca
    

    เมื่อเราเรียกดูข้อมูลทั้งหมดแล้ว เราจะไม่สามารถเรียกดูซ้ำได้:

    # Fetch results
    dbFetch(res)
    

    ผลลัพธ์:

    > dbFetch(res)
    [1] CustomerId LastName   FirstName  Email     
    <0 rows> (or 0-length row.names)
    

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

    # Send query
    res <- dbSendQuery(con,
                       "SELECT
                          CustomerId,
                          LastName,
                          FirstName,
                          Email
                        FROM
                          Customer
                        ORDER BY
                          LastName
                        LIMIT 10;")
    
    # Fetch five, twice
    dbFetch(res, n = 5)
    dbFetch(res, n = 5)
    dbFetch(res, n = 5)
    

    ผลลัพธ์:

    > dbFetch(res, n = 5)
      CustomerId LastName FirstName                         Email
    1         12  Almeida   Roberto roberto.almeida@riotur.gov.br
    2         28  Barnett     Julia           jubarnett@gmail.com
    3         39  Bernard   Camille      camille.bernard@yahoo.fr
    4         18   Brooks  Michelle             michelleb@aol.com
    5         29    Brown    Robert              robbrown@shaw.ca
    > dbFetch(res, n = 5)
      CustomerId   LastName FirstName                    Email
    1         21      Chase     Kathy      kachase@hotmail.com
    2         26 Cunningham   Richard ricunningham@hotmail.com
    3         41     Dubois      Marc  marc.dubois@hotmail.com
    4         34  Fernandes      João      jfernandes@yahoo.pt
    5         30    Francis    Edward      edfrancis@yachoo.ca
    > dbFetch(res, n = 5)
    [1] CustomerId LastName   FirstName  Email     
    <0 rows> (or 0-length row.names)
    

    เราสามารถใช้ dbSendQuery() และ dbFetch() เพื่อดูข้อมูลเป็นชุด ๆ แทนที่จะดูข้อมูลทั้งหมดในครั้งเดียวแบบ dbGetQuery()

    Note: ในกรณีที่เราต้องการลบ query ที่เราส่งไป database ด้วย dbSendQuery() ให้เราใช้ dbClearResult():

    # Clear results
    dbClearResult(res)
    

    🤚 Step 4. Close the Connection

    สุดท้าย เมื่อเราทำงานกับ database เสร็จแล้ว เราต้องสิ้นสุดการเชื่อมต่อกับ database ด้วย dbDisconnect():

    # Close the connection
    dbDisconnect(con)
    

    เป็นอันจบการทำงานกับ database ด้วย DBI


    💪 Summary

    ในบทความนี้ เราได้ไปดูวิธีการใช้งาน DBI เพื่อทำงานกับ database กัน:

    เชื่อมต่อ database:

    • dbConnect()

    สำรวจ database:

    • dbListTables()
    • dbGetQuery()

    Query ข้อมูล:

    • dbReadTable()
    • dbGetQuery()
    • dbSendQuery(), dbFetch(), และ dbClearResult()

    ปิดการเชื่อมต่อ:

    • dbDisconnect()

    😺 GitHub

    ดู code และ database ในบทความนี้ได้ที่ GitHub


    📃 References


    ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    📕 ขอฝากหนังสือเล่มแรกในชีวิตด้วยนะครับ 😆

    🙋 ใครที่กำลังเรียนจิตวิทยาหรือทำงานสายจิตวิทยา และเบื่อที่ต้องใช้ software ราคาแพงอย่าง SPSS และ Excel เพื่อทำข้อมูล

    💪 ผมขอแนะนำ R Book for Psychologists หนังสือสอนใช้ภาษา R เพื่อการวิเคราะห์ข้อมูลทางจิตวิทยา ที่เขียนมาเพื่อนักจิตวิทยาที่ไม่เคยมีประสบการณ์เขียน code มาก่อน

    ในหนังสือ เราจะปูพื้นฐานภาษา R และพาไปดูวิธีวิเคราะห์สถิติที่ใช้บ่อยกัน เช่น:

    • Correlation
    • t-tests
    • ANOVA
    • Reliability
    • Factor analysis

    🚀 เมื่ออ่านและทำตามตัวอย่างใน R Book for Psychologists ทุกคนจะไม่ต้องพึง SPSS และ Excel ในการทำงานอีกต่อไป และสามารถวิเคราะห์ข้อมูลด้วยตัวเองได้ด้วยความมั่นใจ

    แล้วทุกคนจะแปลกใจว่า ทำไมภาษา R ง่ายขนาดนี้ 🙂‍↕️

    👉 สนใจดูรายละเอียดหนังสือได้ที่ meb:

  • sqldf(): แนะนำ function ในการทำงานกับ data frame ด้วย SQL ในภาษา R — ตัวอย่างจาก Cars93

    sqldf(): แนะนำ function ในการทำงานกับ data frame ด้วย SQL ในภาษา R — ตัวอย่างจาก Cars93

    ในบทความนี้ เราจะมาดูวิธีใช้ sqldf() ซึ่งเป็น function ที่ช่วยให้เราทำงานกับ data frame ในภาษา R ได้ด้วย SQL syntax และเหมาะกับคนที่คุ้นเคยกับการใช้ SQL ในการทำงานกัน

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 🏁 Getting Started: Install & Load sqldf
    2. 🏃‍♂️‍➡️ Using sqldf
      1. 1️⃣ Example 1. SELECT
      2. 2️⃣ Example 2. WHERE
      3. 3️⃣ Example 3. Aggregate
    3. 😺 GitHub
    4. 📃 References
    5. ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    🏁 Getting Started: Install & Load sqldf

    ก่อนเริ่มใช้ sqldf() เราจะต้องติดตั้งและโหลด sqldf ซึ่งเป็น package ต้นทางของ sdldf() ด้วย install.packages() และ library() ตามลำดับ:

    # Install sqldf
    install.packages("sqldf")
    
    # Load sqldf
    library(sqldf)
    

    Note:

    • เราใช้ install.packages() เพื่อติดตั้งแค่ครั้งเดียว
    • เราใช้ library() เพื่อโหลด sqldf ทุกครั้งที่เริ่ม session ใหม่

    🏃‍♂️‍➡️ Using sqldf

    sqldf() ต้องการ 1 argument คือ character ที่มี SQL query เช่น:

    sqldf("SELECT * FROM df")
    

    เราลองมาดูตัวอย่างการใช้ sqldf() กับ Cars93 dataset (จาก MASS package) ซึ่งมีข้อมูลรถ 93 คันที่ขายในปี ค.ศ. 1993:

    # Install MASS
    install.packages("MASS")
    
    # Load MASS
    library(MASS)
    
    # Load the dataset
    data(Cars93)
    
    # View the dataset structure
    str(Cars93)
    

    ผลลัพธ์:

    'data.frame':	93 obs. of  27 variables:
     $ Manufacturer      : Factor w/ 32 levels "Acura","Audi",..: 1 1 2 2 3 4 4 4 4 5 ...
     $ Model             : Factor w/ 93 levels "100","190E","240",..: 49 56 9 1 6 24 54 74 73 35 ...
     $ Type              : Factor w/ 6 levels "Compact","Large",..: 4 3 1 3 3 3 2 2 3 2 ...
     $ Min.Price         : num  12.9 29.2 25.9 30.8 23.7 14.2 19.9 22.6 26.3 33 ...
     $ Price             : num  15.9 33.9 29.1 37.7 30 15.7 20.8 23.7 26.3 34.7 ...
     $ Max.Price         : num  18.8 38.7 32.3 44.6 36.2 17.3 21.7 24.9 26.3 36.3 ...
     $ MPG.city          : int  25 18 20 19 22 22 19 16 19 16 ...
     $ MPG.highway       : int  31 25 26 26 30 31 28 25 27 25 ...
     $ AirBags           : Factor w/ 3 levels "Driver & Passenger",..: 3 1 2 1 2 2 2 2 2 2 ...
     $ DriveTrain        : Factor w/ 3 levels "4WD","Front",..: 2 2 2 2 3 2 2 3 2 2 ...
     $ Cylinders         : Factor w/ 6 levels "3","4","5","6",..: 2 4 4 4 2 2 4 4 4 5 ...
     $ EngineSize        : num  1.8 3.2 2.8 2.8 3.5 2.2 3.8 5.7 3.8 4.9 ...
     $ Horsepower        : int  140 200 172 172 208 110 170 180 170 200 ...
     $ RPM               : int  6300 5500 5500 5500 5700 5200 4800 4000 4800 4100 ...
     $ Rev.per.mile      : int  2890 2335 2280 2535 2545 2565 1570 1320 1690 1510 ...
     $ Man.trans.avail   : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 1 1 1 1 1 ...
     $ Fuel.tank.capacity: num  13.2 18 16.9 21.1 21.1 16.4 18 23 18.8 18 ...
     $ Passengers        : int  5 5 5 6 4 6 6 6 5 6 ...
     $ Length            : int  177 195 180 193 186 189 200 216 198 206 ...
     $ Wheelbase         : int  102 115 102 106 109 105 111 116 108 114 ...
     $ Width             : int  68 71 67 70 69 69 74 78 73 73 ...
     $ Turn.circle       : int  37 38 37 37 39 41 42 45 41 43 ...
     $ Rear.seat.room    : num  26.5 30 28 31 27 28 30.5 30.5 26.5 35 ...
     $ Luggage.room      : int  11 15 14 17 13 16 17 21 14 18 ...
     $ Weight            : int  2705 3560 3375 3405 3640 2880 3470 4105 3495 3620 ...
     $ Origin            : Factor w/ 2 levels "USA","non-USA": 2 2 2 2 2 1 1 1 1 1 ...
     $ Make              : Factor w/ 93 levels "Acura Integra",..: 1 2 4 3 5 6 7 9 8 10 ...
    

    .

    1️⃣ Example 1. SELECT

    เลือกข้อมูลจาก columns Manufacturer, Model, Min.Price, และ Max.Price:

    # Set query
    select_query <- "
    SELECT
      Manufacturer,
      Model,
      `Min.Price`,
      `Max.Price`
    FROM
      Cars93
    "
    
    # Select from df
    select_result <- sqldf(select_query)
    
    # View the result
    select_result
    

    Note: เราใช้ backticks (`) สำหรับชื่อ columns ที่ไม่ valid ใน SQL (เช่น column ที่มี . อย่าง Min.Price และ Max.Price)

    ผลลัพธ์:

        Manufacturer          Model Min.Price Max.Price
    1          Acura        Integra      12.9      18.8
    2          Acura         Legend      29.2      38.7
    3           Audi             90      25.9      32.3
    4           Audi            100      30.8      44.6
    5            BMW           535i      23.7      36.2
    6          Buick        Century      14.2      17.3
    7          Buick        LeSabre      19.9      21.7
    8          Buick     Roadmaster      22.6      24.9
    9          Buick        Riviera      26.3      26.3
    10      Cadillac        DeVille      33.0      36.3
    11      Cadillac        Seville      37.5      42.7
    12     Chevrolet       Cavalier       8.5      18.3
    13     Chevrolet        Corsica      11.4      11.4
    14     Chevrolet         Camaro      13.4      16.8
    15     Chevrolet         Lumina      13.4      18.4
    16     Chevrolet     Lumina_APV      14.7      18.0
    17     Chevrolet          Astro      14.7      18.6
    18     Chevrolet        Caprice      18.0      19.6
    19     Chevrolet       Corvette      34.6      41.5
    20      Chrylser       Concorde      18.4      18.4
    21      Chrysler        LeBaron      14.5      17.1
    22      Chrysler       Imperial      29.5      29.5
    23         Dodge           Colt       7.9      10.6
    24         Dodge         Shadow       8.4      14.2
    25         Dodge         Spirit      11.9      14.7
    26         Dodge        Caravan      13.6      24.4
    27         Dodge        Dynasty      14.8      16.4
    28         Dodge        Stealth      18.5      33.1
    29         Eagle         Summit       7.9      16.5
    30         Eagle         Vision      17.5      21.2
    31          Ford        Festiva       6.9       7.9
    32          Ford         Escort       8.4      11.9
    33          Ford          Tempo      10.4      12.2
    34          Ford        Mustang      10.8      21.0
    35          Ford          Probe      12.8      15.2
    36          Ford       Aerostar      14.5      25.3
    37          Ford         Taurus      15.6      24.8
    38          Ford Crown_Victoria      20.1      21.7
    39           Geo          Metro       6.7      10.0
    40           Geo          Storm      11.5      13.5
    41         Honda        Prelude      17.0      22.7
    42         Honda          Civic       8.4      15.8
    43         Honda         Accord      13.8      21.2
    44       Hyundai          Excel       6.8       9.2
    45       Hyundai        Elantra       9.0      11.0
    46       Hyundai         Scoupe       9.1      11.0
    47       Hyundai         Sonata      12.4      15.3
    48      Infiniti            Q45      45.4      50.4
    49         Lexus          ES300      27.5      28.4
    50         Lexus          SC300      34.7      35.6
    51       Lincoln    Continental      33.3      35.3
    52       Lincoln       Town_Car      34.4      37.8
    53         Mazda            323       7.4       9.1
    54         Mazda        Protege      10.9      12.3
    55         Mazda            626      14.3      18.7
    56         Mazda            MPV      16.6      21.7
    57         Mazda           RX-7      32.5      32.5
    58 Mercedes-Benz           190E      29.0      34.9
    59 Mercedes-Benz           300E      43.8      80.0
    60       Mercury          Capri      13.3      15.0
    61       Mercury         Cougar      14.9      14.9
    62    Mitsubishi         Mirage       7.7      12.9
    63    Mitsubishi       Diamante      22.4      29.9
    64        Nissan         Sentra       8.7      14.9
    65        Nissan         Altima      13.0      18.3
    66        Nissan          Quest      16.7      21.5
    67        Nissan         Maxima      21.0      22.0
    68    Oldsmobile        Achieva      13.0      14.0
    69    Oldsmobile  Cutlass_Ciera      14.2      18.4
    70    Oldsmobile     Silhouette      19.5      19.5
    71    Oldsmobile   Eighty-Eight      19.5      21.9
    72      Plymouth          Laser      11.4      17.4
    73       Pontiac         LeMans       8.2       9.9
    74       Pontiac        Sunbird       9.4      12.8
    75       Pontiac       Firebird      14.0      21.4
    76       Pontiac     Grand_Prix      15.4      21.6
    77       Pontiac     Bonneville      19.4      29.4
    78          Saab            900      20.3      37.1
    79        Saturn             SL       9.2      12.9
    80        Subaru          Justy       7.3       9.5
    81        Subaru         Loyale      10.5      11.3
    82        Subaru         Legacy      16.3      22.7
    83        Suzuki          Swift       7.3      10.0
    84        Toyota         Tercel       7.8      11.8
    85        Toyota         Celica      14.2      22.6
    86        Toyota          Camry      15.2      21.2
    87        Toyota         Previa      18.9      26.6
    88    Volkswagen            Fox       8.7       9.5
    89    Volkswagen        Eurovan      16.6      22.7
    90    Volkswagen         Passat      17.6      22.4
    91    Volkswagen        Corrado      22.9      23.7
    92         Volvo            240      21.8      23.5
    93         Volvo            850      24.8      28.5
    

    .

    2️⃣ Example 2. WHERE

    คัดกรองข้อมูลรถที่ชื่อผู้ผลิตขึ้นต้นด้วย “M”:

    # Set query
    where_result <- "
    SELECT
      Manufacturer,
      Model,
      `Min.Price`,
      `Max.Price`
    FROM
      Cars93
    WHERE
      Manufacturer LIKE 'M%'
    "
    
    # Filter df
    where_result <- sqldf(where_result)
    
    # View the result
    where_result
    

    ผลลัพธ์:

        Manufacturer    Model Min.Price Max.Price
    1          Mazda      323       7.4       9.1
    2          Mazda  Protege      10.9      12.3
    3          Mazda      626      14.3      18.7
    4          Mazda      MPV      16.6      21.7
    5          Mazda     RX-7      32.5      32.5
    6  Mercedes-Benz     190E      29.0      34.9
    7  Mercedes-Benz     300E      43.8      80.0
    8        Mercury    Capri      13.3      15.0
    9        Mercury   Cougar      14.9      14.9
    10    Mitsubishi   Mirage       7.7      12.9
    11    Mitsubishi Diamante      22.4      29.9
    

    .

    3️⃣ Example 3. Aggregate

    หารถ 10 อันดับแรกที่มีราคาสูงสุด:

    # Set query
    aggregate_query <- "
    SELECT
      Manufacturer,
      AVG(Price) AS Avg_Price
    FROM
      Cars93
    GROUP BY
      Manufacturer
    ORDER BY
      Avg_Price DESC
    LIMIT
      10;
    "
    
    # Aggregate df
    aggregate_result <- sqldf(aggregate_query)
    
    # View the result
    aggregate_result
    

    ผลลัพธ์:

        Manufacturer Avg_Price
    1       Infiniti      47.9
    2  Mercedes-Benz      46.9
    3       Cadillac      37.4
    4        Lincoln      35.2
    5           Audi      33.4
    6          Lexus      31.6
    7            BMW      30.0
    8           Saab      28.7
    9          Acura      24.9
    10         Volvo      24.7
    

    😺 GitHub

    ดูตัวอย่าง code ทั้งหมดได้ที่ GitHub


    📃 References


    ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    📕 ขอฝากหนังสือเล่มแรกในชีวิตด้วยนะครับ 😆

    🙋 ใครที่กำลังเรียนจิตวิทยาหรือทำงานสายจิตวิทยา และเบื่อที่ต้องใช้ software ราคาแพงอย่าง SPSS และ Excel เพื่อทำข้อมูล

    💪 ผมขอแนะนำ R Book for Psychologists หนังสือสอนใช้ภาษา R เพื่อการวิเคราะห์ข้อมูลทางจิตวิทยา ที่เขียนมาเพื่อนักจิตวิทยาที่ไม่เคยมีประสบการณ์เขียน code มาก่อน

    ในหนังสือ เราจะปูพื้นฐานภาษา R และพาไปดูวิธีวิเคราะห์สถิติที่ใช้บ่อยกัน เช่น:

    • Correlation
    • t-tests
    • ANOVA
    • Reliability
    • Factor analysis

    🚀 เมื่ออ่านและทำตามตัวอย่างใน R Book for Psychologists ทุกคนจะไม่ต้องพึง SPSS และ Excel ในการทำงานอีกต่อไป และสามารถวิเคราะห์ข้อมูลด้วยตัวเองได้ด้วยความมั่นใจ

    แล้วทุกคนจะแปลกใจว่า ทำไมภาษา R ง่ายขนาดนี้ 🙂‍↕️

    👉 สนใจดูรายละเอียดหนังสือได้ที่ meb:

  • readxl และ XLConnect: วิธีใช้ 2 packages สำหรับทำงานกับ Excel ในภาษา R — ตัวอย่างการทำงานกับ Daily Household Transactions

    readxl และ XLConnect: วิธีใช้ 2 packages สำหรับทำงานกับ Excel ในภาษา R — ตัวอย่างการทำงานกับ Daily Household Transactions

    Excel เป็นเครื่องมือทำงานยอดนิยมในการทำงาน ซึ่งทำให้ในหลาย ๆ ครั้ง ข้อมูลที่เราต้องการถูกเก็บอยู่ในไฟล์ Excel (เช่น .xls และ .xlsx)

    ในบทความนี้ เราจะมาทำความรู้จักกับ readxl และ XLConnect ซึ่งเป็น packages สำหรับทำงานกับ Excel ในภาษา R กัน

    เราจะดูการใช้งานผ่านตัวอย่างการทำงานกับ Daily Transactions Dataset จาก Kaggle ที่ถูกเก็บในไฟล์ XLSX (”Daily Household Transactions.xlsx”):

    ข้อมูลใน ”Daily Household Transactions.xlsx”

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 1️⃣ Package 1. readxl
    2. 2️⃣ Package 2. XLConnect
      1. 📔 กรณีที่ 1. โหลดและสำรวจ Workbook
      2. ⬇️ กรณีที่ 2. โหลดข้อมูลจาก sheet
      3. 🖐️ กรณีที่ 3. จัดการ Sheet
      4. ➕ กรณีที่ 4. เพิ่มข้อมูลใน Sheet
      5. 💾 กรณีที่ 5. บันทึก Workbook
    3. 💪 Summary
    4. 😺 GitHub
    5. 📃 References
    6. ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    1️⃣ Package 1. readxl

    readxl เป็น package สำหรับโหลดข้อมูลจาก Excel และมี function ที่เราจะเรียกใช้งานได้ คือ read_excel() ซึ่งต้องการ 2 arguments:

    1. path: ชื่อไฟล์ หรือ file path
    2. sheet: ชื่อหรือลำดับของ sheet ที่เก็บข้อมูลที่เราต้องการ

    ในการเริ่มต้นใช้งาน readxl เราจะติดตั้งและโหลด package:

    # Install readxl
    install.packages("readxl")
    
    # Load readxl
    library(readxl)
    

    จากนั้น เรียกใช้ read_excel() เพื่อโหลดข้อมูล:

    # Import Excel data with read_excel()
    all_transactions <- read_excel("Daily Household Transactions.xlsx",
                                   sheet = 1)
    
    # View the first few rows
    head(all_transactions)
    

    ผลลัพธ์:

    # A tibble: 6 × 8
      Date                Mode              Category Subcategory Note  Amount `Income/Expense` Currency
      <dttm>              <chr>             <chr>    <chr>       <chr>  <dbl> <chr>            <chr>   
    1 2018-09-20 12:04:08 Cash              Transpo… Train       2 Pl…     30 Expense          INR     
    2 2018-09-20 12:03:15 Cash              Food     snacks      Idli…     60 Expense          INR     
    3 2018-09-19 00:00:00 Saving Bank acco… subscri… Netflix     1 mo…    199 Expense          INR     
    4 2018-09-17 23:41:17 Saving Bank acco… subscri… Mobile Ser… Data…     19 Expense          INR     
    5 2018-09-16 17:15:08 Cash              Festiva… Ganesh Puj… Gane…    251 Expense          INR     
    6 2018-09-15 06:34:17 Credit Card       subscri… Tata Sky    Perm…    200 Expense          INR     
    

    Note: read_excel() มี parametres อื่น ๆ ที่เราสามารถตั้งค่าได้ เช่น:

    • range: ช่วงข้อมูลที่เราต้องการโหลด
    • col_names: ชื่อ columns
    • col_types: ประเภทข้อมูลในแต่ละ column
    • skip: จำนวน rows ที่เราจะข้ามในการโหลดข้อมูล เช่น เรากำหนด skip = 5, read_excel() จะโหลดข้อมูลตั้งแต่ row ที่ 6 เป็นต้นไป

    ดูคู่มือการใช้งาน read_excel() ทั้งหมดได้ที่ read_excel: Read xls and xlsx files.


    2️⃣ Package 2. XLConnect

    XLConnect เป็น package ที่ช่วยให้เราทำงานกับไฟล์ Excel จาก R ได้โดยตรง

    การใช้งาน XLConnect แบ่งได้เป็น 5 กรณี ดังนี้:

    1. โหลดและสำรวจ workbook
    2. โหลดข้อมูลจาก sheet
    3. จัดการ sheet
    4. เพิ่มข้อมูลใน sheet
    5. บันทึก workbook

    เราไปดูการใช้งานในแต่ละกรณีกัน

    .

    📔 กรณีที่ 1. โหลดและสำรวจ Workbook

    ในการเริ่มใช้งาน XLConnect เราจะต้องติดตั้งและโหลด package ก่อน:

    # Install
    install.packages("XLConnect")
    
    # Load
    library(XLConnect)
    

    จากนั้น เราสามารถโหลด Excel เราเข้ามาใน R ได้ด้วย loadWorkbook():

    # Load the workbook
    workbook <- loadWorkbook("Daily Household Transactions.xlsx")
    

    และดู sheet ทั้งหมดใน workbook ด้วย getSheets():

    # List sheets
    getSheets(workbook)
    

    ผลลัพธ์:

    [1] "All Transactions"
    

    ในตัวอย่าง จะเห็นว่า Excel ของเรามี 1 sheet ได้แก่ “All Transactions”

    .

    ⬇️ กรณีที่ 2. โหลดข้อมูลจาก sheet

    เมื่อเห็นโครงสร้างของไฟล์ Excel แล้ว เราสามารถโหลดข้อมูลจาก sheet ที่ต้องการได้ด้วย readWorksheet():

    # Get sheet data
    sheet1_data <- readWorksheet(workbook,
                                 sheet = "All Transactions")
    
    # Print data
    head(sheet1_data)
    

    ผลลัพธ์:

                     Date                  Mode       Category             Subcategory                                     Note Amount Income.Expense Currency
    1 2018-09-20 12:04:08                  Cash Transportation                   Train                     2 Place 5 to Place 0     30        Expense      INR
    2 2018-09-20 12:03:15                  Cash           Food                  snacks              Idli medu Vada mix 2 plates     60        Expense      INR
    3 2018-09-19 00:00:00 Saving Bank account 1   subscription                 Netflix                     1 month subscription    199        Expense      INR
    4 2018-09-17 23:41:17 Saving Bank account 1   subscription Mobile Service Provider                        Data booster pack     19        Expense      INR
    5 2018-09-16 17:15:08                  Cash      Festivals            Ganesh Pujan                              Ganesh idol    251        Expense      INR
    6 2018-09-15 06:34:17           Credit Card   subscription                Tata Sky Permanent Residence - Tata Play recharge    200        Expense      INR
    

    .

    🖐️ กรณีที่ 3. จัดการ Sheet

    ในการจัดการ sheet เราสามารถทำได้ 3 อย่าง:

    1. สร้าง sheet ใหม่: createSheet()
    2. เปลี่ยนชื่อ sheet: renameSheet()
    3. ลบ sheet: removeSheet()

    ยกตัวอย่างการสร้าง sheet ใหม่:

    # Create new sheets
    createSheet(workbook,
                name = "New")
    
    # List sheets
    getSheets(workbook)
    

    ผลลัพธ์:

    [1] "All Transactions" "New" 
    

    เปลี่ยนชื่อ sheet:

    # Rename the new sheet
    renameSheet(workbook,
                sheet = "New",
                newName = "Some Transactions")
    
    # List sheets
    getSheets(workbook)
    

    ผลลัพธ์:

    [1] "All Transactions"  "Some Transactions"
    

    และลบ sheet ทิ้ง:

    # Delete the new sheet
    removeSheet(workbook,
                sheet = "Some Transactions")
    
    # List sheets
    getSheets(workbook)
    

    ผลลัพธ์:

    [1] "All Transactions" 
    

    .

    ➕ กรณีที่ 4. เพิ่มข้อมูลใน Sheet

    เราสามารถใส่ข้อมูลลงใน sheet ได้ด้วย writeWorksheet()

    ยกตัวอย่างเช่น เราต้องการเพิ่มข้อมูลสรุปค่าใช้จ่ายตามประเภทการใช้จ่าย

    เราจะเริ่มจากสรุปค่าใช้จ่ายตามประเภทโดยใช้ dplyr package:

    # Load dplyr
    library(dplyr)
    
    # Calculate expense by category
    expense_by_cat <- sheet1_data |>
      
      # Filter for expense
      filter(Income.Expense == "Expense") |>
      
      # Group by category
      group_by(Category) |>
      
      # Calculate sum amount
      summarise(Sum = sum(Amount)) |>
        
      # Ungroup
      ungroup() |>
      
      # Sort by category
      arrange(desc(Sum))
    
    # View the results
    expense_by_cat
    

    (Note: อ่านเกี่ยวกับการใช้ dplyr ได้ที่นี่)

    ผลลัพธ์:

    # A tibble: 27 × 2
       Category                  Sum
       <chr>                   <dbl>
     1 Money transfer        606529.
     2 Investment            271858 
     3 Transportation        169054.
     4 Household             161646.
     5 subscription          114588.
     6 Food                   96403.
     7 Public Provident Fund  90000 
     8 Other                  87025.
     9 Family                 78582.
    10 Health                 66253.
    # ℹ 17 more rows
    # ℹ Use `print(n = ...)` to see more rows
    

    จากนั้น สร้าง sheet ใหม่เพื่อเก็บข้อมูลที่เราได้มา:

    # Create a new sheet
    createSheet(workbook,
                name = "Expense by Category")
    
    # Add data to "Expense by Catogory" sheet
    writeWorksheet(workbook,
                   data = expense_by_cat,
                   sheet = "Expense by Category")
    

    เมื่อเราเรียกดูข้อมูลจาก “Expense by Catogory” เราจะเห็นข้อมูลแบบนี้:

    # Read the sheet
    readWorksheet(workbook,
                  sheet = "Expense by Category")
    

    ผลลัพธ์:

                    Category       Sum
    1         Money transfer 606528.90
    2             Investment 271858.00
    3         Transportation 169053.78
    4              Household 161645.58
    5           subscription 114587.91
    6                   Food  96403.10
    7  Public Provident Fund  90000.00
    8                  Other  87025.28
    9                 Family  78582.20
    10                Health  66252.75
    11               Tourism  63608.85
    12                  Gift  40168.00
    13               Apparel  25373.82
    14     Recurring Deposit  22000.00
    15                  maid  21839.00
    16                  Cook  12443.00
    17                  Rent  10709.00
    18             Festivals   6911.00
    19               Culture   4304.36
    20                Beauty   4189.00
    21      Self-development   2357.00
    22             Education    537.00
    23              Grooming    400.00
    24           Social Life    298.00
    25   water (jar /tanker)    148.00
    26             Documents    100.00
    27      garbage disposal     67.00
    

    .

    💾 กรณีที่ 5. บันทึก Workbook

    จนถึงจุดนี้ สิ่งที่เราแก้ไขไปจะยังไม่ถูกบันทึกลงในไฟล์ Excel ของเรา

    เราต้องใช้ saveWorkbook() เพื่อบันทึกการเปลี่ยนแปลงทั้งหมดได้

    อย่างในตัวอย่าง เราจะบันทึกการเปลี่ยนแปลงทั้งหมดไปที่ workbook ใหม่ชื่อ “Daily Household Transactions (Updated).xlsx”:

    # Save the file
    saveWorkbook(workbook,
                 file = "Daily Household Transactions (Updated).xlsx")
    

    เมื่อเราเปิด working directory ดู เราจะเห็น Excel 2 ไฟล์:

    1. ไฟล์ต้นฉบับ
    2. ไฟล์ที่เราสร้างใหม่
    Workbook ต้นฉบับ (ซ้าย) และ workbook ที่เราสร้างใหม่ (ขวา)

    💪 Summary

    ในบทความนี้ เราได้เรียนรู้วิธีการทำงานกับ Excel ในภาษา R ผ่าน 2 packages ได้แก่:

    Package 1. readxl:

    FunctionFor
    read_excel()โหลดข้อมูลจาก Excel

    Package 2. XLConnect:

    FunctionFor
    loadWorkbook()โหลด workbook
    getSheets()ดู sheets ใน workbook
    readWorksheet()โหลดข้อมูลจาก sheet
    createSheet()สร้าง sheet
    renameSheet()เปลี่ยนชื่อ sheet
    removeSheet()ลบ sheet
    writeWorksheet()เพิ่มข้อมูลใน sheet
    saveWorkbook()บันทึก workbook

    😺 GitHub

    ดู code และ Excel ตัวอย่างได้ที่ GitHub


    📃 References


    ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    📕 ขอฝากหนังสือเล่มแรกในชีวิตด้วยนะครับ 😆

    🙋 ใครที่กำลังเรียนจิตวิทยาหรือทำงานสายจิตวิทยา และเบื่อที่ต้องใช้ software ราคาแพงอย่าง SPSS และ Excel เพื่อทำข้อมูล

    💪 ผมขอแนะนำ R Book for Psychologists หนังสือสอนใช้ภาษา R เพื่อการวิเคราะห์ข้อมูลทางจิตวิทยา ที่เขียนมาเพื่อนักจิตวิทยาที่ไม่เคยมีประสบการณ์เขียน code มาก่อน

    ในหนังสือ เราจะปูพื้นฐานภาษา R และพาไปดูวิธีวิเคราะห์สถิติที่ใช้บ่อยกัน เช่น:

    • Correlation
    • t-tests
    • ANOVA
    • Reliability
    • Factor analysis

    🚀 เมื่ออ่านและทำตามตัวอย่างใน R Book for Psychologists ทุกคนจะไม่ต้องพึง SPSS และ Excel ในการทำงานอีกต่อไป และสามารถวิเคราะห์ข้อมูลด้วยตัวเองได้ด้วยความมั่นใจ

    แล้วทุกคนจะแปลกใจว่า ทำไมภาษา R ง่ายขนาดนี้ 🙂‍↕️

    👉 สนใจดูรายละเอียดหนังสือได้ที่ meb:

  • if, for, while ใน Python: วิธีใช้ conditional statements, control flow, และ loop control ใน Python พร้อมตัวอย่าง

    if, for, while ใน Python: วิธีใช้ conditional statements, control flow, และ loop control ใน Python พร้อมตัวอย่าง

    ในบทความนี้ เราจะมาดูวิธีใช้ code 3 ประเภท ที่จะช่วยให้ Python code สามารถตัดสินใจแทนเราได้:

    1. Conditional statements: if, elif, else
    2. Control flow statements: for, while
    3. Loop control statements: continue, break, pass

    ก่อนไปดูวิธีใช้ทั้ง 3 ประเภท เราจะไปทำความรู้จักกับ comparison และ logical statement ซึ่งเราจะใช้ร่วมกับ code 3 ประเภทนี้กัน

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 🧮 1. Comparison & Logical Operators
      1. #️⃣ (1) Comparison Operators
      2. ♟️ (2) Logical Operators
    2. 🚦 2. Conditional Statements
    3. 🌊 3. Control Flow Statements
      1. 📦 (1) for Loop
      2. 🔁 (2) while Loop
    4. 🚄 4. Loop Control Statements
    5. 💪 5. Summary
    6. 😺 GitHub
    7. 📃 References

    🧮 1. Comparison & Logical Operators

    #️⃣ (1) Comparison Operators

    Comparison operators เป็นเครื่องหมายใช้เปรียบเทียบข้อมูล:

    OperatorDescription
    ==เท่ากับ
    !=ไม่เท่ากับ
    >มากกว่า
    >=มากกว่า/เท่ากับ
    <น้อยกว่า
    <=น้อยกว่า/เท่ากับ

    โดย comparison operators จะให้ผลลัพธ์เป็น Boolean (True, False) กลับมา เช่น:

    # True statement
    10 > 5
    

    ผลลัพธ์:

    True
    

    และ:

    # False statement
    10 < 5
    

    ผลลัพธ์:

    False
    

    ♟️ (2) Logical Operators

    Logical operators เป็น keywords เชื่อมเงื่อนไข ช่วยให้เราประเมินหลายเงื่อนไขพร้อมกันได้:

    OperatorDescription
    andLogical AND
    orLogical OR
    notLogical NOT

    โดยผลลัพธ์เป็นไปตาม truth table:

    Condition 1OperatorCondition 2Result
    TrueandTrueTrue
    TrueandFalseFalse
    FalseandFalseFalse
    TrueorTrueTrue
    TrueorFalseTrue
    FalseorFalseFalse
    notTrueFalse
    notFalseTrue

    ยกตัวอย่างเช่น:

    # True and True
    1 == 1 and 2 < 4
    

    ผลลัพธ์:

    True
    

    🚦 2. Conditional Statements

    Conditional statements ใช้กำหนดเงื่อนไขว่า code จะรันได้เมื่อไร และมีอยู่ 3 แบบ ได้แก่:

    • if: กำหนดเงื่อนไขแรก
    • elif: กำหนดเงื่อนไขเพิ่มเติม
    • else: รันเมื่อตรงกับเงื่อนไขอื่น ๆ ที่ไม่ใช่ if และ elif

    ยกตัวอย่างเช่น เราต้องการ print ข้อความแจ้งเตือนตามสภาพอากาศ:

    # Weather today
    weather = "snowy"
    

    เราสามารถทำได้แบบนี้:

    # Print when sunny
    if weather == "sunny":
        print("It's a sunny day. Don't forget your sunscreen!")
    
    # Print when rainy
    elif weather == "rainy":
        print("It's raining. Remember to bring an umbrella!")
    
    # Print when other conditions
    else:
        print("Likely chilly. Wear a jacket!")
    

    ผลลัพธ์:

    Likely chilly. Wear a jacket!
    

    อธิบาย code:

    • if block: ประเมินว่า weather เป็น "sunny" ไหม ถ้าใช่ จะ print "It's a sunny day. Don't forget your sunscreen!"
    • elif block: weather เป็น "rainy" ไหม ถ้าใช่ จะ print "It's raining. Remember to bring an umbrella!"
    • else block: ถ้า weather เป็นค่าอื่น ๆ (เช่น "snowy") จะ print "Likely chilly. Wear a jacket!"

    เพราะ weather มีค่าตรงกับ else block เราจึงได้ผลลัพธ์เป็น "Likely chilly. Wear a jacket!"


    🌊 3. Control Flow Statements

    Control flow statements ใช้ควบคุมลำดับการทำงานของ code และมีอยู่ 2 แบบ ได้แก่:

    1. for: รัน code ตามจำนวนข้อมูลที่มี
    2. while: รัน code จนกว่าเงื่อนไขจะไม่เป็นจริง

    📦 (1) for Loop

    ตัวอย่าง for loop เช่น print ชื่อแขกในงาน:

    # Guest list
    guests = ["James Bond", "John Wick", "Jack Reacher", "Jason Bourne", "Jack Ryan"]
    
    # Print guest names
    for name in guests:
        
        # Print name
        print(name)
    

    ผลลัพธ์:

    James Bond
    John Wick
    Jack Reacher
    Jason Bourne
    Jack Ryan
    

    อธิบาย code:

    • guest = ...: สร้าง list เก็บรายชื่อแขก
    • for ...: นำชื่อแขกใน list มา print จนกว่าจะครบทุกคน

    🔁 (2) while Loop

    ตัวอย่าง while loop เช่น นับเลข 1 ถึง 10:

    # Starting number
    number = 1
    
    # Count to 10
    while number <= 10:
        
        # Print number
        print(number)
        
        # Add 1 to number
        number += 1
    

    ผลลัพธ์:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    

    อธิบาย code:

    • number = 1: กำหนดเลขเริ่มต้น
    • while ...: print number และปรับ number ให้สูงขึ้น 1 ค่า ทำอย่างนี้วนไปจนกว่า number จะมากกว่า 10 (number <= 10 ไม่เป็นจริง)

    🚄 4. Loop Control Statements

    Loop control statements ใช้ควบคุมการทำงานของ control flow และมีอยู่ 3 แบบ ได้แก่:

    1. continue: skip ไป item ถัดไป
    2. break: หยุดการทำงานของ control flow
    3. pass: placeholder สำหรับใส่ code ในอนาคต

    ยกตัวอย่างเช่น เรามีรายการของที่ต้องซื้อ และแต่ละอย่างมี action ไม่เหมือนกัน:

    # A shopping list program
    shopping_list = ["milk", "bread", "chips", "apple", "toothpaste", "chocolate"]
    
    # Loop through the list
    for item in shopping_list:
    
        # Skip item if chip
        if item == "chips":
            print("Chips are unhealthy. Skipping ...")
            continue
        
        # Stop the loop if toothpaste
        if item == "toothpaste":
            print("Found toothpaste, done shopping early!")
            break
        
        # Do nothing if milk
        if item == "milk" or item == "bread":
            pass
        
        # Print item
        print("Putting", item, "into the cart.")
    

    ผลลัพธ์:

    Putting milk into the cart.
    Putting bread into the cart.
    Chips are unhealthy. Skipping ...
    Putting apple into the cart.
    Found toothpaste, done shopping early!
    

    อธิบาย code:

    • shopping_list = ...: สร้าง list เก็บรายการซื้อของ
    • if item == "chips" block: ประเมินว่า item ใช่ "chip" ไหม ถ้าใช่ ให้ print "Chips are unhealthy. Skipping ..." และข้ามไป item ถัดไป (continue)
    • if item == "toothpaste" block: ประเมินว่า item ใช่ "toothpaste" ไหม ถ้าใช่ ให้ print "Found toothpaste, done shopping early!" และจบ loop ทันที (break)
    • if item == "milk" … block: ประเมินว่า item ใช่ "milk" หรือ "bread" ไหม ถ้าใช่ ไม่ต้องทำอะไร (pass)
    • print ...: print ว่า กำลังเอา item ใส่ตระกร้า

    สังเกตว่า:

    • มีแค่ milk, bread, apple ที่ “กำลังใส่ตระกร้า” เพราะ milk และ bread อยู่ใน pass block และ apple ไม่ได้อยู่ใน block ไหนเลย
    • Chip ถูกข้ามไป เพราะอยู่ใน continue block
    • Toothpaste อยู่ใน break block และมาก่อน chocolate ทำให้เราไม่เห็น chocolate เพราะ toothpaste

    💪 5. Summary

    ในบทความนี้ เราได้ไปดูวิธีการเขียน code ใน Python เพื่อให้ code ตัดสินใจได้:

    Comparison operators:

    OperatorDescription
    ==เท่ากับ
    !=ไม่เท่ากับ
    >มากกว่า
    >=มากกว่า/เท่ากับ
    <น้อยกว่า
    <=น้อยกว่า/เท่ากับ

    Logical operators:

    OperatorDescription
    andLogical AND
    orLogical OR
    notLogical NOT

    Conditional statements:

    StatementDescription
    ifกำหนดเงื่อนไขแรก
    elifกำหนดเงื่อนไขเพิ่มเติม
    elseทำ action เมื่อเข้าเงื่อนไขอื่น ๆ

    Control flow statements:

    StatementDescription
    forวนจนครบทุก item
    whileวนจนกว่าเงื่อนไขจะเป็น False

    Loop control statements:

    StatementDescription
    continueSkip
    breakStop
    passDo nothing

    😺 GitHub

    ดูตัวอย่าง code ทั้งหมดในบทความนี้ได้ที่ GitHub


    📃 References

  • Building Judgment: สรุป 3 แนวทางในการพัฒนาความคิดให้เฉียบคม จากหนังสือ The Almanack of Naval Ravikant โดย Eric Jorgenson — Think Clearly, Mental Models, และ Read

    Building Judgment: สรุป 3 แนวทางในการพัฒนาความคิดให้เฉียบคม จากหนังสือ The Almanack of Naval Ravikant โดย Eric Jorgenson — Think Clearly, Mental Models, และ Read

    The Almanack of Naval Ravikant เป็นหนังสือของ Eric Jorgenson นักเขียนเกี่ยวกับ startups ซึ่งรวบรวมปรัชญาการใช้ชีวิตและความมั่งคั่ง (wealth) ของ Naval Ravikant นักลงทุนที่ประสบความสำเร็จจากการลงทุนในบริษัทอย่าง Uber, Foursquare, และ Twitter (X) และเป็น CEO ของ AngelList บริษัทที่ช่วยให้ startups ได้พบกับ angel investors เอาไว้

    ในบทความนี้ เราจะสรุปบทเรียน Building Judgment ซึ่งเป็นบทที่ 2 จาก 5 ในหนังสือ

    บทสรุปแบ่งออกเป็น 4 กลุ่ม ได้แก่:

    1. What and why of judgment: นิยามและความสำคัญของ judgment
    2. Think clearly: วิธีคิดให้ทะลุปรุโปร่ง
    3. Mental models: หลักการคิดที่ควรมี
    4. Read: แนวคิดเกี่ยวกับการอ่าน

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    หน้าปกหนังสือ The Almanack of Naval Ravikant บน Amazon

    1. ⚖️ What & Why of Judgment
    2. 😎 Think Clearly
      1. 🌱 Basic Knowledge: Start from the Ground Up
      2. 🥠 Reality: See Past the Identity
      3. 🙂 Additional Tips: Honesty & Criticism
    3. 🧠 Mental Models
    4. 📖 Read
      1. 🔖 What & How to Read
    5. 🌻 Summary
    6. 🔥 Get The Almanack of Naval Ravikant

    ⚖️ What & Why of Judgment

    The direction you’re heading in matters more than how fast you move, especially with leverage.

    — Naval Ravikant

    Judgment ในนิยามของ Naval คือ การประยุกต์ใช้ wisdom กับปัญหาภายนอก

    Wisdom หมายถึง ความสามารถในการมองเห็นผลลัพธ์ในระยะยาวของการกระทำ

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

    Judgment = wisdom(external problems)
    

    ในยุคที่เทคโนโลยีพัฒนาอย่างรวดเร็ว judgment มีความสำคัญ เพราะเทคโนโลยีสามารถขยาย impact ของการตัดสินใจของเราได้หลายเท่าตัว

    ยกตัวอย่าง เรามีไอเดียและโพสต์ไอเดียลง social media เราสามารถเข้าถึงคนที่เราต้องการได้ภายในเวลาอันสั้น และถ้าไอเดียนี้ดี เราก็จะได้ผลตอบรับที่ดีจำนวนมากกลับมา แต่ถ้าเป็นไอเดียไม่เป็นที่ยอมรับของสังคม เราก็จะได้รับแรงต้านมหาศาลเช่นกัน

    ถ้าเรามี judgment ที่ดีกว่าคนอื่นเพียงนิดเดียว เราก็สามารถเห็นผลลัพธ์ที่แตกต่างกันได้อย่างสิ้นเชิง

    In an age of leverage, one correct decision can win everything.

    — Naval Ravikant

    ทั้งนี้ เรามี 3 วิธีในการพัฒนา judgment ของเรา ได้แก่:

    1. Think clearly
    2. Mental models
    3. Read

    ไปดูรายละเอียดของแต่ละวิธีกัน


    😎 Think Clearly

    “Clear thinker” is a better compliment than “smart.”

    — Naval Ravikant

    Think clearly คือ การคิดที่ตั้งอยู่บนพื้นฐานของความเป็นจริง (reality) และประกอบด้วย 2 ส่วน ได้แก่:

    1. ความรู้ขั้นพื้นฐาน
    2. การมองเห็นความเป็นจริง

    .

    🌱 Basic Knowledge: Start from the Ground Up

    Real knowledge is intrinsic, and it’s built from the ground up.

    — Naval Ravikant

    คนที่มี judgment ที่ดีมักมีความรู้ขั้นพื้นฐานที่ดี เพราะเมื่อเรามีความรู้พื้นฐานแล้ว เราสามารถต่อยอดเป็นความรู้ที่ซับซ้อนมากขึ้นได้

    ในมุมมองของ Naval คนที่ฉลาดมักจะเป็นคนที่เข้าใจความรู้พื้นฐานอย่างท่องแท้ ยกตัวอย่างเช่น Richard Feynman นักฟิสิกส์ที่ได้ Nobel Prize ในปี 1965 ซึ่งสามารถอธิบายคณิตศาสตร์ได้โดยเริ่มจากการนับเลขและต่อยอดไปเรื่อย ๆ ไปจนถึงพีชคณิตและตรีโกณมิติ (precalculus) โดยไม่ใช้นิยามใด ๆ แต่ใช้ chain of logic อย่างเดียว

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

    .

    🥠 Reality: See Past the Identity

    The hard thing is seeing the truth.

    — Naval Ravikant

    คนที่มี judgment ที่ดี คือ คนที่เข้าใกล้ reality ได้มากที่สุด

    การเข้าใกล้ reality ไม่ใช่เรื่องง่าย เพราะมีปัจจัยหลายอย่างที่ขัดขวางไม่ให้เราเห็น reality เช่น:

    • Desires: สิ่งที่เราต้องการให้เป็น
    • Expectations: ความคาดหวัง
    • Beliefs: ความเชื่อ
    • Habits: ความเคยชิน

    Naval เรียกปัจจัยเหล่านี้รวมกันว่า identity หรือ ego ที่ก่อรูปเป็นตัวเราและคอยกำกับการกระทำของเรา

    What we wish to be true clouds our perception of what is true.

    — Naval Ravikant

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

    ยกตัวอย่างเช่น เราเชื่อว่าธุรกิจกำลังไปได้ดี ทำให้เราตัดสินใจลงทุนเพิ่ม ทั้ง ๆ ที่เศรษฐกิจกำลังซบเซา ทำให้การตัดสินใจของเราส่งผลเสีย (แทนที่จะเป็นผลดี) ต่อธุรกิจ

    ยิ่งเราเข้าใกล้ reality ได้มากเท่าไร เราก็ยิ่งมี judgment ที่ดีขึ้นเท่านั้น

    .

    🙂 Additional Tips: Honesty & Criticism

    You should never, ever fool anybody, and you are the easiest person to fool.

    — Richard Feynman

    Naval แนะนำอีก 2 เคล็ดลับที่จะช่วยให้เราคิดได้ดีขึ้น ได้แก่:

    1. Radical honesty
    2. Praise specifically, criticise generally

    Radical honesty หมายถึง เราควรซื่อสัตย์ต่อทั้งตัวเองและคนอื่น เพราะคนที่ถูกหลอกง่ายที่สุดคือตัวเอง

    ถ้าเราโกหกคนอื่น เราจะเชื่อคำโกหกของตัวเอง ทำให้เราไม่สามารถเป็นตัวของตัวเองได้ รวมทั้งทำให้เราหลุดจากความเป็นจริง

    Praise specifically, criticise generally เป็นแนวคิดที่ Naval ได้มาจาก Warren Buffet ซึ่งหมายถึง:

    • เวลาที่เราวิพากวิจารณ์ใคร เราควรวิจารณ์แนวทางมากกว่าตัวบุคคล
    • เวลาที่เราชื่นชมใคร ให้เราชมตัวบุคคล

    ยกตัวอย่างเช่น:

    • ถ้าเราเห็นพนักงานทำงานไม่ดี ให้เราวิจารณ์แนวทางในการทำงานที่พนักงานใช้
    • ถ้าเราเห็นพนักงานทำงานได้ดี เราควรชื่นชมพนักงาน เพราะเป็นตัวอย่างคนทำงานที่ดี

    การทำอย่างนี้จะช่วยทำให้คนอื่นอยากทำงานกับเรา มากกว่าต่อต้านเรา เพราะเราไม่ได้โจมตี identity/ego ของคนอื่น


    🧠 Mental Models

    What you want is principles. You want mental models.

    — Naval Ravikant

    Mental model เป็นเหมือนแผนที่ที่บอกว่า สิ่งต่าง ๆ ทำงานยังไง เช่น ถ้า X เกิดขึ้น Y จะตามมา

    ถ้าเราอยากจะมี judgment ที่ดี เราควรมี mental models ที่จะช่วยให้เราตัดสินใจได้ถูกต้องและแม่นยำ

    Naval แนะนำ 12 mental models ที่น่าสนใจ:

    1. Evolution: ทุกอย่างที่เกิดขึ้นในอารยธรรมสามารถอธิบายได้ด้วยหลัก evolution ที่ว่า ใครจะอยู่รอดและได้สืบพันธุ์ต่อไป
    2. Inversion: แนวคิดในการตัดตัวเลือกที่ไม่ใช่ แทนการมองหาตัวเลือกที่ใช่
    3. Complexity theory: Naval เชื่อว่า คนเราใสซื่อจนเกินไปและมีความสามารถในการทำนายอนาคตที่แย่มาก
    4. Economics: ความรู้เชิงเศรษฐศาสตร์ต่าง ๆ เช่น demand-supply, game theory
    5. Principal-agent problem: แนวคิดที่ว่า ความไม่สอดคล้องอาจเกิดขึ้นได้เมื่อเรา (principal) ให้คนอื่น (agent) ทำงานให้กับเรา เพราะ agent ไม่สามารถรู้ความต้องการของ principal ได้ตลอดเวลา เช่น เราฝากเพื่อนซื้อข้าว เพื่อนอาจซื้อข้าวผัดมาให้เพราะเห็นเรากินข้าวผัดในอดีต แต่วันนี้ เราอยากกินก๋วยเตี๋ยว ทำให้ข้าวที่ซื้อมาไม่ตรงโจทย์
    6. Compound interest: แนวคิดที่ว่า ดอกเบี้ยทบต้นไม่ได้ใช้ได้กับการเงินเท่านั้น แต่ยังใช้ได้กับด้านอื่น ๆ ของชีวิต เช่น การหาลูกค้า ถ้าบริษัทมีผู้ใช้ 100 คนในเดือนแรก และมียอดการเติบโตของผู้ใช้ 20% ต่อเดือน ภายใน 1 ปี บริษัทจะมีผู้ใช้งานถึงเกือบ 900 คน
    7. Basic math: ความรู้ทางคณิตศาสตร์ เช่น การคิดบวกลบเลข ความน่าจะเป็น และสถิติ
    8. Black swans: แนวคิดของ Nassim Nicholas Taleb นักวิทยาศาสตร์และนักปรัชญา ซึ่งหมายถึง เหตุการณ์ที่มีโอกาสเกิดขึ้นน้อยมาก แต่มีผลกระทบในวงกว้าง Naval แนะนำให้ศึกษางานของ Nassim ถ้าต้องการศึกษาเพิ่มเติม
    9. Calculus: การคำนวณ output โดยใช้ input และ functions
    10. Falsifiability: falsifiable หมายถึง สามารถพิสูจน์ว่าเป็น/ไม่เป็นจริงได้ และแนวคิดเป็นแก่นหลักของวิทยาศาสตร์ ทฤษฎีใดที่ไม่สามารถ falsify ได้เป็นทฤษฎีที่ไม่ควรยึดถือ เพราะเราพิสูจน์ไม่ได้ว่าเป็นจริง/ไม่เป็นจริง
    11. If you can’t decide, then the answer is no: ถ้าเราตัดสินใจไม่ได้ (เช่น จะไปเรียนต่อไหม) คำตอบคือไม่ เพราะในปัจจุบัน เรามีตัวเลือกมากมาย และเราควร say “yes” ก็ต่อเมื่อเรามั่นใจในตัวเลือกจริง ๆ แล้วเท่านั้น
    12. Run uphill: ถ้าเรารู้สึก 50-50 กับการตัดสินใจยาก ๆ ให้เราเลือกทางที่ยากกว่า เพราะทางที่ยากในระยะสั้นมักให้ผลดีในระยะยาว เหมือนกับการวิ่ง เราจะเหนื่อยในระหว่างวิ่ง แต่สุดท้ายเราจะมีสุขภาพที่ดีในระยะยาว

    📖 Read

    Read a lot—just read.

    — Naval Ravikant

    แนวทางสุดท้ายในการพัฒนา judgment คือ การอ่าน

    การอ่านคือ superpower ซึ่งเราสามารถพัฒนาได้

    สำหรับคนที่ต้องการฝึกทักษะการอ่าน Naval แนะนำให้เริ่มจากการอ่านสิ่งที่ชอบจนกว่าเราจะรักในการอ่าน

    Read what you love until you love to read.

    — Naval Ravikant

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

    .

    🔖 What & How to Read

    The problem with saying “just read” is there is so much junk out there.

    — Naval Ravikant

    Naval มีเทคนิคในการอ่านเพื่อสร้างความรู้ 5 ข้อ ได้แก่:

    1. Basic knowledge: อ่านหนังสือที่มีความรู้พื้นฐาน เช่น คณิตศาสตร์ วิทยาศาสตร์ และปรัชญา
    2. Classic work: อ่านหนังสือต้นฉบับหรือหนังสือ classic เช่น ถ้าเราต้องการอ่านเกี่ยวกับ evolution เราควรอ่านงานของ Charles Darwin ก่อน แล้วค่อยอ่านหนังสือของคนอื่นที่เขียนต่อยอดจาก Charles Darwin เป็นต้น
    3. No obligation to finish a book: เราอ่านเพื่อทำความเข้าใจไอเดียพื้นฐานของหนังสือ เราไม่จำเป็นต้องอ่านหนังสือให้จบทั้งเล่ม ถ้าเรารู้สึกว่าเข้าใจไอเดียพื้นฐานในหนังสือแล้ว เราสามารถข้ามไปเล่มถัดไปได้ และกลับมาดูหนังสือเล่มเก่าอีกครั้งเมื่อต้องการทบทวนความรู้
    4. You are what you read: เลือกหนังสือที่อ่านให้ดี เพราะหนังสือจะเหมือนเนื้อเพลงที่เล่นวนอยู่ในหัวเรา เราจะกลายเป็นสิ่งที่เราอ่าน
    5. Read to teach: อ่านโดยมีความตั้งใจว่าจะอธิบายให้คนอื่นฟัง การทำเช่นนี้จะทำให้เราเข้าใจสิ่งที่อ่านมากขึ้น

    🌻 Summary

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

    แนวทางในการพัฒนา judgment มีอยู่ 3 แนวทาง ได้แก่:

    1. Think clearly: คิดโดยตั้งอยู่บนพื้นฐานของความเป็นจริง โดยเราต้องมี (1) ความรู้พื้นฐาน และ (2) การตัดสินใจโดยไม่ใช้ identity/ego
    2. Mental models: สะสมแนวคิดในการตัดสินใจ เช่น evolution, inversion, complexity theory
    3. Read: อ่านให้เยอะเพื่อสะสมความรู้พื้นฐานและหลีกเลี่ยงหนังสือที่ไม่ดี

    🔥 Get The Almanack of Naval Ravikant

    สำหรับคนที่สนใจเนื้อหาของหนังสือและอยากอ่านเพิ่มเติม สามารถซื้อหนังสือได้ตาม link ด้านล่าง:

    Note: ใครที่สนใจอ่านต้นฉบับภาษาอังกฤษแบบ e-book หรือ PDF สามารถดาวน์โหลดฟรีได้ที่ navalmanack.com

  • 4 วิธีการใช้ getSymbols() เพื่อโหลดข้อมูลการเงินในภาษา R — ตัวอย่างการโหลดข้อมูลหุ้น Apple

    4 วิธีการใช้ getSymbols() เพื่อโหลดข้อมูลการเงินในภาษา R — ตัวอย่างการโหลดข้อมูลหุ้น Apple

    ในบทความนี้ เราจะมาทำความรู้จักกับ getSymbols() จาก quantmod package ซึ่งใช้โหลดข้อมูลทางการเงิน เช่น ข้อมูลหุ้น และข้อมูลทางเศรษฐกิจ กัน

    โดยเราจะไปดู 4 วิธีการใช้งาน ได้แก่:

    1. Basics: การใช้งาน getSymbols() เบื้องต้น
    2. Advanced: การใช้งานขั้นสูง
    3. View columns: การดู column ข้อมูล
    4. Visualise data: การสร้างกราฟข้อมูล

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 💻 Install & Import
    2. 1️⃣ Basics: 5 Parametres to Know
      1. 💲 Symbols
      2. 🏦 src
      3. 🏧 auto.assign
      4. 🌲 env
      5. 📆 from, to
    3. 2️⃣ Advanced: Set Defaults
      1. 🌍 getDefaults(), setDefaults()
      2. 💹 setSymbolLookup(), getSymbolLookup()
      3. 💾 saveSymbolLookup(), loadSymbolLookup()
    4. 3️⃣ View Columns
    5. 4️⃣ Visualise Data
    6. 💪 Summary
    7. 😺 GitHub
    8. 📃 References
    9. ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    💻 Install & Import

    ในการใช้งาน getSymbols() เราจะต้องเริ่มจากการติดตั้งและโหลด quantmod package ก่อน แบบนี้:

    # Install the packages
    install.packages("quantmod")
    
    # Load the packages
    library(quantmod)
    

    1️⃣ Basics: 5 Parametres to Know

    ในการใช้งานพื้นฐาน getSymbols() มี 5 parametres หลักที่เราควรรู้ ได้แก่:

    1. Symbols: ตัวย่อชื่อข้อมูล
    2. src: แหล่งข้อมูล
    3. auto.assign: ให้โหลด (TRUE) หรือแสดงข้อมูล (FALSE)
    4. env: environment สำหรับโหลดข้อมูล
    5. from และ to: ช่วงเวลาของข้อมูล

    เราไปดูวิธีใช้งานแต่ละ parametre กัน

    .

    💲 Symbols

    ในขั้นแรกของการโหลดข้อมูลการเงินด้วย getSymbols() ให้เราระบุชื่อข้อมูลที่เราต้องการ เช่น:

    ข้อมูลชื่อข้อมูล
    AppleAAPL
    GoogleGOOG
    MicrosoftMSFT
    NVIDIANVDA

    ในบทความนี้ เราจะลองโหลดข้อมูลหุ้น Apple กัน ซึ่งเราสามารถกำหนด Symbols ได้แบบนี้:

    # Import Apple data
    getSymbols("AAPL")
    

    เมื่อรันแล้ว เราจะได้ตัวแปรประเภท xts (time series object) ชื่อ AAPL มา ซึ่งเราดูข้อมูลในตัวแปรนี้ได้ด้วย head():

    # Print result
    head(AAPL)
    

    ผลลัพธ์:

               AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
    2007-01-03  3.081786  3.092143 2.925000   2.992857  1238319600      2.518541
    2007-01-04  3.001786  3.069643 2.993571   3.059286   847260400      2.574443
    2007-01-05  3.063214  3.078571 3.014286   3.037500   834741600      2.556108
    2007-01-08  3.070000  3.090357 3.045714   3.052500   797106800      2.568732
    2007-01-09  3.087500  3.320714 3.041071   3.306071  3349298400      2.782115
    2007-01-10  3.383929  3.492857 3.337500   3.464286  2952880000      2.915257
    

    จะเห็นได้ว่า นอกจากวันที่แล้ว ข้อมูลเรายังประกอบไปด้วย 6 columns ดังนี้:

    1. Open: ราคาเปิด
    2. High: ราคาสูงสุด
    3. Low: ราคาต่ำสุด
    4. Close: ราคาปิด
    5. Volume: ปริมาณการซื้อขาย
    6. Adjusted: ราคาปรับปรุง

    ในกรณีที่เราต้องการโหลดข้อมูลหุ้นหลายตัวพร้อมกัน เราสามารถใช้ character vector ช่วยได้แบบนี้:

    # Load multiple instruments
    getSymbols(c("AAPL", "GOOGL", "MSFT", "NVDA"))
    

    .

    🏦 src

    src ใช้กำหนดแหล่งข้อมูลที่ getSymbols() จะไปดึงข้อมูลมา

    โดย default, src ถูกตั้งไว้ให้ดึงข้อมูลจาก Yahoo! Finance ("yahoo")

    แสดงว่า เราสามารถเขียน code เพื่อดึงข้อมูล Apple จาก Yahoo! Finance ได้ทั้งแบบนี้:

    # Import Apple data
    getSymbols("AAPL")
    

    และแบบนี้:

    # Import Apple data
    getSymbols("AAPL", src = "yahoo")
    

    ทั้งนี้ getSymbols() มีแหล่งข้อมูลอื่น ๆ ให้เราเลือกใช้งานได้ เช่น:

    • Federal Reserve Economic Data ("FRED")
    • Oanda ("oanda")

    นอกจากแหล่งข้อมูลออนไลน์แล้ว เรายังสามารถโหลดข้อมูลแบบออฟไลน์ได้ เช่น:

    • CSV ("csv")
    • RData ("RData")

    ยกตัวอย่างเช่น โหลดข้อมูล Apple จาก CSV:

    # Load csv data
    getSymbols("AAPL", src = "csv")
    

    Note: การโหลดข้อมูล CSV ด้วย getSymbols() มีเงื่อนไข 4 อย่าง ได้แก่:

    1. มีชื่อไฟล์เป็นชื่อหุ้น (เช่น AAPL.csv)
    2. มี header
    3. Column แรกจะต้องเป็น datetime (เช่น 2025-05-25)
    4. Column ที่เหลือควรมีชื่อและข้อมูลดังนี้:
      1. Open: ข้อมูลราคาเปิด
      2. High: ข้อมูลราคาสูงสุด
      3. Low: ข้อมูลราคาต่ำสุด
      4. Close: ข้อมูลราคาปิด
      5. Volume: ข้อมูลปริมาณการซื้อขาย
      6. Adjusted: ข้อมูลราคาปรับปรุง

    .

    🏧 auto.assign

    auto.assign ใช้กำหนดว่า getSymbols() จะโหลดข้อมูลมาไว้ใน global environment หรือแสดงข้อมูลที่โหลดมาได้

    โดย default, auto.assign เป็น TRUE ซึ่งทำให้เราได้ตัวแปรที่เก็บข้อมูลการเงินมาไว้ใน global environment ของเรา โดยไม่ต้องกำหนดตัวแปรเอง

    ทั้งนี้ ในกรณีที่เราต้องการกำหนดตัวแปรเอง ให้เราเปลี่ยน auto.assign เป็น FALSE แบบนี้:

    # Set auto.assign to FALSE to assign to custom variable
    apple_data <- getSymbols("AAPL", auto.assign = FALSE)
    

    ถ้าเรากำหนดให้ auto.assign = FALSE โดยไม่จัดเก็บไว้ในตัวแปร getSymbols() จะแสดงข้อมูลใน console ของเรา:

    # Set auto.assign to FALSE without variable assignment
    getSymbols("AAPL", auto.assign = FALSE)
    

    ผลลัพธ์:

                AAPL.Open  AAPL.High   AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
    2007-01-03   3.081786   3.092143   2.925000   2.992857  1238319600      2.518541
    2007-01-04   3.001786   3.069643   2.993571   3.059286   847260400      2.574442
    2007-01-05   3.063214   3.078571   3.014286   3.037500   834741600      2.556108
    2007-01-08   3.070000   3.090357   3.045714   3.052500   797106800      2.568732
    2007-01-09   3.087500   3.320714   3.041071   3.306071  3349298400      2.782115
    2007-01-10   3.383929   3.492857   3.337500   3.464286  2952880000      2.915257
    2007-01-11   3.426429   3.456429   3.396429   3.421429  1440252800      2.879192
    2007-01-12   3.378214   3.395000   3.329643   3.379286  1312690400      2.843727
    2007-01-16   3.417143   3.473214   3.408929   3.467857  1244076400      2.918262
    2007-01-17   3.484286   3.485714   3.386429   3.391071  1646260000      2.853645
           ...                                                                      
    2025-06-05 203.500000 204.750000 200.149994 200.630005    55126100    200.630005
    2025-06-06 203.000000 205.699997 202.050003 203.919998    46607700    203.919998
    2025-06-09 204.389999 206.000000 200.020004 201.449997    72862600    201.449997
    2025-06-10 200.600006 204.350006 200.570007 202.669998    54672600    202.669998
    2025-06-11 203.500000 204.500000 198.410004 198.779999    60989900    198.779999
    2025-06-12 199.080002 199.679993 197.360001 199.199997    43904600    199.199997
    2025-06-13 199.729996 200.369995 195.699997 196.449997    51447300    196.449997
    2025-06-16 197.300003 198.690002 196.559998 198.419998    43020700    198.419998
    2025-06-17 197.199997 198.389999 195.210007 195.639999    38856200    195.639999
    2025-06-18 195.940002 197.570007 195.070007 196.580002    45350400    196.580002
    

    .

    🌲 env

    env ใช้กำหนด environment ที่ใช้เก็บข้อมูล ซึ่งโดย default, getSymbols() จะโหลดข้อมูลไว้ใน global environment

    ในการใช้ env กำหนด environment ที่ต้องการ เราจะต้องเริ่มจากสร้าง environment ขึ้นมาก่อนด้วย new.env():

    # Create a new environment
    my_env <- new.env()
    

    จากนั้น โหลดข้อมูลเข้าไปใน environment ใหม่:

    # Load data into the environment
    getSymbols("AAPL", env = my_env)
    

    เราสามารถดูตัวแปรที่เก็บไว้ใน environment ได้ด้วย ls():

    # List all variables in environment
    ls(envir = my_env)
    

    และดูข้อมูลได้ด้วย $ เช่น:

    # Show Apple data
    head(my_env$AAPL)
    

    ผลลัพธ์:

               AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
    2007-01-03  3.081786  3.092143 2.925000   2.992857  1238319600      2.518541
    2007-01-04  3.001786  3.069643 2.993571   3.059286   847260400      2.574442
    2007-01-05  3.063214  3.078571 3.014286   3.037500   834741600      2.556109
    2007-01-08  3.070000  3.090357 3.045714   3.052500   797106800      2.568732
    2007-01-09  3.087500  3.320714 3.041071   3.306071  3349298400      2.782115
    2007-01-10  3.383929  3.492857 3.337500   3.464286  2952880000      2.915256
    

    .

    📆 from, to

    from ใช้กำหนดวันแรกของข้อมูล และ to กำหนดวันสุดท้ายของข้อมูล

    ยกตัวอย่างเช่น เราต้องการโหลดข้อมูล Apple ในเดือนพฤษภาคม 2025:

    # Load data for May 2025
    apple_data_2025_05 = getSymbols("AAPL",
                                    auto.assign = FALSE,
                                    from = "2025-05-01",
                                    to = "2025-05-31")
    
    # Print results
    print("First three records:")
    head(apple_data_2025_05, n = 3)
    print("------------------------------------------------------------------------------")
    print("Last three records:")
    tail(apple_data_2025_05, n = 3)
    

    ผลลัพธ์:

    First three records:
               AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
    2025-05-01    209.08    214.56   208.90     213.32    57365700      213.0406
    2025-05-02    206.09    206.99   202.16     205.35   101010600      205.0811
    2025-05-05    203.10    204.10   198.21     198.89    69018500      198.6295
    ------------------------------------------------------------------------------
    Last three records:
               AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
    2025-05-28    200.59    202.73   199.90     200.42    45339700        200.42
    2025-05-29    203.58    203.81   198.51     199.95    51396800        199.95
    2025-05-30    199.37    201.96   196.78     200.85    70819900        200.85
    

    Note: ตลาดหุ้นวันสุดท้ายของเดือนพฤษภาคม 2025 คือ 30 พฤษภาคม ทำให้ข้อมูลสิ้นสุด ณ วันที่ 30


    2️⃣ Advanced: Set Defaults

    จะเห็นว่า getSymbols() การตั้งค่าที่หลากหลาย

    ทั้งนี้ quantmod มี 6 functions ที่ใช้ร่วมกับ getSymbols() เพื่อช่วยลดขั้นตอนในการตั้งค่าต่าง ๆ ได้แก่:

    1. getDefaults() และ setDefaults()
    2. getSymbolLookup() และ setSymbolLookup()
    3. saveSymbolLookup() และ loadSymbolLookup()

    เราไปดูวิธีการใช้งานทั้ง 6 functions กัน

    .

    🌍 getDefaults(), setDefaults()

    getDefaults() ใช้สำหรับดูค่า default ของ getSymbols()

    ส่วน setDefaults() ใช้สำหรับกำหนดค่า default

    ยกตัวอย่างเช่น เราต้องการกำหนด:

    • src จาก "yahoo" เป็น "FRED"
    • auto.assign จาก TRUE เป็น FALSE

    เราสามารถทำได้แบบนี้:

    # Get defaults before changing
    print("Defaults (before):")
    getDefaults(getSymbols)
    
    # Set defaults
    setDefaults(getSymbols,
                src = "FRED",
                auto.assign = FALSE)
     
    # Get defaults after changing
    print("Defaults (after):")
    getDefaults(getSymbols)
    

    ผลลัพธ์:

    Defaults (before):
    NULL
    
    Defaults (after):
    $src
    [1] "'FRED'"
    
    $auto.assign
    [1] FALSE
    

    ตอนนี้ ถ้าเราเรียกใช้ getSymbols() โดยไม่กำหนด src และ auto.assign ทั้งสอง arguments นี้จะเป็น "FRED" และ FALSE ตามลำดับ

    ถ้าเราต้องการ reset ค่า default ให้เราใส่ NULL ใน setDefaults():

    # Reset defaults
    setDefaults(getSymbols,
                src = NULL,
                auto.assign = NULL)
    
    # Check defaults after resetting
    print("Defaults (reset):")
    getDefaults(getSymbols)
    

    ผลลัพธ์:

    Defaults (reset):
    NULL
    

    .

    💹 setSymbolLookup(), getSymbolLookup()

    getSymbolLookup() และ setSymbolLookup() ทำงานเหมือนกับ getDefaults() และ setDefaults() แต่เป็นการตั้งค่า default สำหรับข้อมูลแต่ละตัว (แทนระดับ global) ภายใน session เท่านั้น

    ยกตัวอย่างเช่น เราต้องการกำหนดให้ดึงข้อมูลหุ้น Google มาจาก Google Finance:

    # Set default for Google
    setSymbolLookup(GOOG = list(src = "google"))
    
    # Get new defaults
    getSymbolLookup()
    

    ผลลัพธ์:

    $GOOG
    $GOOG$src
    [1] "google"
    

    Note: Google Finance หยุดให้ข้อมูลกับ quantmod เมื่อปี 2018 ทำให้ตอนนี้ เราไม่สามารถใช้ src = "google" ได้อีก

    เราสามารถ reset ค่า default ได้โดยใส่ NULL เหมือนเดิม:

    # Reset defaults
    setSymbolLookup(NULL)
    
    # Get defaults after resetting
    getSymbolLookup()
    

    ผลลัพธ์:

    named list()
    

    .

    💾 saveSymbolLookup(), loadSymbolLookup()

    ค่าที่เราใช้ setSymbolLookup() กำหนดจะถูก reset ทุกครั้งที่เราปิด session ไป

    ถ้าเราต้องการเก็บค่าเพื่อไปใช้ใน session อื่น เราสามารถใช้ saveSymbolLookup() และ loadSymbolLookup() ช่วยได้:

    • saveSymbolLookup() บันทึกค่าเก็บไว้ในไฟล์ RDS
    • loadSymbolLookup() โหลดค่าที่เก็บไว้ใน RDS

    ตัวอย่าง code:

    # Save defaults
    saveSymbolLookup(file = "symbols.rds")
    
    # Load defaults
    loadSymbolLookup(file = "symbols.rds")
    

    3️⃣ View Columns

    หลังจากเราโหลดข้อมูลมาแล้ว เราสามารถดูข้อมูลแต่ละ column ได้ด้วย 7 functions หลัก ดังนี้:

    No.FunctionFor
    1Op()ราคาเปิด
    2Hi()ราคาสูงสุด
    3Lo()ราคาต่ำสุด
    4Cl()ราคาปิด
    5Ad()ราคาปรับปรุง
    6Vo()ปริมาณการซื้อขาย
    7OHLC()ราคาเปิด, สูงสุด, ต่ำสุด, และราคาปิด

    ตัวอย่างเช่น ดูราคาเปิด:

    # Get opening price
    Op(AAPL)
    

    ผลลัพธ์:

                AAPL.Open
    2007-01-03   3.081786
    2007-01-04   3.001786
    2007-01-05   3.063214
    2007-01-08   3.070000
    2007-01-09   3.087500
    2007-01-10   3.383929
    2007-01-11   3.426429
    2007-01-12   3.378214
    2007-01-16   3.417143
    2007-01-17   3.484286
           ...           
    2025-06-05 203.500000
    2025-06-06 203.000000
    2025-06-09 204.389999
    2025-06-10 200.600006
    2025-06-11 203.500000
    2025-06-12 199.080002
    2025-06-13 199.729996
    2025-06-16 197.300003
    2025-06-17 197.199997
    2025-06-18 195.940002
    

    ดูราคาสูงสุด:

    # Get highest price
    Hi(AAPL)
    

    ผลลัพธ์:

                AAPL.High
    2007-01-03   3.092143
    2007-01-04   3.069643
    2007-01-05   3.078571
    2007-01-08   3.090357
    2007-01-09   3.320714
    2007-01-10   3.492857
    2007-01-11   3.456429
    2007-01-12   3.395000
    2007-01-16   3.473214
    2007-01-17   3.485714
           ...           
    2025-06-05 204.750000
    2025-06-06 205.699997
    2025-06-09 206.000000
    2025-06-10 204.350006
    2025-06-11 204.500000
    2025-06-12 199.679993
    2025-06-13 200.369995
    2025-06-16 198.690002
    2025-06-17 198.389999
    2025-06-18 197.570007
    

    ดูราคาต่ำสุด:

    # Get lowest price
    Lo(AAPL)
    

    ผลลัพธ์:

                 AAPL.Low
    2007-01-03   2.925000
    2007-01-04   2.993571
    2007-01-05   3.014286
    2007-01-08   3.045714
    2007-01-09   3.041071
    2007-01-10   3.337500
    2007-01-11   3.396429
    2007-01-12   3.329643
    2007-01-16   3.408929
    2007-01-17   3.386429
           ...           
    2025-06-05 200.149994
    2025-06-06 202.050003
    2025-06-09 200.020004
    2025-06-10 200.570007
    2025-06-11 198.410004
    2025-06-12 197.360001
    2025-06-13 195.699997
    2025-06-16 196.559998
    2025-06-17 195.210007
    2025-06-18 195.070007
    

    ดูราคาปิด:

    # Get closing price
    Cl(AAPL)
    

    ผลลัพธ์:

               AAPL.Close
    2007-01-03   2.992857
    2007-01-04   3.059286
    2007-01-05   3.037500
    2007-01-08   3.052500
    2007-01-09   3.306071
    2007-01-10   3.464286
    2007-01-11   3.421429
    2007-01-12   3.379286
    2007-01-16   3.467857
    2007-01-17   3.391071
           ...           
    2025-06-05 200.630005
    2025-06-06 203.919998
    2025-06-09 201.449997
    2025-06-10 202.669998
    2025-06-11 198.779999
    2025-06-12 199.199997
    2025-06-13 196.449997
    2025-06-16 198.419998
    2025-06-17 195.639999
    2025-06-18 196.580002
    

    ดูราคาปรับปรุง:

    # Get adjusted price
    Ad(AAPL)
    

    ผลลัพธ์:

               AAPL.Adjusted
    2007-01-03      2.518541
    2007-01-04      2.574442
    2007-01-05      2.556109
    2007-01-08      2.568732
    2007-01-09      2.782116
    2007-01-10      2.915256
    2007-01-11      2.879192
    2007-01-12      2.843727
    2007-01-16      2.918261
    2007-01-17      2.853645
           ...              
    2025-06-05    200.630005
    2025-06-06    203.919998
    2025-06-09    201.449997
    2025-06-10    202.669998
    2025-06-11    198.779999
    2025-06-12    199.199997
    2025-06-13    196.449997
    2025-06-16    198.419998
    2025-06-17    195.639999
    2025-06-18    196.580002
    

    ดูปริมาณการซื้อขาย:

    # Get volume
    Vo(AAPL)
    

    ผลลัพธ์:

               AAPL.Volume
    2007-01-03  1238319600
    2007-01-04   847260400
    2007-01-05   834741600
    2007-01-08   797106800
    2007-01-09  3349298400
    2007-01-10  2952880000
    2007-01-11  1440252800
    2007-01-12  1312690400
    2007-01-16  1244076400
    2007-01-17  1646260000
           ...            
    2025-06-05    55126100
    2025-06-06    46607700
    2025-06-09    72862600
    2025-06-10    54672600
    2025-06-11    60989900
    2025-06-12    43904600
    2025-06-13    51447300
    2025-06-16    43020700
    2025-06-17    38856200
    2025-06-18    45350400
    

    ดูราคาเปิด, สูงสุด, ต่ำสุด, และราคาปิด:

    # Get all price
    OHLC(AAPL)
    

    ผลลัพธ์:

                AAPL.Open  AAPL.High   AAPL.Low AAPL.Close
    2007-01-03   3.081786   3.092143   2.925000   2.992857
    2007-01-04   3.001786   3.069643   2.993571   3.059286
    2007-01-05   3.063214   3.078571   3.014286   3.037500
    2007-01-08   3.070000   3.090357   3.045714   3.052500
    2007-01-09   3.087500   3.320714   3.041071   3.306071
    2007-01-10   3.383929   3.492857   3.337500   3.464286
    2007-01-11   3.426429   3.456429   3.396429   3.421429
    2007-01-12   3.378214   3.395000   3.329643   3.379286
    2007-01-16   3.417143   3.473214   3.408929   3.467857
    2007-01-17   3.484286   3.485714   3.386429   3.391071
           ...                                            
    2025-06-05 203.500000 204.750000 200.149994 200.630005
    2025-06-06 203.000000 205.699997 202.050003 203.919998
    2025-06-09 204.389999 206.000000 200.020004 201.449997
    2025-06-10 200.600006 204.350006 200.570007 202.669998
    2025-06-11 203.500000 204.500000 198.410004 198.779999
    2025-06-12 199.080002 199.679993 197.360001 199.199997
    2025-06-13 199.729996 200.369995 195.699997 196.449997
    2025-06-16 197.300003 198.690002 196.559998 198.419998
    2025-06-17 197.199997 198.389999 195.210007 195.639999
    2025-06-18 195.940002 197.570007 195.070007 196.580002
    

    4️⃣ Visualise Data

    สุดท้าย เราสามารถสร้างกราฟเพื่อสำรวจข้อมูล โดยใช้ 2 functions ได้แก่:

    1. autoplot() จาก ggplot2 package
    2. chartSeries() จาก quantmod package

    ยกตัวอย่างเช่น สำรวจราคาปิดของ Apple:

    # Import ggplots
    library(ggplot2)
    
    # Visualise with autoplot()
    autoplot(Cl(AAPL),
             ts.colour = "darkgreen") +
    
      # Add text
      labs(title = "AAPL Closing Price (Jan 2007 – Jun 2025)",
           x = "Time",
           y = "Price (USD)")
    

    ผลลัพธ์:

    # Visualise with chartSeries()
    chartSeries(Cl(AAPL))
    

    ผลลัพธ์:


    💪 Summary

    ในบทความนี้ เราได้ดูวิธีการทำงานกับ getSymbols() เพื่อโหลดข้อมูลจากการเงินจากแหล่งต่าง ๆ กัน

    ตอนนี้ เรารู้จักกับ 5 parametres หลักของ getSymbols():

    1. Symbols
    2. src
    3. auto.assign
    4. env
    5. from และ to

    วิธีตั้งค่า default ด้วย 3 คู่ functions:

    1. getDefaults() และ setDefaults()
    2. getSymbolLookup() และ setSymbolLookup()
    3. saveSymbolLookup() และ loadSymbolLookup()

    วิธีดูข้อมูลด้วย 7 functions:

    1. Op()
    2. Hi()
    3. Lo()
    4. Cl()
    5. Ad()
    6. Vo()
    7. OHLC()

    และสุดท้าย วิธีสร้างกราฟด้วย 2 functions:

    1. autoplot()
    2. chartSeries()

    😺 GitHub

    ดู code ทั้งหมดในบทความนี้ได้ที่ GitHub


    📃 References


    ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

    📕 ขอฝากหนังสือเล่มแรกในชีวิตด้วยนะครับ 😆

    🙋 ใครที่กำลังเรียนจิตวิทยาหรือทำงานสายจิตวิทยา และเบื่อที่ต้องใช้ software ราคาแพงอย่าง SPSS และ Excel เพื่อทำข้อมูล

    💪 ผมขอแนะนำ R Book for Psychologists หนังสือสอนใช้ภาษา R เพื่อการวิเคราะห์ข้อมูลทางจิตวิทยา ที่เขียนมาเพื่อนักจิตวิทยาที่ไม่เคยมีประสบการณ์เขียน code มาก่อน

    ในหนังสือ เราจะปูพื้นฐานภาษา R และพาไปดูวิธีวิเคราะห์สถิติที่ใช้บ่อยกัน เช่น:

    • Correlation
    • t-tests
    • ANOVA
    • Reliability
    • Factor analysis

    🚀 เมื่ออ่านและทำตามตัวอย่างใน R Book for Psychologists ทุกคนจะไม่ต้องพึง SPSS และ Excel ในการทำงานอีกต่อไป และสามารถวิเคราะห์ข้อมูลด้วยตัวเองได้ด้วยความมั่นใจ

    แล้วทุกคนจะแปลกใจว่า ทำไมภาษา R ง่ายขนาดนี้ 🙂‍↕️

    👉 สนใจดูรายละเอียดหนังสือได้ที่ meb:

  • Building Wealth: สรุป 5 กลุ่มแนวคิดในการสร้างความมั่งคั่ง (Wealth) อย่างยั่งยืน จากหนังสือ The Almanack of Naval Ravikant โดย Eric Jorgenson — What Is Wealth, How to Build Wealth, What to Build Wealth With, Why Seek Wealth, และข้อคิดอื่น ๆ

    Building Wealth: สรุป 5 กลุ่มแนวคิดในการสร้างความมั่งคั่ง (Wealth) อย่างยั่งยืน จากหนังสือ The Almanack of Naval Ravikant โดย Eric Jorgenson — What Is Wealth, How to Build Wealth, What to Build Wealth With, Why Seek Wealth, และข้อคิดอื่น ๆ

    Naval Ravikant เป็นนักลงทุนชาวอเมริกันที่ประสบความสำเร็จจากการลงทุนในบริษัทอย่าง Uber, Foursquare, และ Twitter (X) และเป็น CEO ของ AngelList บริษัทที่เชื่อม startup กับ angel investor

    หนังสือ The Almanack of Naval Ravikant โดย Eric Jorgenson รวบรวมข้อคิดเกี่ยวกับความมั่งคั่ง (wealth) และความสุข (happiness) ผ่านการสัมภาษณ์และ tweet ของ Naval

    ในบทความนี้ เราจะมาสรุปเนื้อหา Building Wealth ซึ่งเป็นบทแรกจาก 5 บทในหนังสือ และพูดถึงเรื่องการสร้างความมั่งคั่งอย่างยั่งยืน

    บทความนี้แบ่งออกเป็น 5 ส่วน ได้แก่:

    1. Intro to wealth
    2. How to build wealth right
    3. What to build wealth with
    4. Why seek wealth?
    5. Additional tips on life of wealth

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    หน้าปกหนังสือ The Almanack of Naval Ravikant บน Amazon

    1. 🏦 1. Intro to Wealth
    2. 😎 2. How to Build Wealth Right
      1. 🎁 2.1 Productise Yourself
      2. 🧠 2.2 Earn With Mind, Not Time
      3. 🎲 2.3 Luck
    3. 🏗️ 3. What to Build Wealth With
      1. ⚡ 3.1 Specific Knowledge
      2. 🧰 3.2 Leverage
      3. 🫡 3.3 Accountability
      4. 🏪 3.4 Equity
      5. 🪙 3.5 Compound Interest
    4. 🕊️ 4. Why Seek Wealth?
    5. 💡 5. Additional Tips on Life of Wealth
      1. ⌚ 5.1 Value Your Time
      2. 🚨 5.2 Avoid Ruin
      3. 🏆 5.3 Early Success
    6. 💰 Summary
    7. 🔥 Get The Almanack of Naval Ravikant

    🏦 1. Intro to Wealth

    Seek wealth, not money or status.

    — Naval Ravikant

    เราควรมองหา wealth ไม่ใช่ money หรือ status

    • Wealth = asset ที่สร้างรายได้ให้เราในขณะที่กำลังหลับ
    • Money = สื่อที่เราใช้เคลื่อนย้าย wealth
    • Status = สถานะทางสังคมที่บอกว่า เราอยู่สูงหรือต่ำขนาดไหน

    Why not money?

    Money สร้างความสุขให้เราไม่ได้ สิ่งเดียวที่ money แก้ได้ คือ ช่วยจัดการอุปสรรคที่ขัดขวางเส้นทางสู่ความสุขของเรา

    Money ทำให้เรามีกินมีใช้และสามารถใช้จ่ายในสิ่งที่เราต้องการได้ แต่สิ่งเหล่านี้ไม่ได้ใช่ความสุขที่เราตามหา

    Why not status?

    การต่อสู้เพื่อ status (อย่างการเล่นการเมือง) เป็น zero-sum game นั่นคือ ต้องมีฝ่ายแพ้และฝ่ายชนะ (-1, +1) ทำให้ในภาพรวม ไม่มีอะไรที่เปลี่ยนแปลงไปในทางที่ดีขึ้น

    ความสัมพันธ์ที่ดีควรเป็น win-win ที่ทุกฝ่ายได้ผลประโยชน์ร่วมกันในระยะยาว

    Why wealth?

    Wealth สามารถสร้างรายได้ให้เราได้ในระยะยาว เพราะ wealth สามารถทำรายได้ให้กับเราแม้ในขณะที่เรากำลังหลับ

    เราควรมองหา wealth เช่น โรงงาน ธุรกิจ หนังสือ โค้ด มากกว่า money และ status


    😎 2. How to Build Wealth Right

    แนวทางการสร้าง wealth อย่างยั่งยืนมีอยู่ 3 ข้อ ได้แก่:

    1. Productise yourself
    2. Earn with mind, not time
    3. Luck

    .

    🎁 2.1 Productise Yourself

    Productize Yourself

    — Naval Ravikant

    Productise yourself หมายถึง การพัฒนาตัวให้เป็น product ที่เป็นที่ต้องการของสังคม

    เราจะ productise ตัวเองได้สำเร็จเมื่อเราสามารถสร้างสิ่งที่:

    1. มีเอกลักษณ์เฉพาะตัว (unique/authentic)
    2. เป็นสิ่งที่สังคมต้องการ แต่ไม่รู้จะหามาได้ยังไง (เพราะถ้าหาได้ สังคมจะไม่ต้องการเรา)

    เมื่อเราสามารถทำ 2 อย่างนี้ได้ สังคมก็จะตอบแทนเรา (ด้วยเงิน)

    .

    🧠 2.2 Earn With Mind, Not Time

    Earn with your mind, not your time.

    — Naval Ravikant

    เราควรหารายได้ด้วยความคิด (mind) ไม่ใช่เวลา (time)

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

    การผูกรายได้กับเวลา หมายถึง เราจะต้องใช้เวลาแลกกับรายได้ และเราจะไม่มีรายได้ถ้าเราไม่มีเวลา

    เช่น เราจะได้เงินเดือนก็ต่อเมื่อเราทำงานครบ 1 เดือน และถ้าเดือนนั้นเราขาดงาน รายได้ของเราก็จะหายไป 1 เดือน

    Time -> Money
    Time -> Money

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

    Time Mind -> Money

    ในขณะที่เวลามีอยู่อย่างจำกัด ความคิดของเราไม่มีที่สิ้นสุด และเราสามารถพัฒนาความคิดของเราให้ดีขึ้นเรื่อย ๆ ได้ ซึ่งทำให้เราสามารถหารายได้มากขึ้นเรื่อย ๆ ได้

    เมื่อเราหารายได้ด้วยความคิด ไม่ใช่เวลา รายได้ของเราจะไม่ถูกจำกัดอีกต่อไป

    Earn with your mind, not your time (source: The Almanack of Naval Ravikant)

    .

    🎲 2.3 Luck

    You put yourself in a position to capitalize on luck or to attract luck when nobody else created the opportunity for themselves.

    — Naval Ravikant

    Luck เป็นสิ่งที่เราควบคุมไม่ได้ และถ้าเราอยากสร้าง wealth อย่างมั่นคง เราควรตัด luck ออกจากสมการของเรา

    Naval มองว่า luck มีอยู่ 4 ประเภท:

    1. Blind luck: luck ที่เกิดขึ้นโดยความบังเอิญ เช่น ถูกหวย
    2. Luck from persistence: luck ที่เกิดจากความเพียร เราจะพบ luck ประเภทนี้ได้เมื่อเราทำงานหนักหรือใส่ความพยายามไปกับสิ่งใดสิ่งหนึ่งเป็นเวลานาน
    3. Luck from spotting: luck ที่เกิดจากการที่เราพัฒนาทักษะในการสังเกตเห็นโอกาสต่าง ๆ ในชีวิต ทำให้เราพบเจอ luck ได้มากกว่าคนอื่น
    4. Luck that finds you: luck ที่เข้ามาหาเราเองเพราะเราพัฒนาตัวเองให้เป็นที่ต้องการของสังคม (productise yourself)

    Luck ประเภทสุดท้ายเป็น luck ที่คาดเดาได้มากที่สุด เพราะเป็น luck ที่เกิดจากตัวเองเรา

    ถ้าเราอยากสร้าง wealth เราควรตัด luck ออกจากสมการโดยการพัฒนาตัวเองจน luck วิ่งเข้ามาหาเราเอง


    🏗️ 3. What to Build Wealth With

    สิ่งที่เราควรมีเพื่อสร้าง wealth อย่างยั่งยืนมีอยู่ 5 อย่าง ได้แก่:

    1. Specific knowledge
    2. Leverage
    3. Accountability
    4. Equity
    5. Compound interest

    .

    ⚡ 3.1 Specific Knowledge

    No one can compete with you on being you.

    — Naval Ravikant

    Specific knowledge คือ ความรู้/ความสามารถเฉพาะตัว

    Specific knowledge เป็นสิ่งที่ทำให้เราแตกต่างจากคนอื่น และทำให้เราสามารถสร้างสิ่งที่สังคมต้องการแต่ยังไม่รู้ว่าจะหามาได้ยังไง เพราะสิ่งนั้นมีแต่เราที่รู้/ทำได้

    Specific knowledge เกิดมาจาก 3 ส่วน ได้แก่:

    1. Innate trait: ลักษณะที่ติดตัวเรามาตั้งแต่เกิด
    2. Passion: ความชอบ/ความหลงใหล
    3. Experience: ประสบการณ์ชีวิต

    What’s your specific knowledge?

    แต่ละคนมี specific knowledge ที่ไม่เหมือนใคร เราสามารถสังเกต specific knowledge ของเราได้โดยมองหาสิ่งที่:

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

    ยกตัวอย่าง เช่น:

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

    How to develop your specific knowledge?

    เราสามารถพัฒนา specific knowledge ได้โดยทำตาม passion มากกว่าการทำตาม trend

    ยกตัวอย่างเช่น ถ้าเราชอบเล่นดนตรี เราควรฝึกเล่นดนตรี แทนที่จะเรียน machine learning ในยุคของ AI (เว้นว่า เราจะชอบ machine learning จริง ๆ)

    การทำตาม passion จะทำให้เราพัฒนา specific knowledge ได้ยั่งยืนกว่า เพราะในขณะที่คนอื่นล้มเลิกความพยายามไปตาม trend เราจะยังคงทำในสิ่งที่เรารักอยู่ ทำให้เราสั่งสมประสบการณ์การและความรู้ได้มากกว่าคนอื่น ๆ

    .

    🧰 3.2 Leverage

    Give me a lever long enough and a place to stand, and I will move the earth.

    — Archimedes

    Leverage คือ สิ่งที่จะขยาย impact ของเรา

    ยกตัวอย่างเช่น ถ้าสัดส่วนระหว่างความพยายามและผลลัพธ์อยู่ที่ 1:1, leverage สามารถทำให้สัดส่วนนี้กลายเป็น 1:2, 1:5, 1:10, 1:1,000, 1:10,000 ได้

    Leverage มีอยู่ 3 ประเภท ได้แก่:

    1. Labour
    2. Capital
    3. Product with no marginal cost of replication

    Labour หรือแรงงานเป็น leverage ที่เก่าแก่ที่สุด แต่ใช้งานยาก เพราะเราต้องมี leadership skill ที่ดี

    Capital หรือเงินทุน เป็น leverage ที่ scale ได้ดี แต่จัดการได้ยาก แต่ใครที่ทำได้จะได้แต้มต่อจากคนอื่นมาก

    Leverage ประเภทสุดท้าย คือ product with no marginal cost of replication

    ในขณะที่ labour และ capital เป็น permission-based leverage เพราะเราจะใช้ได้ก็ต่อเมื่อได้รับความยินยอมจากคนอื่น product with no marginal cost of replication เป็น permissionless leverage เพราะเราสามารถใช้ได้โดยไม่ต้องขอความยินยอมจากใคร

    Product with no marginal cost of replication คือ สิ่งที่เราสามารถสร้างเพิ่มได้โดยใช้ต้นทุนแทบเป็น 0 เช่น:

    • หนังสือ
    • เพลง
    • โค้ด
    • YouTube video

    ในยุคที่เทคโนโลยีพัฒนาอย่างรวดเร็ว ทุกคนสามารถเข้าถึง product with no marginal cost of replication ทุกคนสามารถสร้าง video และ copy ไปโพสต์ตาม platform ต่าง ๆ โดยไม่เสียค่าใช้จ่ายสักบาท และทำให้ตัวเองให้เป็นที่รู้จักไปทั่วโลกได้ในชั่วข้ามคืนได้

    ถ้าอยากจะสร้างความมั่งคั่ง เราควรจะมี leverage ซึ่ง leverage ที่เข้าถึงได้ง่ายที่สุด คือ product with no marginal cost of replication

    .

    🫡 3.3 Accountability

    Clear accountability is important. Without accountability, you don’t have incentives.

    — Naval Ravikant

    Accountability หมายถึง ความรับผิดชอบในงานที่ทำ

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

    แม้จะมีความเสี่ยง แต่เราควรมี accountability ถ้าเราอยากสร้าง wealth เพราะเมื่อเรามี accountability เราก็จะมี credibility ซึ่งทำให้เราสามารถหา leverage อย่าง labour และ capital ได้ขึ้น

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

    ถ้าเราต้องการสร้าง wealth เราควรมี accountability ในสิ่งที่เราทำ

    .

    🏪 3.4 Equity

    You must own equity—a piece of a business—to gain your financial freedom.

    — Naval Ravikant

    นอกจาก specific knowledge, leverage, และ accountability แล้ว ถ้าเราต้องการจะสร้างความมั่งคั่งอย่างยั่งยืน เราจะควรมี equity ด้วย

    Equity เป็นการแสดงความเป็นเจ้าของ (ownership) ใน asset ที่สามารถสร้างรายได้ได้ เช่น:

    • product ต่าง ๆ
    • สินทรัพย์ทางปัญญา
    • ธุรกิจ

    ถ้าเราไม่มี ownership, ความพยายามและผลลัพธ์ที่เราได้จะอยู่ในสัดส่วนที่ 1:1 แต่ถ้ามี equity แล้ว เราจะสามารถเปลี่ยนสัดส่วนให้มากขึ้นได้

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

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

    .

    🪙 3.5 Compound Interest

    The combination of those over a long period of time with the magic of compound interest will make you wealthy.

    — Naval Ravikant

    สุดท้าย สิ่งที่เราต้องการเพื่อสร้างความมั่งคั่ง คือ เวลา

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

    เวลาอยู่ข้างเรา ถ้าเราโฟกัสได้ถูกจุด

    99% vs 1%

    99% ของสิ่งที่เราทำเป็นความพยายามที่เสียเปล่า

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

    มีเพียง 1% ของความพยายามทั้งหมดของเราที่จะให้ผลลัพธ์ที่เราต้องการ

    เราจะต้องใช้ความพยายาม 99% เพื่อหา 1% นี้ให้เจอ และเมื่อเจอแล้วให้เราทุ่มสุดตัวไปกับ 1% ที่ว่า เพราะ 1% นี้เป็นสิ่งที่ตอบโจทย์ในชีวิตของเรา

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

    Compound interest in life

    Compound interest เป็นแนวคิดทางการเงินที่ไม่ได้ใช้ได้กับการเงิน แต่ใช้กับด้านอื่น ๆ ของชีวิตอีกด้วย

    Compound interest คือ การที่เราได้ดอกเบี้ยเงินฝากเพิ่มขึ้นทุกปี เพราะในแต่ละปี เงินต้นของเราจะเท่ากับเงินต้น + ดอกเบี้ย ทำให้ดอกเบี้ยในแต่ละปีจะคิดต่อยอดจากดอกเบี้ยปีก่อน ๆ ด้วย

    Compound interest สามารถปรับใช้กับด้านต่าง ๆ ของชีวิตได้ เช่น ความสัมพันธ์

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

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


    🕊️ 4. Why Seek Wealth?

    When you’re finally wealthy, you’ll realize it wasn’t what you were seeking in the first place.

    — Naval Ravikant

    ถึงตอนนี้ เราได้เห็นแนวคิดและวิธีการสร้าง wealth แล้ว แต่เรายังไม่ได้ตอบคำถามที่ว่า ทำไมเราต้องการ wealth?

    แต่ละคนอาจมีเป้าหมายในการมองหา wealth ไม่เหมือนกัน แต่ Naval เชื่อว่า เราตามหา wealth เพื่อ freedom

    Freedom ในมุมมองของ Naval คือ อิสระในทุก ๆ ด้าน เช่น:

    • อิสระในการเลือก: สามารถเลือกทำในสิ่งที่ต้องการ และไม่ทำในสิ่งที่ไม่ต้องการได้
    • อิสระในทางการเงิน: สามารถใช้จ่ายในสิ่งที่ต้องการได้
    • อิสระทางอารมณ์: ไม่ต้องมีความรู้สึกที่ทำลายความสงบทางจิตใจ

    Freedom เป็นเป้าหมายปลายทาง และ wealth เป็นเพียงทางที่จะนำเราไปสู่ freedom

    ตราบใดที่ wealth ยังสร้าง freedom ให้เรา wealth คือทางออก

    แต่เมื่อไรที่ wealth ขัดขวาง freedom ของเรา wealth คือปัญหา


    💡 5. Additional Tips on Life of Wealth

    3 คำแนะนำเพิ่มเติมจาก Naval เกี่ยวกับการใช้ชีวิตอย่างมั่งคั่ง:

    1. Value your time
    2. Avoid ruin
    3. Early success

    .

    ⌚ 5.1 Value Your Time

    Value your time at an hourly rate, and ruthlessly spend to save time at that rate.

    — Naval Ravikant

    เวลาเป็นสิ่งที่มีค่ามากที่สุดของเรา และเราควรจะใช้เวลาอย่างคุ้มค่าที่สุด

    เทคนิคหนึ่งในการจัดการเวลา คือ กำหนด hourly rate

    Hourly rate คือ ราคาค่าตัวต่อชั่วโมงของเรา เราควรตั้ง hourly rate ให้สูงจนน่าตกใจเพื่อที่:

    1. เราจะมีแรงผลักที่จะมุ่งไปข้างหน้า
    2. เราจะรู้จักใช้เวลาอย่างคุ้มค่า

    ยกตัวอย่างเช่น เราตั้ง hourly rate ไว้ที่ 5,000 บาท และถ้าเรากำลังจะใช้เวลา 1 ชั่วโมงไปกับการดู Netflix แสดงว่า เรากำลังจะเสียเงิน 5,000 บาทไปฟรี ๆ เพราะในเวลา 1 ชั่วโมง เราสามารถทำกิจกรรมอื่นที่อาจสร้างรายได้ 5,000 บาทได้

    การตั้ง hourly rate จะช่วยให้เราคำนึงถึงเวลาในการตัดสินใจต่าง ๆ ของเรา และทำให้เราใช้เวลาอย่างคุ้มค่าที่สุด

    .

    🚨 5.2 Avoid Ruin

    The one thing you have to avoid is the risk of ruin.

    — Naval Ravikant

    เราควรหลีกเลี่ยง ruin หรือสิ่งที่จะทำลายชีวิตของเรา เช่น:

    1. Jail: ไม่ทำอะไรที่ผิดกฎหมาย ไม่มีอะไรที่คุ้มค่าพอจะให้เราเข้าไปนอนในคุก
    2. Catastrophic loss: หลีกเลี่ยงการสูญเสียแบบหมดตัว เช่น การเล่นพนัน
    3. Physical danger: อันตรายต่อร่างกายและสุขภาพ

    .

    🏆 5.3 Early Success

    Some of the most successful people I’ve seen in Silicon Valley had breakouts very early in their career.

    — Naval Ravikant

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

    สำหรับคนที่เพิ่งเริ่มต้นชีวิต Naval แนะนำให้ตัดสินใจ 3 อย่างนี้ให้ดี:

    1. Where: เราจะใช้ชีวิตอยู่ที่ไหน สถานที่ที่เราอยู่จะส่งผลต่อแนวทางและเส้นทางชีวิตของเรา
    2. Who: เราจะใช้เวลาไปกับใคร หรือใครที่เราจะมีความสัมพันธ์ด้วย
    3. What: เราจะทำอะไร เช่น จะทำงานอะไร

    เราควรคิดถึง 3 เรื่องนี้ให้ถี่ถ้วนและใน timeframe ระยะยาว เช่น:

    1. Where: จะใช้ชีวิตในเมืองไหน 10 ปี?
    2. Who: จะคบกับใครไปทั้งชีวิต?
    3. What: จะทำงานเดิมกี่ปี 3 ปี? 5 ปี?

    เราควรวางแผนทั้ง 3 สิ่งนี้ให้ดี เพราะการตัดสินใจนี้จะกำหนดเส้นทางชีวิตที่เหลือของเรา


    💰 Summary

    ในบทความนี้ เราสรุปแนวคิดในการสร้าง wealth ในหนังสือ The Almanack of Naval Ravikant

    Intro to wealth: wealth คืออะไร?

    1. Seek wealth, not money or status: ตามมา wealth ไม่ใช่ money หรือ status. Wealth คือ asset ที่สร้างรายได้ให้เราในขณะที่เราหลับ ในขณะที่ money คือ สื่อในการเคลื่อนย้าย wealth และ status คือ สถานะทางสังคมของเรา

    How to build wealth right: แนวทางในการสร้าง wealth อย่างยั่งยืน

    1. Productise yourself: สร้างสิ่งที่สังคมต้องการ แต่ยังไม่รู้ว่าจะหามาได้ยังไง
    2. Earn with mind, not time: สร้างรายได้ผ่านความคิด ไม่ใช่เวลา
    3. Luck: ตัด luck ออกจากสมการสร้าง wealth ด้วยการพัฒนาตัวเองจน luck เข้ามาหาเอง

    What to build wealth with: สิ่งที่เราควรมีเพื่อสร้าง wealth อย่างยั่งยืน

    1. Specific knowledge: ความรู้/ความสามารถเฉพาะตัว
    2. Leverage: สิ่งที่จะขยาย impact ของสิ่งที่เราทำ
    3. Accountability: ความรับผิดชอบในสิ่งที่เราทำ
    4. Equity: ownership ใน asset ที่ช่วยสร้างรายได้ในขณะที่เราหลับ
    5. Compound interest: เวลา

    Why seek wealth?

    1. Freedom: เราตามหา wealth เพื่อ freedom ในชีวิต

    Additional tips: ข้อคิดเพิ่มเติมในการสร้าง wealth

    1. Value your time: กำหนด hourly rate เพื่อรู้จักใช้เวลาอย่างคุ้มค่า
    2. Avoid ruin: หลีกเลี่ยงสิ่งที่จะทำลายชีวิต เช่น jail, catastrophic loss, และ physical danger
    3. Early success: เริ่มตามหาความสำเร็จแต่เนิ่น ๆ และตัดสินใจในเรื่องที่อยู่ ความสัมพันธ์ และสิ่งที่เราจะทำให้ดี

    🔥 Get The Almanack of Naval Ravikant

    สำหรับคนที่สนใจเนื้อหาของหนังสือและอยากอ่านเพิ่มเติม สามารถซื้อหนังสือได้ตาม link ด้านล่าง:

    Note: ใครที่สนใจอ่านต้นฉบับภาษาอังกฤษแบบ e-book หรือ PDF สามารถดาวน์โหลดฟรีได้ที่ navalmanack.com

  • Regular Expressions: เครื่องมือถอดรหัส เพื่อทำงานกับ Text ใน Google Sheets — แนะนำวิธีใช้สูตร REGEXMATCH, REGEXEXTRACT, REGEXREPLACE

    Regular Expressions: เครื่องมือถอดรหัส เพื่อทำงานกับ Text ใน Google Sheets — แนะนำวิธีใช้สูตร REGEXMATCH, REGEXEXTRACT, REGEXREPLACE

    Regular expression หรือ การเขียน pattern เพื่อทำงานกับ text เป็นเหมือนกับเครื่องถอดรหัสที่ช่วยถอดรูปแบบของข้อความ และช่วยให้เราทำงานกับข้อมูลได้ง่ายขึ้น

    ยกตัวอย่างเช่น เรามีข้อมูลลูกค้าที่เก็บค่าไว้ใน cell เดียวกัน:

    แต่เราต้องการแยกข้อมูลเป็น columns เพื่อความสะดวกในการใช้งานต่อ เช่น:

    • ID
    • Name
    • Address

    แทนที่เรา copy-paste ข้อมูลลงทีละ column ด้วยตัวเอง เราสามารถใช้สูตร regular expression ของ Google Sheets ช่วยได้:

    .

    ในบทความนี้ เราจะทำความรู้จักกับ:

    1. 3 สูตร Google Sheets ที่ใช้ทำงานกับ regular expression
    2. การเขียน regular expression เพื่อใช้งาน 3 สูตรนี้

    ถ้าพร้อมแล้วมาเริ่มกันเลย


    1. 👨‍🔬 Intro to REGEX Formulas
    2. ⌨️ Regular Expression Basics
      1. 🔣 (1) Special Characters
      2. 🔣 (2) Character Classes
      3. 🔣 (3) Quantifiers
      4. 🔣 (4) Others
      5. 📃 Learn More
    3. 💪 Put It All Together
      1. 🗝️ (1) REGEXMATCH
      2. 🗝️ (2) REGEXEXTRACT
      3. 🗝️ (3) REGEXREPLACE
    4. 📚 References

    👨‍🔬 Intro to REGEX Formulas

    Google Sheets มี 3 สูตรสำหรับใช้ regular expression ซึ่งได้แก่:

    No.FormulaFor
    1REGEXMATCH()เช็กหาคำที่ตรงกับ regular expression
    2REGEXEXTRACT()ดึงคำที่ตรงกับ regular expression ออกมา
    3REGEXREPLACE()แทนที่คำที่ตรงกับ regular expression

    โดยมีการเขียนดังนี้:

    No.FormulaSyntax
    1REGEXMATCH()REGEXMATCH(text, regular_expression)
    2REGEXEXTRACT()REGEXEXTRACT(text, regular_expression)
    3REGEXREPLACE()REGEXREPLACE(text, regular_expression, replacement)
    • text คือ ข้อมูล text ที่เราจะใช้ทำงาน
    • regular_expression คือ regular expression ที่เราใช้กำหนดเงื่อนไข
    • replacement คือ คำที่จะแทนที่คำที่ตรงกับ regular expression

    .

    ก่อนไปดูการใช้งานจริง เรามาดูหลักการเขียน regular expression เพื่อให้สูตรเหล่านี้ทำงานได้กัน


    ⌨️ Regular Expression Basics

    การเขียน regular expression แบ่งออกได้เป็น 4 กลุ่มหลัก ได้แก่:

    1. Special characters
    2. Character classes
    3. Quantifiers
    4. Others

    .

    🔣 (1) Special Characters

    Regular expression ในกลุ่มนี้ เป็นอักขระพิเศษ โดยมี usage ต่างกันดังนี้:

    No.CharacterForExample
    1^…เริ่มต้นด้วย …^J หมายถึง คำที่ขึ้นต้นด้วย J
    2…$ลงท้ายด้วย …s$ หมายถึง คำที่ลงท้ายด้วย s
    3.แทนอักขระใด ๆ 1 ตัว (ยกเว้นการขึ้นบรรทัดใหม่)c.t ใช้หาคำเช่น cat, cmt, cPt, c7t
    5\\…ใช้บอกว่า … ไม่ใช่ regular expression\\. หมายถึง ให้หาคำที่มี . แทนคำที่มีอักขระใด ๆ

    .

    🔣 (2) Character Classes

    Regular expression ในกลุ่มนี้ ใช้แทนตัวอักษรและตัวเลข:

    No.CharacterForExample
    1[…]จับคู่ตัวอักษร ใน [][ABC] หมายถึง จับคู่คำที่มี A, B, หรือ C
    2[A-Z]จับคู่ตัวอักษร A-Z พิมพ์ใหญ่จะได้คำ เช่น ANT, FGH, QPD, …
    3[a-z]จับคู่ตัวอักษร a-z พิมพ์เล็กจะได้คำ เช่น ant, fgh, qpd, …
    4[A-Za-z]จับคู่ตัวอักษร A-Z พิมพ์เล็กหรือใหญ่ก็ได้จะได้คำ เช่น aNt, Fgh, qpD, …
    5[A-z]จับคู่ตัวอักษร a-z พิมพ์เล็กหรือใหญ่ก็ได้จะได้คำ เช่น aNt, Fgh, qpD, …
    6[0-9]จับคู่ตัวตัวเลข 0-9จะได้คำ เช่น 012, 438, 507, …

    .

    🔣 (3) Quantifiers

    Regular expression ในกลุ่มนี้ ใช้แทนจำนวนตัวอักขระที่ต้องการค้นหา:

    No.CharacterForExample
    1…*จับคู่อักขระ … จำนวนตั้งแต่ 0 ขึ้นไปA* จับคู่คำ เช่น A, An, Ant, ANts, …
    2…+จับคู่อักขระ … จำนวนตั้งแต่ 1 ขึ้นไปA+ จับคู่คำ เช่น An, Ant, ANts, …
    3…?จับคู่อักขระ … จำนวน 0 หรือ 1A? จับคู่คำ เช่น A, An, AT, …
    5…{…}จับคู่อักขระ … ตามจำนวนใน {}.{5} หมายถึง จับคู่อักขระใด ๆ ที่มีความยาว 5 ตัว
    4…{…, …}จับคู่อักขระ … ตามช่วงใน {}.{3, 5} หมายถึง จับคู่อักขระใด ๆ ที่มีความยาว 3 ถึง 5 ตัว

    .

    🔣 (4) Others

    Regular expression อื่น ๆ นอกเหนือ 3 กลุ่มแรก:

    No.CharacterForExample
    1\\wจับคู่ A-Z ทั้งพิมพ์เล็กและใหญ่ หรือตัวเลขก็ได้
    2\\dจับคู่ตัวตัวเลข 0-9
    3\\bจับคู่ word boundary
    4\\nจับคู่ new line
    5\\sจับคู่ blank space
    6(…)จับกลุ่ม regular expression

    .

    📃 Learn More

    เราสามารถ regular expression อื่น ๆ ได้ที่ Syntax for Regular Expressions จาก Google


    💪 Put It All Together

    ตอนนี้ เรารู้จัก 3 สูตร REGEX และการเขียน regular expression แล้ว

    เรามาดูตัวอย่างการใช้งานสูตร REGEX ในการทำงานกัน

    .

    ในตัวอย่าง เรามีข้อมูลพนักงาน 3 columns ได้แก่:

    1. Name
    2. Email
    3. Comment

    Note: สามารถดูต้นฉบับได้ที่ Google Sheets

    .

    🗝️ (1) REGEXMATCH

    สมมุติว่า เราต้องการเช็กว่า ใน comment มีคำว่า “comment” ไหม

    เราสามารถใช้ REGEXMATCH ได้ดังนี้:

    =REGEXMATCH(C3, "[Cc]omment")

    ผลลัพธ์:

    จะเห็นว่า เราได้ค่า TRUE และ FALSE กลับมา:

    • TRUE แสดงว่า text มีคำว่า “comment”
    • FALSE แสดงว่า text ไม่มีคำว่า “comment”

    .

    🗝️ (2) REGEXEXTRACT

    เราต้องการดึงนามสกุลออกจากชื่อ

    เราสามารถใช้ REGEXEXTRACT ช่วยได้:

    =REGEXEXTRACT(A3, "\s([A-z]*)")

    ผลลัพธ์:

    .

    🗝️ (3) REGEXREPLACE

    เราต้องการเปลี่ยนอีเมลของทุกคนให้มี domain (เช่น @example.com และ @adams-mail.net) เป็น @email.com

    เราสามารถใช้ REGEXREPLACE ช่วยได้:

    =REGEXREPLACE(B3, "@[A-z.-]+\.[A-z]{2,}", "@email.com")

    ผลลัพธ์:


    📚 References

  • The Brain Audit Recap: สรุป 3 กลุ่มประเด็น จากงาน The Brain Audit โดย DataRockie ft. Sean D’Souza: วิธีเอาตัวรอดในยุคใหม่ เคล็ดลับ marketing ที่จะทำให้ลูกค้าตัดสินใจซื้อ และ Q&A

    The Brain Audit Recap: สรุป 3 กลุ่มประเด็น จากงาน The Brain Audit โดย DataRockie ft. Sean D’Souza: วิธีเอาตัวรอดในยุคใหม่ เคล็ดลับ marketing ที่จะทำให้ลูกค้าตัดสินใจซื้อ และ Q&A

    ในบทความนี้ เราจะมาสรุปเนื้อหาจาก The Brain Audit ซึ่งเป็น event พิเศษที่พี่ทอย DataRockie จัดขึ้นร่วมกับ Sean D’Souza เจ้าของ one person business “Psychotactics” ซึ่งสอนทักษะทางธุรกิจ เช่น marketing และ copywriting

    Event นี้ประกอบด้วย 3 sessions:

    1. Survive: แนวคิดในการเอาตัวรอดของคนทำงานในยุคนี้ โดย พี่ทอย
    2. Brain Audit: เคล็ดลับการทำ marketing ให้ลูกค้าซื้อ ซึ่งเป็นเนื้อหาบางส่วนจากหนังสือ The Brain Audit โดย Sean
    3. Q&A: session ถามตอบระหว่าง Sean พี่ทอย และผู้เข้าร่วม

    เราไปดูสรุปเนื้อหาในแต่ละ session กัน


    1. ⚔️ Part 1. Survive (P’Toy)
      1. 🎁 1. Productise Yourself
      2. 🦆 2. Be a Generalist
    2. 🧠 Part 2. Brain Audit (Sean D’Souza)
      1. 🧳 1. The Seven Bags Framework
      2. 🔫 2. Trigger
      3. 🎢 3. Keep the Attention
      4. 💬 4. Language
    3. 🤚 Part 3. Q&A (Sean, P’Toy, & the Audience)
    4. 🍩 Bonus
    5. 🤞 Additional Reading
    6. 📖 Expand Your Knowledge

    ⚔️ Part 1. Survive (P’Toy)

    P’Toy (left): ลงบทความทุกสัปดาห์จนพี่ทอยจำชื่อได้ 😆

    ในส่วนนี้ มีเนื้อหา 2 ประเด็นที่น่าสนใจ:

    1. Productise yourself
    2. Be a generalist

    .

    🎁 1. Productise Yourself

    เป้าหมาย คือ การพัฒนาตัวเอง, ไม่ใช่การหาเงิน

    Productise yourself เป็นแนวคิดในการประสบความสำเร็จของ Naval Ravikant ซึ่งหมายถึง การมองและทำตัวเองให้เป็น product ที่โลกต้องการ

    เช่นเดียวกับ product อย่างมือถือและ AI เราจะต้องมีการปรับปรุงและพัฒนาตัวเองอย่างต่อเนื่อง เพื่อตอบโจทย์ความต้องการของสังคม

    ถ้าเราอยากจะอยู่รอด เราควรจะยึดสิ่งนี้เป็นเป้าหมายหลักของเรา มากกว่าการหาเงินให้มากขึ้น

    แม้ในตอนแรกจะฟังดูขัดแย้งกัน แต่จริง ๆ แล้วแนวคิดนี้สอดคล้องกับการเอาตัวรอดในยุคของ AI

    ตัวเรา (หรือจริง ๆ แล้ว คือ สมอง หรือ mind ของเรา) เป็น asset ที่มีค่ามากที่สุด ในการทำงานประจำ (หรืองานออฟฟิศ) เรากำลัง “ขาย” ความรู้และความสามารถที่เรามี ให้กับบริษัทหรือคนที่จ้างงานเรา สิ่งที่เราส่งมอบทำให้ลูกค้าของเราเติบโต และเราก็ได้เงินเป็นค่าตอบแทนกลับมา

    การทำงานแบบนี้ไม่ใช่โมเดลที่ยั่งยืน เพราะ:

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

    โมเดลรายได้แบบงานประจำ:

    ✅ We + ✅ Time → ✅ Money

    ✅ We + ❌ Time → ❌ Money

    โมเดลทางรอดที่ดีกว่า คือ การใช้สมองของเราสร้าง creative artefact เช่น หนังสือ, โค้ด, วิดีโอ และ asset อื่น ๆ ที่สามารถส่งมอบคุณค่าให้กับโลกและสร้างรายได้ให้เราในระหว่างที่เราหลับ ซึ่งจะช่วยตัดเวลาออกจากสมการรายได้ของเรา:

    We → Creative artefact → Value → Money

    ในโมเดลนี้ ตัวเราเป็นต้นทางของทุกอย่าง ถ้าเราอยากจะได้สร้างรายได้ (money) มากขึ้น เราจะต้องส่งมอบคุณค่า (value) ที่ดีขึ้น ซึ่งหมายถึงการสร้าง creative artefact ที่ดีขึ้น และตัวเราจะมีความรู้ความสามารถที่มากขึ้น

    เมื่อเรามีความรู้ความสามารถที่มากขึ้นแล้ว creative artefact ก็จะมีคุณภาพมากขึ้น สามารถส่งต่อคุณค่าได้ดีขึ้น และรายได้ก็จะมากขึ้นตามไปด้วย

    ดังนั้น ถ้าเราอยากจะอยู่รอดในยุคนี้ เราควรจะโฟกัสกับการพัฒนาตัวเอง มากกว่าการหาเงินให้มากขึ้น เพราะเมื่อเราพัฒนาตัวเองให้เก่งขึ้น เงินก็จะตามมาเอง

    Better yourself, not money

    .

    🦆 2. Be a Generalist

    หนทาง คือ การเป็น "เป็ด"

    (Note: ในสรุปส่วนนี้ ผมได้ใส่ข้อมูลและความคิดเห็นเพิ่มเติมลงไปด้วย)

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

    ก่อนวันงาน The Brain Audit ไม่กี่วัน CK Cheong ซึ่งเป็น CEO ของ Fastwork ออกมาแสดงความเห็นว่า ความต้องการคนที่เป็นเป็ดกำลังลดลง โดยเฉพาะตอนนี้ที่ทุกคนมี AI ซึ่งเป็นเป็ดที่เก่งทุกด้านอยู่ในกระเป๋าอยู่แล้ว

    มุมมองของ CK Cheong ต่อการเป็น generalist (source: TNN Tech)

    ในมุมนี้ CK Cheong อาจมีส่วนที่สอดคล้องกับความเป็นจริงอยู่บ้าง เพราะถ้าเราดูรายละเอียดประกาศรับสมัครงานต่าง ๆ เราจะเห็นได้ว่า บริษัทต้องการคนที่มีความรู้ความสามารถอยู่ไม่กี่ด้าน

    ยกตัวอย่างเช่น ประกาศงานตำแหน่ง Data Analyst ของ AIS ที่ต้องการคนที่ทักษะดังนี้:

    • ความรู้เลขและสถิติ
    • การเขียนโค้ดอย่าง SQL
    • เครื่องมือ analytics อย่าง Tableau
    • ความรู้เรื่อง big data
    • ความรู้เรื่อง cloud

    จะเห็นได้ว่า ทักษะที่ AIS ต้องการจำกัดวงอยู่แค่ data analyst คนที่มีความสามารถอื่น ๆ เช่น ตัดต่อวิดีโอ เล่นกีต้าร์ หรือวาดรูป อาจไม่ได้รับการพิจารณาเป็นพิเศษ เพราะไม่ใช่ทักษะที่จะช่วยบริษัทแก้ปัญหาได้ คนเหล่านี้จะยังถูกประเมินตามความสามารถในประกาศงาน และถ้าคนเหล่านี้เป็น “เป็ด” ตามนิยามของ CK Cheong คือ รู้กว้างแต่ไม่รู้ลึก ก็จะสู้คนที่เป็น specialist ที่รู้ลึกรู้จริงไม่ได้ และมีโอกาสได้งานน้อยกว่า specialist

    อย่างไรก็ตาม ผมเห็นด้วยกับพี่ทอยที่เป็น “pro generalist” ว่า การเป็น generalist ยังเป็นทางรอดสำหรับคนทำงานในยุคนี้

    จริงอยู่ว่า ผู้จ้างงานจะมองหา specialist เวลารับสมัครพนักงาน แต่ในมุมมองคนหางานแล้ว เราควรเป็น generalist ด้วยเหตุผล 3 ข้อ:

    ข้อที่ 1. Generalist มีตัวเลือกมากกว่า specialist

    ถ้าเราเก่งด้านใดด้านหนึ่งอย่างเดียว หมายความว่า เราจะรับงานได้เฉพาะงานที่ตรงกับทักษะเดียวของเรา

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

    ข้อ 2. Generalist ชนะใน long run

    แม้ว่า generalist มักจะแพ้ specialist ใน domain ของ specialist เอง (เช่น เขียนโค้ดสู้กับ programmer ไม่ได้) แต่ generalist จะชนะในอีกหลาย ๆ ด้าน เพราะแม้จะรู้ไม่สุด แต่ก็มีความรู้เพียงพอที่จะทำงานให้สำเร็จได้ (เช่น ตัดต่อวิดีโอได้ ทำให้สามารถสร้างเปิดช่อง YouTube ของตัวเองได้)

    ข้อที่ 3. Generalist is a niche

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

    ยกตัวอย่างเช่น บุคคลที่ประสบความสำเร็จจาก skill stacking:

    • Scott Adams ที่ประสบความสำเร็จจากการ์ตูนตลกเสียดสีสังคมเรื่อง Dilbert ซึ่งเกิดการผสมทักษะการวาดรูป + ความรู้ธุรกิจ + อารมณ์ขัน
    • Dan Koe เจ้าของ one-person business ที่ประสบความสำเร็จจากการสร้าง content โดยผสมทักษะการเขียน + ปรัชญา + ความรู้ธุรกิจ
    • พี่ทอย เจ้าของ DataRockie School ที่เป็นที่รู้จักในฐานะนักธุรกิจและ generalist (ของแทร่ 555+) ซึ่งสร้างความสำเร็จด้วยการผสมทักษะ data + การเขียน + marketing + และอีกมากมาย
    • Sean D’Souza เจ้าของ Psychotactics ธุรกิจที่ทำด้วยตัวเองและประสบความสำเร็จมายาวนานต่อเนื่อง 25 ปี ด้วยการผสมทักษะวาดการ์ตูน + marketing + การเขียน

    ดังนั้น แม้ว่าสังคมอาจมีความต้องการ generalist น้อยลง แต่การเป็น generalist ยังคงเป็นทางเลือกในการอยู่รอดในปัจจุบัน


    🧠 Part 2. Brain Audit (Sean D’Souza)

    Sean D’Souza (right): ขอลายเซ็น Sean 3 ครั้งในวันเดียวจน Sean จำหน้าได้ 😂

    ในส่วนนี้ Sean มาแชร์ความรู้ในการทำ marketing ซึ่งแบ่งได้เป็น 4 ประเด็น ได้แก่:

    1. The Seven Bags Framework
    2. Trigger
    3. Keep the attention
    4. Language

    .

    🧳 1. The Seven Bags Framework

    ลูกค้าจะซื้อก็ต่อเมื่อได้ข้อมูลครบทุกใบ

    เหตุผลหนึ่งที่ทำให้ลูกค้ายังไม่ตัดสินใจซื้อ คือ ลูกค้ายังมีข้อมูลไม่เพียงพอในการตัดสินใจ

    ดังนั้น ถ้าเราต้องการให้ลูกค้าซื้อของ หน้าที่หลักของเรา คือ การให้ข้อมูลที่เพียงพอในการตัดสินใจกับลูกค้า ซึ่งเราสามารถทำได้โดยใช้ The Brain Audit framework ที่มี 7 ส่วน:

    1. Problem
    2. Solution
    3. Target profile
    4. Objection
    5. Testimonials
    6. Risk
    7. Uniqueness

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

    Seven Red Bags

    ใน session, Sean พูดถึงกระเป๋า 3 ใบแรก ซึ่งเรียกรวมกันว่า trigger (สำหรับใบอื่น ๆ สามารถตามอ่านรายละเอียดกันได้ในหนังสือ The Brain Audit)

    .

    🔫 2. Trigger

    Trigger = Problem + Solution + Target profile

    Trigger คือ สิ่งที่จะกระตุ้นให้ลูกค้าหันมาสนใจเรา เพื่อที่เราจะสามารถส่งสารที่เหลือให้กับลูกค้าได้

    Trigger ประกอบด้วยกระเป๋า 3 ใบแรกในสายพานซึ่งได้แก่:

    1. Problem
    2. Solution
    3. Target profile

    ใบที่ 1. Problem หมายถึง สิ่งที่เปลี่ยนแปลงไปในทางที่แย่ลง เช่น:

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

    Problem เป็นภาษาของสมอง และเป็นสิ่งที่จะทำให้ลูกค้าหันมาสนใจเรา สิ่งที่คนส่วนใหญ่มักทำพลาด คือ พูดถึงคุณประโยชน์ของ product/service โดยไม่เริ่มจาก problem ซึ่งจะทำให้ลูกค้าตัดสินใจซื้อไม่ได้ เพราะไม่เห็นความเชื่อมโยงระหว่าง product/service และตัวเอง

    ใบที่ 2. Solution คือ ประโยชน์ที่ product/service เราจะส่งมอบให้เพื่อแก้ปัญหาให้กับลูกค้า

    ใบที่ 3. Target profile คือ profile ของคนคนเดียวใน target audience ของเรา ซึ่งเราจะใช้เป็นต้นแบบในการสร้าง marketing message เพื่อสื่อสารกับลูกค้า

    นั่นคือ แทนที่เราจะเขียน marketing message เพื่อตอบโจทย์คนส่วนมาก เราจะสร้าง message ที่จะส่งถึงคนคนเดียว (target profile) ซึ่งเป็นคนที่มี problem และต้องการ solution ของเรา

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

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

    การเขียน marketing message เพื่อให้เป็น trigger จะต้องประกอบด้วยกระเป๋า 3 ใบนี้ เพื่อทำให้ลูกค้าหันมาสนใจเรา

    ยกตัวอย่างเช่น marketing message ของ solution ที่จะช่วยให้คนน้อยหลับได้ง่ายขึ้น:

    Death of a loved one? Fix insomnia in under 5 minutes.

    • Problem: Insomnia
    • Solution: Fix [insomnia]
    • Target profile: [people with] death of a loved one

    ถ้าลูกค้าเห็น trigger ของเรา และถามว่า:

    • How do you do that? หรือ
    • What do you mean by that?

    แสดงว่า trigger ของเราสามารถดึงความสนใจของลูกค้าได้สำเร็จ และเราสามารถที่จะไป step ถัดไปได้

    เคล็ดลับกระเป๋า 3 ใบ:

    • ถ้าลูกค้าบอกว่า “Interesting” นั่นหมายถึง ลูกค้าไม่ได้สนใจจริง ๆ แต่ถ้าลูกค้าพูดว่า “Tell me more about it” แสดงว่าเราเรียกความสนใจของลูกค้าได้สำเร็จ
    • ในการสร้าง marketing message เราควรจะเริ่มจาก target profile > problem > solution

    .

    🎢 3. Keep the Attention

    Series of problems + solutions -> Rollercoaster

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

    Sean เสนอ framework ง่าย ๆ สำหรับปัญหานี้ นั่นคือ ให้เราพูดถึง problem + solution สลับกันไปเรื่อย ๆ:

    • 🔴 Problem
    • 🟢 Solution
    • 🔴 Problem
    • 🟢 Solution
    • 🔴 Problem
    • 🟢 Solution
    • 🔴 Problem
    • 🟢 Solution
    Keep the attention: Problem + Solution

    ถ้าเราไม่คอยพูดถึง problem + solution สลับกันไป ลูกค้าของเราก็จะเหมือนกำลังนั่งรถไฟที่วิ่งเอื่อย ๆ ไปบนที่ราบ (และหลับได้ง่าย ๆ)

    ในทางกลับกัน ถ้าเราคอยสื่อสารถึง problem + solution สลับกันไป ลูกค้าก็จะเหมือนกำลังนั่ง rollercoaster และไม่มีทางที่ลูกค้าจะหลับหรือรู้สึกเบื่อเราได้

    Problem + Solution = Rollercoaster

    .

    💬 4. Language

    ลูกค้าจะไม่เข้าใจถ้าเราไม่พูดภาษาลูกค้า

    สุดท้าย ไม่ว่า marketing message จะดีแค่ไหน แต่ลูกค้าเราจะไม่ตอบรับเลยถ้าไม่เข้าใจภาษาของเรา

    Sean ยกตัวอย่างว่า ถ้าเรากำลังยื่นข้อเสนอพักร้อนฟรี โดยไม่มีค่าใช้จ่ายหรือข้อผูกพันใด ๆ ให้กับลูกค้า ลูกค้ามีโอกาสที่จะไม่ตอบรับได้ ถ้าเรากำลังพูดเป็นภาษาที่ลูกค้าไม่เข้าใจ (เช่น พูดเป็นภาษา Hindi ให้คนไทยฟัง)

    ดังนั้น เราควรใช้ภาษาเดียวกับลูกค้าในการทำ marketing อย่างมีประสิทธิภาพ

    นอกจากนี้ สิ่งที่เราใส่ลงไปใน marketing message ก็มีผลต่อการตัดสินใจซื้อของลูกค้าเช่นกัน

    ยกตัวอย่างเช่น ถ้าเรามีรถ 2 คันซึ่งมีทุกอย่างเหมือนกันยกเว้นราคา:

    • คันที่ 1: $35,000
    • คันที่ 2: $18,000
    Which would you buy? $35,000 or $18,000 cars?

    หลายคนก็เลือกที่จะซื้อคันที่ 2 จนกระทั่งคนขายบอกว่าคันที่ 2 เป็นรถที่ถูกขโมยมา ถึงตอนนั้นทุกคนก็จะหันไปเลือกคันที่ 1 ซึ่งมีราคาแพงกว่าเท่าตัว


    🤚 Part 3. Q&A (Sean, P’Toy, & the Audience)

    Result > information

    ใน session ถามตอบ มี 6 หัวคิดที่น่าสนใจ:

    1. ลูกค้าที่สำคัญที่สุด คือ ลูกค้าที่กลับมาซื้อซ้ำ เราจะต้องทำให้ลูกค้ากลับมาซ้ำโดยการให้ result ไม่ใช่ให้ information เพราะในยุคของ AI ลูกค้าสามารถหา information ได้ง่ายมาก แต่น้อยคนที่จะให้ result กับลูกค้าได้
    2. Talent คือ การทำผิดให้น้อยลง และ learning คือ การสร้างความผิดพลาด (อ้างอิงหนังสือ Suddenly Talented)
    3. ถ้าเราไม่เก่ง AI ก็จะเก่งกว่าเรา แต่ถ้าเราเก่ง AI ก็จะไม่ค่อยมีประโยชน์
    4. การเขียน คือ การคิด (writing is thinking) เราควรจะฝึกเขียนทุกวันเพื่อพัฒนากระบวนการคิดให้ดีขึ้นเรื่อย ๆ
    5. มองหา “good teacher” ไม่ใช่ “fast teacher” เพราะ “good teacher” คือ คนที่จะให้ result กับเราได้
    6. เริ่มต้นจากการโฟกัสไปที่ลูกค้าคนเดียวของเรา ถ้าเราหาลูกค้าคนนี้เจอ เราก็จะหาลูกค้าอีก 1,000 คนได้
    ภาพบรรยากาศงาน The Brain Audit (source: Kasidis Satangmongkol)

    🍩 Bonus

    ในอนาคต ไม่มีใครรู้ว่าจะเกิดอะไรขึ้น

    ช่วงท้ายงาน ผมได้มีโอกาสพูดคุยกับพี่ทอยในระหว่างเซ็นหนังสือ มี 3 ประเด็นที่พี่ทอยแชร์ให้ฟังเกี่ยวกับการสร้างเว็บไซต์และการใช้ชีวิต:

    1. ถ้าจะสร้างตัวในโลกออนไลน์ เราควรสร้างเว็บไซต์เป็นของตัวเอง เพราะถ้าเราฝากตัวไว้กับ platform อื่น (เช่น Facebook) online presence เราจะเปลี่ยนไปเมื่อไรก็ได้ เพราะ algorithm ของ platform สามารถเปลี่ยนได้ทุกเมื่อ
    2. เมื่อเราได้ traffic เข้ามาในหน้าเว็บของเราแล้ว เราควรจะ direct traffic ไปที่ที่หนึ่ง ซึ่งที่นั้นควรเป็น product/service ของเรา (ตั้งแต่วันแรกที่มีเว็บไซต์ Sean ก็มีหนังสือ The Brain Audit ควรรับ traffic อยู่แล้ว)
    3. ไม่มีใครรู้ว่า ในอนาคตจะเกิดอะไรขึ้น เราควรใช้ชีวิตอยู่กับปัจจุบัน

    🤞 Additional Reading

    อ่านสรุปไอเดียเพิ่มเติมจาก event ได้ที่:


      📖 Expand Your Knowledge

      สำหรับที่คนสนใจติดตามไอเดียเพิ่มเติมจากหนังสือที่พูดถึงในบทความนี้ สามารถซื้อหาหนังสือได้ตาม link ด้านล่าง:

      • The Brain Audit ของ Sean D’Souza: framework กระเป๋า 7 ใบในการทำ marketing ให้ลูกค้าซื้อ
      • The Almanack of Naval Ravikant ของ Eric Jorgenson: รวมข้อคิดเกี่ยวกับ wealth และ happiness ของ Naval Ravikant นักลงทุนที่ประสบความสำเร็จจากการลงทุนในบริษัทอย่าง Uber, X (Twitter), และ FourSquare
      • Suddenly Talented ของ Sean D’Souza: แนวคิดการทำตัวให้เก่งในระดับที่เข้าถึงได้ (ใครที่อยากวาดรูปวาฬเป็น ลองอ่านหนังสือเล่มนี้ดู 🐳)

      Note:

    • แบบทดสอบทางจิตวิทยาน่าเชื่อถือแค่ไหน? แนะนำให้รู้จักกับ Reliability และ Validity — 2 ลักษณะที่ทุกคนควรรู้ เพื่อประเมินประสิทธิภาพของแบบทดสอบทางจิตวิทยาได้ด้วยตัวเอง (ไม่ต้องเป็นนักจิตวิทยาก็ทำได้)

      แบบทดสอบทางจิตวิทยาน่าเชื่อถือแค่ไหน? แนะนำให้รู้จักกับ Reliability และ Validity — 2 ลักษณะที่ทุกคนควรรู้ เพื่อประเมินประสิทธิภาพของแบบทดสอบทางจิตวิทยาได้ด้วยตัวเอง (ไม่ต้องเป็นนักจิตวิทยาก็ทำได้)

      แบบทดสอบทางจิตวิทยา (psychological test) เป็นเครื่องมือที่ช่วยเราประเมินลักษณะทางจิตวิทยาได้อย่างมีมาตรฐาน เช่น:

      • Personality
      • Intelligence (IQ)
      • Value
      • Emotion
      • Self-concept

      แบบทดสอบทางจิตวิทยาเป็นที่นิยมอย่างแพร่หลาย โดยในแต่ละปีมีคนทำแบบทดสอบทางจิตวิทยาราว 80–100 ล้านคน (Goldberg, 2023; Leikvoll, 2022)

      เราใช้แบบทดสอบทางจิตวิทยา เช่น 16personalities ทั้งในชีวิตประจำวันและในการทำงาน เราทำแบบทดสอบเพื่อเข้าใจตัวเองมากขึ้น (เช่น ดูว่าเรามีนิสัยเหมือนคนดังหรือตัวละครใดจาก Game of Throne) ในการทำงาน เราใช้แบบทดสอบเพื่อคัดกรองผู้สมัครและวางแผนพัฒนาบุคลากรให้เหมาะสมกับองค์กร

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

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

      แบบทดสอบที่เราใช้งานมีประสิทธิภาพเพียงพอที่จะตัดสินชีวิตของเราได้มากน้อยขนาดไหน?

      อะไรที่จะบอกเราได้ว่าแบบทดสอบสามารถประเมินสิ่งที่เราต้องการประเมินได้จริง?

      เราสามารถวิเคราะห์ประสิทธิภาพของแบบทดสอบได้จากหลายมุมมอง เช่น:

      • จำนวนข้อคำถาม (item)
      • รูปแบบการตอบ (เช่น เขียนตอบ, เลือกตอบ)
      • รูปแบบของแบบทดสอบ (เช่น ประเมินตัวเอง, สัมภาษณ์, เล่นเกม)
      • การแปลผล (เช่น แปลผลโดยอิงกลุ่มหรืออิงคะแนนตัวเอง)

      อย่างไรก็ตาม ไม่ว่าจะเป็นการวิเคราะห์แบบไหน คำตอบที่ได้จะย้อนกลับมาที่ 2 ลักษณะหลักที่ทุกแบบทดสอบจะต้องมี ได้แก่:

      1. Reliability (ความเที่ยง)
      2. Validity (ความตรง)

      ดังนั้น แม้ว่าเราอาจจะไม่ใช่นักจิตวิทยาหรือผู้เชี่ยวชาญในการทดสอบ ถ้าเราเข้าใจลักษณะทั้งสองอย่างนี้แล้ว เราจะสามารถบอกได้ว่า แบบทดสอบมีประสิทธิภาพภาพหรือไม่

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

      ถ้าพร้อมแล้ว ไปเริ่มกันเลย


      1. 📏 Reliability
        1. ⌚ Test-Retest Reliability
        2. 🤌 Internal Consistency
        3. 🅰️ Alternate Form Reliability
      2. 📐 Intro to Validity
      3. 💭 Validity, Part I: Opinion-Based Approach
        1. 🙃 Face Validity
        2. 🧐 Content Validity
      4. 👁️ Validity, Part II: Empirical Approach
        1. 🏗️ Construct Validity
        2. 🌡️ Criterion Validity
      5. 💪 Summary
      6. 👀 See for Yourself: Is 16Personalities Reliable & Valid?
      7. 📚 Further Reading
      8. 📃 References
      9. ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

      📏 Reliability

      Reliability หมายถึง ความเสถียรของคะแนนแบบทดสอบ

      ถ้าเราเปรียบแบบทดสอบเหมือนตลับเมตร reliability คือ การที่เราวัดโต๊ะตัวเดียวกันและได้ความยาวเท่าเดิมทุกครั้ง

      สำหรับแบบทดสอบทางจิตวิทยา เราสามารถประเมิน reliability ได้ 3 แบบ ได้แก่:

      1. Test-retest reliability: ความเสถียรในมิติเวลา
      2. Internal consistency: ความเสถียรภายในตัวเอง
      3. Alternate form reliability: ความเสถียรระหว่างต้นฉบับและ alternate form

      .

      ⌚ Test-Retest Reliability

      Test-retest reliability เป็น reliability ที่ประเมินตามมิติเวลา นั่นคือ ถ้าเราเก็บคะแนนแบบทดสอบ 2 ครั้งในเวลาที่ต่างกัน คะแนนทั้งสองครั้งจะเหมือนหรือต่างกันแค่ไหน

      เรามักใช้ correlation ในการวิเคราะห์ test-retest reliability

      Correlation มีค่าอยู่ระหว่าง 0 กับ 1 โดย:

      • 0 หมายถึง คะแนนสองครั้งไม่มีความสอดคล้องกันเลย
      • 1 หมายถึง คะแนนเหมือนกัน 100%

      ดังนั้น ยิ่งค่า correlation เข้าใกล้ 1 มากเท่าไร ก็แสดงว่ามี test-retest reliability สูงขึ้นเท่านั้น

      ยกตัวอย่างเช่น เรามีแบบทดสอบ IQ ที่มีค่า correlation ระหว่างคะแนน 2 ครั้ง (เช่น เดือนที่แล้วกับวันนี้) ต่ำ (เช่น .10) แสดงว่าคะแนนมีความแตกต่างมาก (เช่น IQ = 10 และ IQ = 100) และแบบทดสอบมีความเสถียรน้อย

      ในทางกลับกัน ถ้าแบบทดสอบมี correlation สูง (เช่น .80) แสดงว่า คะแนนมีความคล้ายกันสูง (เช่น IQ = 100 และ IQ = 101) และแบบทดสอบมีความเสถียรสูง

      ทั้งนี้ test-retest reliability เหมาะกับแบบทดสอบที่ประเมินลักษณะที่มีความคงที่และเปลี่ยนแปลงน้อย (เช่น personality, intelligence ซึ่งไม่เปลี่ยนวันต่อวัน)

      ถ้าเราต้องการประเมิน reliability ของแบบทดสอบที่ประเมินลักษณะที่เปลี่ยนแปลงได้ง่าย (เช่น อารมณ์) เราควรใช้ reliability ประเภทอื่นอย่าง internal consistency และ alternate form reliability ในการประเมินแบบทดสอบ

      .

      🤌 Internal Consistency

      Internal consistency เป็น reliability ที่ดูความสอดคล้องระหว่างข้อคำถาม โดยแนวคิด คือ ถ้าข้อคำถามประเมินลักษณะเดียวกัน คะแนนของทุกข้อควรเป็นไปในทิศทางเดียวกัน

      ยกตัวอย่างเช่น ถ้าแบบทดสอบ extraversion มี reliability สูง คนตอบแบบทดสอบก็ควรให้คะแนนทุกข้อเหมือนกัน เช่น:

      • ชอบคุยกับคนอื่น → 5/5 (สูง)
      • ชอบเที่ยวกับเพื่อน → 4/5 (สูง)
      • ชอบไปปาร์ตี้ → 5/5 (สูง)

      ในทางกลับกัน ถ้าแบบทดสอบมี reliability ต่ำ คะแนนของทุกข้อจะแตกต่างกัน เช่น:

      • ชอบคุยกับคนอื่น → 1/5 (ต่ำ)
      • ชอบเที่ยวกับเพื่อน → 3/5 (ปานกลาง)
      • ชอบไปปาร์ตี้ → 5/5 (สูง)

      การคำนวณ internal consistency มีหลายวิธี แต่วิธีที่นิยมที่สุด คือ การคำนวณ Cronbach’s alpha (α) ซึ่งมีค่าอยู่ระหว่าง 0 กับ 1 โดย:

      • 0 หมายถึง internal consistency ต่ำสุด
      • 1 หมายถึง internal consistency สูงสุด

      α ในระดับที่ “ยอมรับได้ (acceptable)” มีค่าตั้งแต่ .70 ขึ้นไป (Ashton, 2018)

      วิธีอื่น ๆ ในการประเมิน internal consistency ได้แก่:

      1. Split-half reliability: แบ่งแบบทดสอบเป็น 2 ส่วนและดูว่า คะแนนสองส่วนเหมือนกันขนาดไหน
      2. Inter-rater reliability: ดูความสอดคล้องระหว่างคะแนนจากผู้สังเกตการณ์ตั้งแต่ 2 คนขึ้นไป

      .

      🅰️ Alternate Form Reliability

      สุดท้าย alternate form reliability เป็น reliability ที่ดูความสอดคล้องระหว่างแบบทดสอบต้นฉบับและ alternate form

      Alternate form หมายถึง version ของแบบทดสอบที่ค่าทางสถิติต่าง ๆ เหมือนกับต้นฉบับ เช่น:

      • Mean
      • Standard deviation
      • Correlation กับแบบทดสอบอื่น ๆ

      ถ้าคะแนนของต้นฉบับเหมือนกับคะแนนของ alternate form แสดงว่า แบบทดสอบของเรามี reliability สูง

      Alternate form reliability ไม่เป็นที่นิยมใช้ เนื่องจากข้อจำกัด 2 อย่าง ได้แก่:

      1. การสร้างแบบทดสอบอีกฉบับให้เป็น alternate form มีความท้าทายสูง (การทำให้ค่าสถิติเหมือนกันเป็นเรื่องยาก)
      2. แม้ว่า เราจะสามารถสร้าง alternate form ได้แล้ว เราไม่สามารถมั่นใจได้ 100% ว่า คะแนนของ alternate form จะสะท้อนถึงสิ่งเดียวกับต้นฉบับ (เช่น คะแนน 100 ของต้นฉบับอาจหมายถึง extraversion แต่คะแนน 100 ของ alternate form อาจหมายถึง IQ ก็ได้) ทำให้การเปรียบเทียบต้นฉบับและ alternate form ไม่มีความหมาย เพราะ เรากำลังเปรียบเทียบแบบทดสอบที่ประเมินลักษณะที่แตกต่างกัน

      📐 Intro to Validity

      ในขณะที่ reliability ประเมินความเสถียรของคะแนน validity ประเมินว่า แบบทดสอบสามารถประเมินในสิ่งที่เราต้องการได้หรือไม่

      Reliability และ validity มีความเกี่ยวข้องกัน โดยแบบทดสอบจะไม่มี validity ถ้าไม่มี reliability เพราะถ้าคะแนนแบบทดสอบไม่คงที่ (reliability) เราจะไม่สามารถรู้ได้ว่า แบบทดสอบกำลังประเมินอะไรอยู่ (validity)

      การที่แบบทดสอบจะมี validity ได้ จะต้องมี reliability ก่อน อย่างไรก็ตามการมี reliability ไม่ได้หมายความว่า แบบทดสอบจะมี validity

      ยกตัวอย่างเช่น แบบทดสอบ extraversion อาจให้คะแนนเหมือนเดิมทุกครั้ง แต่แบบทดสอบอาจไม่ได้วัด extraversion แต่วัดลักษณะอื่นอย่าง intelligence (ซึ่งมีคะแนนคงที่) ก็ได้

      ดังนั้น แบบทดสอบจะมี validity ได้จะต้องมี reliability ก่อน แต่เมื่อมี reliability แล้ว เราจะต้องทดสอบ validity เพื่อดูว่า แบบทดสอบสามารถประเมินสิ่งที่ต้องประเมินได้หรือไม่

      Validity แบ่งเป็น 2 กลุ่มใหญ่ ๆ ได้แก่:

      1. Opinion-based approach: validity ตามความคิดเห็น
      2. Empirical approach: validity ตามหลักฐานเชิงประจักษ์ (หลักฐานที่สามารถมองเห็นและตรวจสอบได้)

      💭 Validity, Part I: Opinion-Based Approach

      ในกลุ่ม opinion-based approach เรามี validity 2 ประเภท ได้แก่:

      1. Face validity
      2. Content validity

      .

      🙃 Face Validity

      Face validity คือ validity ตามความเห็นของผู้ตอบแบบทดสอบ

      ถ้าคนที่ตอบแบบทดสอบบอกว่า แบบมาทดสอบ “สามารถ” วัดสิ่งที่เราต้องการได้ แสดงว่าแบบทดสอบเรามี face validity สูง

      เนื่องจาก face validity เป็นเพียงความคิดเห็น การมี face validity จึงไม่ได้หมายความว่าแบบทดสอบจะสามารถประเมินสิ่งที่เราต้องการได้จริง

      เราสามารถเห็นแบบทดสอบที่มี face validity ต่ำ แต่สามารถประเมินสิ่งที่ต้องการได้ เช่น:

      • IAT ที่วัดความลำเอียงต่อกลุ่มคน (เช่น คนผิวสี) แม้ว่า เราจะตอบว่า คนผิวสี = “ดี” แต่แบบทดสอบก็สามารถบอกได้ว่า เรามีความลำเอียงไหม
      • Name Letter Preference Task ที่ให้คนให้คะแนนความชอบต่อตัวอักษรต่าง ๆ ซึ่งสามารถประเมิน self-esteem ได้ (คนส่งนใหญ่จะให้คะแนนตัวอักษรในชื่อตัวเองมากกว่าตัวอักษรอื่น)
      • Iowa Gambling Task ที่เป็นเกมไพ่สำหรับประเมินความสามารถในการตัดสินใจ

      แม้ว่า face validity อาจไม่ใช่ตัวบ่งชี้ validity ที่ดี แต่ face validity มีประโยชน์เมื่อเราต้องการสร้างแรงจูงใจให้ผู้ตอบ: เมื่อแบบทดสอบดูเหมือนจะประเมินในสิ่งที่ควรประเมิน (มี face validity) ผู้ตอบจะมีแรงจูงใจที่จะทำแบบทดสอบให้เสร็จ มากกว่าเมื่อแบบทดสอบขาด face validity

      .

      🧐 Content Validity

      เช่นเดียวกับ face validity, content validity เกิดมาจากความคิดเห็น แต่แทนที่จะมาจากคนทั่วไป content validity เป็นความเห็นของผู้เชี่ยวชาญ

      ถ้าผู้เชี่ยวชาญประเมินแบบทดสอบของเราแล้วยกนิ้วให้ 👍 แสดงว่าแบบทดสอบเรามี content validity สูง

      เช่นเดียวกับ face validity, content validity ไม่ได้การันตีว่าแบบทดสอบเราจะสามารถวัดสิ่งที่ต้องการวัดได้ เพราะความเห็นของผู้เชี่ยวชาญยังมีความผิดพลาดได้

      Content validity มีประโยชน์ในขั้นต้นของการพัฒนาแบบทดสอบ เราสามารถให้ผู้เชี่ยวชาญประเมินและตัดข้อคำถามที่ไม่น่าเกี่ยวข้องกับสิ่งที่เราจะวัดออกได้

      ไม่ว่าแบบทดสอบจะมีหรือไม่มี face validity และ content validity เราจะไม่รู้เลยว่า แบบทดสอบสามารถประเมินสิ่งที่เราต้องการได้ไหม จนกว่าเราจะทดสอบให้เห็นกับตา (empirical approach)


      👁️ Validity, Part II: Empirical Approach

      Validity ในกลุ่ม empirical approach มีอยู่ 2 ประเภท ได้แก่:

      1. Construct validity
      2. Criterion validity

      .

      🏗️ Construct Validity

      Construct หมายถึง ลักษณะทางจิตวิทยาซึ่งเรามองไม่เห็นและไม่สามารถจับต้องได้ เช่น personality, intelligence, self-concept

      Construct validity หมายถึง validity ของแบบทดสอบในการประเมิน construct ที่ต้องการ

      เราสามารถวิเคราะห์ construct validity ได้ด้วยการดูความสัมพันธ์ระหว่างแบบทดสอบของเรากับแบบทดสอบอื่น ๆ ซึ่งสามารถแบ่งได้เป็น 2 แบบ ได้แก่:

      1. Convergent validity
      2. Divergent validity (หรือ discriminant validity)

      สำหรับ convergent validity เราจะดูว่า แบบทดสอบมีความสัมพันธ์กับแบบทดสอบอื่น ๆ ที่ควรมีไหม

      ยกตัวอย่างเช่น แบบทดสอบ IQ ซึ่งสะท้อนความฉลาดรอบด้าน ควรมีความสัมพันธ์กับแบบทดสอบความสามารถอื่น ๆ เช่น แบบทดสอบเลข แบบทดสอบความรู้ทั่วไป ถ้าแบบทดสอบ IQ มีความสัมพันธ์กับแบบทดสอบเหล่านี้ ก็แสดงว่ามี convergent validity

      Divergent validity คือ การที่แบบทดสอบของเราไม่มีความสัมพันธ์กับแบบทดสอบที่ไม่ควรเกี่ยวข้องด้วย

      ยกตัวอย่างเช่น ถ้าแบบทดสอบ IQ จะมี divergent validity ได้ จะต้องไม่มีความสัมพันธ์กับแบบทดสอบที่ไม่เกี่ยวข้องกับสามารถทางปัญญา เช่น ความทดสอบ integrity หรือแบบทดสอบความสุภาพ

      ในการวิเคราะห์ construct validity ยิ่งเราทดสอบ convergent validity และ divergent validity ได้มากเท่าไรก็ยิ่งดี เพราะเราจะยิ่งมั่นใจได้ว่า แบบทดสอบของเราสามารถประเมินสิ่งที่ต้องการประเมินได้จริง

      ยกตัวอย่างเช่น เราควรหา convergent validity ของแบบทดสอบ IQ กับแบบทดสอบหลาย ๆ วิชา เช่น ข้อสอบเลข, ข้อสอบภาษา, ข้อสอบสังคม แทนการหา convergent validity กับวิชาใดวิชาหนึ่ง

      เรามักใช้ correlation ในการวิเคราะห์ construct validity ดังนี้:

      1. Convergent validity: ยิ่ง correlation สูงยิ่งดี (เช่น .7 หรือ -.7) *
      2. Divergent validity: ยิ่ง correlation น้อยก็ยิ่งดี (เช่น .10 หรือ -.10)

      Note: * convergent validity ไม่ควรสูงเกิน เพราะนั่นอาจหมายความว่า แบบทดสอบเราอาจประเมินสิ่งเดียวกับแบบทดสอบอื่น เช่น แบบทดสอบ IQ กำลังประเมินความสามารถด้านคณิตศาสตร์แทน IQ (ความฉลาดรอบด้าน)

      .

      🌡️ Criterion Validity

      Criterion validity คือ validity ที่ดูความสอดคล้องระหว่างแบบทดสอบกับเกณฑ์ (criterion) ที่มีความสำคัญ

      ยกตัวอย่างเช่น:

      • แบบทดสอบ IQ กับเกรดการเรียน
      • แบบทดสอบ extraversion กับจำนวนเพื่อน
      • แบบทดสอบ integrity กับพฤติกรรมการโกง
      • แบบทดสอบ depression กับภาวะซึมเศร้า

      Criterion validity มีอยู่ 2 แบบ ได้แก่:

      1. Concurrent validity: ดูว่าแบบทดสอบมีความเกี่ยวข้องกับเกณฑ์ที่เกิดขึ้นในเวลาเดียวกันไหม (เช่น คะแนนสอบวันนี้)
      2. Predictive validity (aka incremental validity): ดูว่า แบบทดสอบมีความเกี่ยวข้องกับเกณฑ์ที่จะเกิดขึ้นในอนาคตไหม (เช่น คะแนนสอบในอีก 2 เดือนข้างหน้า)

      เช่นเดียวกับ construct validity ยิ่งเรามี concurrent validity และ predictive validity มากเท่าไรก็ยิ่งดี เพราะจะทำให้เรายิ่งมั่นใจในแบบทดสอบมากขึ้น

      และเช่นเดียวกับ construct validity เรามักใช้ correlation ในการประเมิน criterion validity ซึ่งหมายความว่า ยิ่ง correlation สูงก็ยิ่งมี criterion validity สูง


      💪 Summary

      ในบทความนี้ เราได้ไปทำความรู้จักกับ 2 ลักษณะที่ช่วยให้เราประเมินประสิทธิภาพของแบบทดสอบทางจิตวิทยาได้ ซึ่งได้แก่:

      ลักษณะที่ 1. Reliability หรือ ความเสถียรของคะแนนแบบทดสอบ ซึ่งมี 3 ประเภท ได้แก่:

      TypeDescription
      Test-retest reliabilityความเสถียรตามมิติเวลา
      Internal consistencyความเสถียรระหว่างข้อคำถาม
      Alternate form reliabilityความเสถียรระหว่างต้นฉบับและ alternate form

      ลักษณะที่ 2. Validity ซึ่งบอกว่า แบบทดสอบวัดสิ่งที่ต้องการวัดได้ขนาดไหน และแบ่งได้เป็น 2 กลุ่มใหญ่ ได้แก่:

      กลุ่มที่ 1. Opinion-based approach หรือ validity ตามความเห็น:

      TypeDescription
      Face validityValidity ตามความเห็นของคนทั่วไป
      Content validityValidity ตามความเห็นของผู้เชี่ยวชาญ

      กลุ่มที่ 2. Empirical approach หรือ validity ที่มีหลักฐานเชิงประจักษ์:

      Construct validity:

      TypeDescription
      Convergent validityความสัมพันธ์ระหว่างแบบทดสอบกับปัจจัยที่ควรเกี่ยวข้อง
      Divergent validityความสัมพันธ์ระหว่างแบบทดสอบกับปัจจัยที่ไม่ควรเกี่ยวข้อง

      Criterion validity:

      TypeDescription
      Concurrent validityความสัมพันธ์ระหว่างแบบทดสอบกับเกณฑ์ในปัจจุบัน
      Predictive validityความสัมพันธ์ระหว่างแบบทดสอบกับเกณฑ์ในอนาคต

      👀 See for Yourself: Is 16Personalities Reliable & Valid?

      ตอนนี้ เรารู้จักกับ reliability และ validity แล้ว และสามารถประเมินประสิทธิภาพของแบบทดสอบทางจิตวิทยาได้แล้ว

      แบบทดสอบต่าง ๆ มักจะรายงานผลการทดสอบ reliability และ validity ไว้ ดังนั้น เราสามารถประเมินประสิทธิภาพของแบบทดสอบได้โดยไม่ต้องทำการทดสอบเอง

      ถ้าแบบทดสอบใดที่ไม่มีการรายงานค่าเหล่านี้ เราสามารถตั้งคำถามได้ว่าแบบทดสอบสามารถใช้งานได้จริงหรือไม่

      เราสามารถดูตัวอย่างการรายงาน reliability และ validity ได้จากรายงานของ 16personalities ซึ่งประกอบ:

      1. Internal consistency
      2. Test-retest reliability
      3. Discriminant (divergent) validity

      ใครที่ลองอ่านรายงานของ 16personalities สามารถทิ้งคอมเม้นท์ไว้ได้ว่า แบบทดสอบนี้น่าเชื่อถือแค่ไหน

      .

      (ใครที่ยังไม่ได้ดูรายงาน 16personalities ให้ข้ามบรรทัดล่างไปก่อนนะครับ 😁)

      (Note: รายงานไม่ได้ระบุ validity ประเภทอื่น ๆ ไว้ ทำให้เราไม่รู้ว่า 16personalities ประเมิน 4 มิติของบุคลิกภาพตามที่ออกแบบไว้หรือไม่)


      📚 Further Reading

      สำหรับคนที่สนใจอ่านเพิ่มเติมเกี่ยว reliability และ validity สามารถอ่าน

      • Ashton (2018): บทเรียนเกี่ยวกับ reliability และ validity เบื้องต้น
      • Geisinger (2013): บทเรียนเกี่ยวกับ reliability เชิงลึก
      • Sireci และ Sukin (2013): บทเรียนเกี่ยวกับ validity เชืงลึก
      • Part II และ III ของ Furr และ Bacharach (2014): บทเรียนเชิงทฤษฎีและสถิติของ reliability และ validity

      📃 References

      • Ashton, M. C. (2018). Basic concepts in psychological measurement. In M. C. Ashton (Ed.), Individual differences and personality (3rd ed., pp. 1–28). Academic Press. https://doi.org/10.1016/B978-0-12-809845-5.00001-9
      • Furr, R. M., & Bacharach, V. R. (2014). Psychometrics: An introduction (2nd ed.). Sage.
      • Geisinger, K. F. (2013). Reliability. In K. F. Geisinger, B. A. Bracken, J. F. Carlson, J. I. C. Hansen, N. R. Kuncel, S. P. Reise, & M. C. Rodriguez (Eds.), APA handbook of testing and assessment in psychology, Vol. 1. Test theory and testing and assessment in industrial and organizational psychology (pp. 21–42). American Psychological Association. https://doi.org/10.1037/14047-002
      • Goldberg, E. (2023, March 5). The $2 billion question of who you are at work. The New York Times. https://www.nytimes.com/2023/03/05/business/remote-work-personality-tests.html
      • Leikvoll, V. (2022, September 14). 80% of Fortune 500 companies use personality tests, but are they ethical? Leaders. https://leaders.com/articles/business/personality-tests/
      • Rindskopf, D. (2001). Reliability: Measurement. In N. J. Smelser & P. B. Baltes (Eds.), International encyclopedia of the social & behavioral sciences (pp. 13023–13028). Pergamon. https://doi.org/10.1016/B0-08-043076-7/00722-1
      • Sireci, S. G., & Sukin, T. (2013). Test validity. In K. F. Geisinger, B. A. Bracken, J. F. Carlson, J. I. C. Hansen, N. R. Kuncel, S. P. Reise, & M. C. Rodriguez (Eds.), APA handbook of testing and assessment in psychology, Vol. 1. Test theory and testing and assessment in industrial and organizational psychology (pp. 61–84). American Psychological Association. https://doi.org/10.1037/14047-004

      ✅ R Book for Psychologists: หนังสือภาษา R สำหรับนักจิตวิทยา

      📕 ขอฝากหนังสือเล่มแรกในชีวิตด้วยนะครับ 😆

      🙋 ใครที่กำลังเรียนจิตวิทยาหรือทำงานสายจิตวิทยา และเบื่อที่ต้องใช้ software ราคาแพงอย่าง SPSS และ Excel เพื่อทำข้อมูล

      💪 ผมขอแนะนำ R Book for Psychologists หนังสือสอนใช้ภาษา R เพื่อการวิเคราะห์ข้อมูลทางจิตวิทยา ที่เขียนมาเพื่อนักจิตวิทยาที่ไม่เคยมีประสบการณ์เขียน code มาก่อน

      ในหนังสือ เราจะปูพื้นฐานภาษา R และพาไปดูวิธีวิเคราะห์สถิติที่ใช้บ่อยกัน เช่น:

      • Correlation
      • t-tests
      • ANOVA
      • Reliability
      • Factor analysis

      🚀 เมื่ออ่านและทำตามตัวอย่างใน R Book for Psychologists ทุกคนจะไม่ต้องพึง SPSS และ Excel ในการทำงานอีกต่อไป และสามารถวิเคราะห์ข้อมูลด้วยตัวเองได้ด้วยความมั่นใจ

      แล้วทุกคนจะแปลกใจว่า ทำไมภาษา R ง่ายขนาดนี้ 🙂‍↕️

      👉 สนใจดูรายละเอียดหนังสือได้ที่ meb:

    • สรุปวิธีสร้างงานเขียนจาก 0 สำหรับนักออกแบบและผู้ที่ต้องการพัฒนาทักษะการเขียน จากหนังสือ Writing Is Not Magic, It’s Design โดย João Batalheiro Ferreira

      สรุปวิธีสร้างงานเขียนจาก 0 สำหรับนักออกแบบและผู้ที่ต้องการพัฒนาทักษะการเขียน จากหนังสือ Writing Is Not Magic, It’s Design โดย João Batalheiro Ferreira

      Writing Is Not Magic, It’s Design เป็นหนังสือของ João Batalheiro Ferreira ซึ่งแนะนำแนวคิดการเขียนสำหรับนักออกแบบ (designer) ซึ่งมัก “คิดเป็นภาพ” ได้ดีกว่า “คิดเป็นตัวหนังสือ”

      แม้ว่า Writing Is Not Magic, It’s Design จะถูกเขียนมาให้นักออกแบบ แต่แนวคิดในหนังสือสามารถปรับใช้ได้กับทุกคนที่ต้องการพัฒนาทักษะการเขียนของตัวเอง โดยเฉพาะการเขียน non-fiction อย่างเขียน blog และบทความ

      ในบทความนี้ เราจะมาสรุปเนื้อหาของ Writing Is Not Magic, It’s Design ใน 2 ส่วน กัน:

      1. Writing Is …: การเขียนคืออะไร?
      2. Writing Method: กรอบแนวคิดในการออกแบบงานเขียนอย่างมีประสิทธิภาพ

      ถ้าพร้อมแล้ว ไปเริ่มกันเลย


      1. ✍️ Part I. Writing Is …
      2. 🖋️ Part II. Writing Method
        1. ⚛️ 1. Modular Writing
        2. 🪄 2. Writing Stages
          1. 🗒️ N for Note
          2. 🗺️ O for Organise
          3. ✒️ D for Draft
          4. 🔎 E for Edit
        3. 💪 Writing Method = Modular Writing + Writing Stages
      3. 🤩 Deep Noting Notion Template


      ✍️ Part I. Writing Is …

      การเขียนในมุมมองของ João สรุปได้เป็น 4 ข้อ ได้แก่:

      1. … Skill: การเขียนเป็นทักษะ นั่นคือ ทุกคนสามารถเรียนรู้และฝึกฝนได้ การเขียนได้ดีไม่จำเป็นต้องใช้พรสรรค์ แต่ต้องใช้ความรู้ ความเข้าใจ และการฝึกฝนอย่างมีหลักการ
      2. … Communication problem: จุดประสงค์หลักของการเขียน คือ การสื่อสารไอเดียของผู้เขียนไปยังผู้อ่าน ปัญหาหลักของงานเขียนที่ขาดประสิทธิภาพเกิดจากการที่ผู้เขียนไม่สามารถสื่อสารไอเดียอย่างที่เป็นไปถึงผู้อ่านได้ ถ้าเราอยากจะสร้างงานเขียนที่มีคุณภาพ เราต้องจะแก้ปัญหาการสื่อสารให้ได้
      3. … Creative process: งานเขียนเป็นงานสร้างสรรค์ (creative) ดังนั้น เช่นเดียวกับงานสร้างสรรค์อื่น ๆ ในการสร้างงานเขียน เราจะต้องทำตาม creative process และเลือกใช้เครื่องมือให้เหมาะสมกับแต่ละขั้นตอนใน process เราจะได้ทำความรู้จักกับ process นี้ในส่วนที่สอง
      4. … Thinking: สุดท้าย การเขียนคือการคิด การที่เราจะเขียนได้ดี เราจะต้องคิดให้ถี่ถ้วนก่อน และการที่เราจะคิดได้ เราจะต้องเขียนออกมา การเขียนไม่ใช่แค่การสื่อของความคิด แต่ยังเป็นเครื่องมือช่วยคิดที่กลมกลืนเป็นเนื้อเดียวกันกับการคิด เราจะเขียนได้ก็ต้องคิด และถ้าจะคิดได้ก็ต้องเขียน ทำให้เราไม่รู้ว่าอะไรมาก่อนกัน

      🖋️ Part II. Writing Method

      Writing method = Modular writing + Writing stages

      Writing method หรือวิธีการออกแบบงานเขียนประกอบด้วย 2 ส่วน ได้แก่:

      1. Modular writing
      2. Writing stages

      .

      ⚛️ 1. Modular Writing

      Module คือ หน่วยย่อยซึ่งสามารถนำมาประกอบเป็นสิ่งอื่น ๆ ได้

      ยกตัวอย่างเช่น:

      1. Atom ที่ประกอบกันเป็นสิ่งมีชีวิต
      2. Lego ที่ประกอบร่างเป็นของเล่นต่าง ๆ
      3. Engine ในรถยนต์ที่ทำให้รถรุ่นต่าง ๆ สามารถวิ่งไปข้างหน้าได้

      Modular writing เป็นแนวคิดในการจำแนกงานเขียนออกเป็น module หรือหน่วยย่อย ๆ ที่เราสามารถเขียนจบได้ในตัวเอง

      ยกตัวอย่างเช่น เราต้องการเขียนเกี่ยวกับ design thinking เราสามารถแบ่ง module ได้แบบนี้:

      • Module 1. What design thinking is
      • Module 2. History of design thinking
      • Module 3. Examples of design thinking
      • Module 4. Case studies of design thinking

      การแบ่งงานเขียนออกเป็น module มีข้อดี คือ:

      1. Overcome blank-page anxiety: ช่วยให้เราไม่รู้สึก overwhelmed เพราะแทนที่เราจะเริ่มจะ 0 (หน้าเปล่า) ไปถึง 100 (งานเขัยนฉบับสมบูรณ์) ในคราวเดียว เราค่อย ๆ เริ่มเขียนจากทีละส่วน และต่อยอดขึ้นไปเรื่อย ๆ
      2. Ease of restructuring: เราสามารถจัดโครงสร้างของงานเขียนได้ง่ายขึ้น เพราะแต่ละ module จบในตัวเอง เราสามารถสลับ module ไปมาเพื่อให้เข้ากับโครงร่างที่เราต้องการได้ โดยที่เราไม่ต้องแก้ไขงานเขียนใหม่ทั้งหมด (เราแค่ต้องแก้ส่วนเชื่อม module เท่านั้น)

      การเขียนแบบ modular writing มีอยู่ 3 ขั้นตอน:

      1. แยกงานเขียนออกเป็น module แต่ละ module จะต้องมีจุดเริ่มต้น เนื้อหา และจุดจบในตัวเอง
      2. เขียนแต่ละ module
      3. ประกอบ module ให้กลายเป็นงานเขียน

      .

      🪄 2. Writing Stages

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

      เพราะงานเขียนเป็นงานสร้างสรรค์ จึงไม่แปลกที่งานเขียนจะมีขั้นตอนการทำงานคล้ายกับ creative process ของการออกแบบ:

      WritingDesigning
      Gather informationGather information
      OutlineSketch
      DraftDesign specifications
      EditPrototyping

      จากตารางด้านบน เราสามารถสรุป writing stages ของการเขียนสามารถสรุปได้เป็น 4 ขั้นหลัก หรือ NODE ซึ่งได้แก่:

      1. N: Note
      2. O: Organise
      3. D: Draft
      4. E: Edit

      ในการเขียน เราจะต้องทำตามแต่ละ step ใน NODE แม้ว่าเราสามารถย้อนกลับไปใน step ก่อนหน้าได้ (เช่น ระหว่างที่เรากำลัง draft เราสามารถกลับไป organise ไอเดียที่เราต้องการนำเสนอได้) แต่เราไม่ควรข้าม step ได้ (เช่น edit งานเขียนก่อนที่จะ draft งานขึ้นมา) การทำเช่นนั้นจะทำให้งานเขียนเรามีรากฐานที่ไม่แข็งแรง เพราะแต่ละ step วางโครงสร้างให้กับ step ถัดไป

      .

      🗒️ N for Note

      ขั้นแรกของ NODE หรือ note หมายถึง การจัดเก็บไอเดียต่าง ๆ เพื่อให้เรามีคลังข้อมูลไว้ใช้เขียนในภายหลัง

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

      สำหรับขั้นนี้ของ NODE, João นำเสนอระบบ Deep Noting ซึ่งเป็นพัฒนามาจาก Zettelkasten ซึ่งเป็นระบบจัดการความรู้ที่มีประสิทธิภาพในสมัยก่อน

      Deep Noting ใช้ประโยชน์จากเครื่องมือ 2 อย่าง ได้แก่:

      1. กระดาษ (แนะนำให้ใช้ขนาด A7) และปากกา
      2. TXT file

      และมี 3 ขั้นตอนในการใช้งาน ได้แก่:

      1. Capture notes
      2. Review
      3. Deep notes

      โดยทั้ง 3 ขั้นตอนมีรายละเอียดดังนี้:

      ขั้นที่ 1. Capture notes คือ การจดข้อมูล ไอเดีย ความคิด quote ที่เราพบเจอในชีวิตประจำวันและรู้สึกว่าน่าสนใจลงบนกระดาษ โดยให้จด 1 ไอเดียต่อ 1 แผ่น รวมทั้งต้องโน้ตที่มาและสิ่งที่ทำให้เรานึกถึง (ถ้ามี)

      ยกตัวอย่างเช่น เราเจอ quote ที่น่าสนใจระหว่างอ่านหนังสือ เราอาจจะสร้าง capture note แบบนี้:

      “writing is easy. all you have to do is cross out the wrong words.” — mark twain. reminds of book “essentialism”

      ขั้นที่ 2. Review คือ นำ capture notes ที่เรารวบรวมได้มารีวิวทุกสัปดาห์ เพื่อเลือกเก็บไว้หรือทิ้งไป

      สำหรับ capture notes ที่เลือกเก็บไว้ เราจะปรับให้เป็น deep notes ต่อไป

      ขั้นที่ 3. Deep notes คือ capture notes ที่ถูกแปลงให้กลายเป็นข้อมูลที่เราจะเก็บเข้าคลังความรู้ของเรา โดยเราจะเก็บ deep notes ไว้ในรูปแบบ TXT files ซึ่งจัดเก็บอยู่ใน folder เดียวในคอมพิวเตอร์ของเรา

      (João แนะนำว่า เราไม่ควรแยก folder ย่อย เพราะจะทำให้เราหา TXT files ได้ยากขึ้น)

      เช่นเดียวกับ capture notes, เราจะเก็บ 1 ไอเดียต่อ 1 deep note (1 TXT file) โดย deep note จะประกอบไปด้วย 4 อย่าง ได้แก่:

      1. Idea: เราจะเขียนขยายความจาก capture note ว่าทำไมไอเดียนี้ถึงน่าสนใจ และไอเดียนี้มีความหมายกับเรายังไง
      2. Reference: ที่มาของไอเดีย (ถ้ามี เช่น อ่านจากหนังสือ X, ได้ยินจาก Y)
      3. Link to: อ้างอิงถึงไอเดียอื่น ๆ โดยใส่ชื่อ TXT file ที่เก็บไอเดียนั้นไว้ (ถ้ามี)
      4. Tags: ใส่ #hashtag เพื่อช่วยจับกลุ่มไอเดียต่าง ๆ เข้าด้วยกัน (เหมือน tweet ใน X)

      ยกตัวอย่างเช่น:

      “Writing is easy. All you have to do is cross out the wrong words.”

      Good writing isn’t about being wordy. It’s as much about picking the right words as cutting out what’s not essential.

      Reference: Mark Twain

      Link to: “write drunk, edit sober”

      #writing #editing

      Note: เพื่อช่วยให้เราจัดค้นหาไอเดียได้ เราสามารถสร้าง TXT file ขึ้นมาเพื่อเก็บ #hashtag ทั้งหมดที่เราเคยสร้างไว้ได้

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

      .

      🗺️ O for Organise

      หลังจากที่เรามีไอเดียของตัวเองแล้ว เราจะนำไอเดียมาจัดเรียง (organise) เพื่อสร้างแผนที่ที่จะ guide เราในการร่างงานเขียน (draft) ซึ่งเราทำได้ใน 3 ขั้นตอน ได้แก่:

      1. Print: ปริ้นต์ TXT files ที่มี #hashtag ที่เราสนใจออกมา (เช่น เราต้องการเขียนเกี่ยวกับ design thinking เราจะปริ้นต์ไฟล์ที่มี #designthinking ทั้งหมด รวมทั้ง #hashtag อื่น ๆ ที่เกี่ยวข้อง เช่น #designsprint #doublediamond)
      2. Group: จากนั้น เราจะจับไอเดียที่มีเป็นกลุ่มก้อน และตั้งชื่อให้กับกลุ่มไอเดีย (เช่น “history of design thinking”, “prototyping”, “user persona”)
      3. Organise: เราจะจัดเรียงกลุ่มไอเดียให้เป็นเรื่องราว (story) ที่เราต้องการ และตั้งไว้ในจุดที่เรามองเห็นได้ เพื่อใช้เป็นแผนที่นำทางในการเขียน

      .

      ✒️ D for Draft

      ในขั้นที่ 3 ของ NODE หรือ draft เราจะเริ่มร่างงานเขียนขึ้นมา โดยในขั้นนี้ เป้าหมายของเราคือการเขียนข้อมูลที่มีในหัวที่เราต้องการสื่อสารออกมาให้มากที่สุด โดยยังไม่ต้องสนใจความสวยงาม

      ในขั้นนี้ เราจะต้องทำ 2 อย่าง คือ:

      1. Elaborate: เขียนอธิบายไอเดียที่เราต้องการสื่อสารให้ผู้อ่านเข้าใจ เพราะจนถึงตอนนี้ ไอเดียของเราอยู่ในรูปแบบการเขียนที่เราเข้าใจได้คนเดียว (deep notes)
      2. Clarify: เขียนอธิบายความเชื่อมโยงระหว่างไอเดีย เพื่อให้ผู้อ่านเข้าใจความสัมพันธ์ระหว่างไอเดียต่าง ๆ ในงานเขียน

      Draft แรกของเราจะเป็นสิ่งที่เราสามารถใช้เก็บ feedback จากคนอื่น ๆ (เช่น ให้เพื่อนช่วยอ่าน) เพื่อนำมาปรับปรุงให้เป็นงานเขียนที่สมบูรณ์มากขึ้น

      .

      🔎 E for Edit

      สุดท้าย เราจะปรับแก้ (edit) ร่างงานเขียนของเรา เพื่อให้เป็นงานเขียนที่สมบูรณ์

      โดยในการแก้ไข เราสามารถทำได้ 2 อย่าง ได้แก่:

      1. Structuring (what และ where): แก้ไขโครงสร้างและลำดับการนำเสนอไอเดียต่าง ๆ (เช่น เราอาจนำ module เกี่ยวกับ case study ขึ้นมาก่อน module เกี่ยวกับนิยามของ design thinking เพื่อดึงดูดผู้อ่านมากขึ้น)
      2. Revising (how): แก้ไขการสะกดคำ การเลือกใช้คำ และรูปแบบประโยค โดยการแก้ไขจะต้องทำให้การสื่อสารไอเดียเป็นไปได้อย่างกระชับ (concise) และแม่นยำ (precise) มากขึ้น ถ้าคำหรือประโยคไหนที่ไม่ทำให้เกิด 2 อย่างนี้ ให้เราเลือกปรับแก้ในทันที

      .

      โดยสรุป writing stages มีอยู่ 4 ขั้นตอน หรือ NODE ซึ่งได้แก่:

      1. Note: จัดเก็บไอเดียต่าง ๆ
      2. Organise: จัดเรียงไอเดียให้เป็นเรื่องราว
      3. Draft: ร่างงานเขียนจากเรื่องราว
      4. Edit: แก้ไขร่างให้เป็นงานฉบับสมบูรณ์

      💪 Writing Method = Modular Writing + Writing Stages

      ตอนนี้ เราเรียนรู้ modular writing และ writing stages แล้ว

      ในการเขียน เราจะใช้ทั้ง 2 อย่างรวมกันเพื่อสร้างงานเขียนอย่างมีประสิทธิภาพใน 3 ขั้นตอน ได้แก่:

      1. แยกงานเขียนเป็น modules
      2. เขียนแต่ละ module โดยใช้ NODE
      3. ประกอบ modules เข้าด้วยกัน

      Writing method เป็นวิธีที่จะช่วยให้เราสร้างงานเขียนได้อย่างง่าย และไม่ต้องกังวลกับการเริ่มเขียนบนหน้าเปล่าอีกต่อไป


      🤩 Deep Noting Notion Template

      สำหรับคนที่ต้องการระบบ Deep Noting เพื่อจัดเก็บไอเดียไว้ต่อยอดสำหรับงานเขียนและโปรเจกต์อื่น ๆ สามารถซื้อ Deep Note template ได้ที่ Notion Marketplace