บทเรียนการใช้งาน dplyr ใน R: การผสานและรวมข้อมูล พร้อมตัวอย่าง
⚡ สรุปอย่างชาญฉลาด
dplyr เป็นแพ็กเกจที่รวมและเชื่อมข้อมูลเฟรมใน R โดยใช้คำสั่งสี่คำสั่ง ได้แก่ left_join(), right_join(), inner_join() และ full_join() จากนั้นแพ็กเกจ tidyr ที่ใช้งานร่วมกันจะปรับรูปร่างผลลัพธ์ที่เชื่อมแล้วโดยใช้ gather(), spread(), separate() และ unite()

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

หนึ่งในความท้าทายที่สำคัญที่สุดที่นักวิทยาศาสตร์ข้อมูลต้องเผชิญคือการจัดการข้อมูล ข้อมูลไม่เคยอยู่ในรูปแบบที่ต้องการเสมอไป นักวิทยาศาสตร์ข้อมูลจึงต้องใช้เวลาอย่างน้อยครึ่งหนึ่งในการทำความสะอาดและจัดการข้อมูล ซึ่งเป็นหนึ่งในงานที่สำคัญที่สุด หากกระบวนการจัดการข้อมูลไม่สมบูรณ์ แม่นยำ และเข้มงวด โมเดลก็จะไม่ทำงานอย่างถูกต้อง
R dplyr
R มีแพ็กเกจชื่อ dplyr ที่ใช้สำหรับแปลงข้อมูล แพ็กเกจนี้สร้างขึ้นจากชุดคำสั่งหลักไม่กี่คำสั่ง ได้แก่ filter(), select(), arrange(), mutate() และ summarise() รวมถึงฟังก์ชันการรวมข้อมูล (join functions) เมื่อข้อมูลพร้อมแล้ว ggplot2 ก็สามารถแสดงผลออกมาเป็นภาพได้
เราจะเรียนรู้วิธีการใช้แพ็กเกจ dplyr เพื่อจัดการข้อมูล กรอบข้อมูลหากยังไม่ได้ติดตั้ง R โปรดทำตามขั้นตอนต่อไปนี้ ขั้นตอนการตั้งค่า R และ RStudioจากนั้นเรียกใช้คำสั่ง install.packages(“dplyr”)
ผสานข้อมูลด้วย dplyr
dplyr เป็นวิธีที่ดีและสะดวกในการรวมชุดข้อมูล เราอาจมีแหล่งข้อมูลอินพุตมากมาย และเมื่อถึงจุดหนึ่ง เราจำเป็นต้องรวมเข้าด้วยกัน การรวมกับ dplyr จะเพิ่มตัวแปรทางด้านขวาของชุดข้อมูลดั้งเดิม
dplyr เข้าร่วม
ต่อไปนี้คือการเชื่อมต่อข้อมูลที่สำคัญสี่ประเภทที่ใช้ใน dplyr เพื่อรวมชุดข้อมูลสองชุดเข้าด้วยกัน การเชื่อมต่อทั้งสี่ประเภทนี้ใช้พารามิเตอร์เดียวกัน คือ ตารางทั้งสองและคีย์ และแตกต่างกันเพียงแค่แถวที่ไม่ตรงกันที่จะยังคงอยู่:
| ฟังก์ชัน | วัตถุประสงค์ | ข้อโต้แย้ง | หลายปุ่ม |
|---|---|---|---|
| left_join() | รวมสองชุดข้อมูล เก็บข้อสังเกตทั้งหมดจากตารางต้นทาง | x, y, by = “ID” | x, y, by = c(“ID”, “ID2”) |
| right_join() | รวมสองชุดข้อมูล เก็บข้อสังเกตทั้งหมดจากตารางปลายทาง | x, y, by = “ID” | x, y, by = c(“ID”, “ID2”) |
| inner_join() | รวมชุดข้อมูลสองชุดเข้าด้วยกัน ตัดแถวที่ไม่ตรงกันออกทั้งหมด | x, y, by = “ID” | x, y, by = c(“ID”, “ID2”) |
| เต็ม_เข้าร่วม() | รวมชุดข้อมูลสองชุดเข้าด้วยกัน โดยคงข้อมูลทั้งหมดไว้ | x, y, by = “ID” | x, y, by = c(“ID”, “ID2”) |
คำกริยาทั้งสี่คำนี้เชื่อมโยงกับการเชื่อมต่อแบบ LEFT, RIGHT, INNER และ FULL OUTER ของ SQL.R พื้นฐานให้ผลลัพธ์เดียวกันผ่านอาร์กิวเมนต์ all, all.x และ all.y ของ ผสาน().
เราจะศึกษาประเภทการเชื่อมต่อทั้งหมดผ่านตัวอย่างง่ายๆ
ขั้นแรก เราสร้างชุดข้อมูลสองชุด ตารางที่ 1 ประกอบด้วยตัวแปรสองตัว คือ ID และ y ในขณะที่ตารางที่ 2 รวบรวม ID และ z ในแต่ละสถานการณ์ เราจำเป็นต้องมี คีย์คู่ ตัวแปร. ในกรณีของเรา ID คือของเรา สำคัญ ตัวแปร ฟังก์ชันนี้จะค้นหาค่าที่เหมือนกันในทั้งสองตารางและผูกค่าที่ส่งคืนไปยังด้านขวาของตารางที่ 1 รูปด้านล่างแสดงตารางทั้งสองวางเคียงข้างกัน
library(dplyr) df_primary <- tribble( ~ID, ~y, "A", 5, "B", 5, "C", 8, "D", 0, "F", 9) df_secondary <- tribble( ~ID, ~z, "A", 30, "B", 21, "C", 22, "D", 25, "E", 29)
dplyr left_join()
วิธีที่พบได้บ่อยที่สุดในการรวมชุดข้อมูลสองชุดคือการใช้ฟังก์ชัน left_join() ภาพด้านล่างแสดงให้เห็นว่าคู่คีย์ตรงกับแถว A, B, C และ D ในขณะที่ E และ F ยังคงอยู่ ด้วย left_join() เราจะเก็บแถวทั้งหมดในตารางต้นฉบับและละเว้นแถวที่ไม่มีคู่คีย์ในตารางปลายทาง ในตัวอย่างของเรา ค่า E ไม่มีอยู่ในตารางที่ 1 ดังนั้นแถวนั้นจึงถูกลบออก ค่า F มาจากตารางต้นทาง ดังนั้นจึงถูกเก็บไว้หลังจาก left_join() และส่งคืนค่า NA ในคอลัมน์ z
ตัวอย่างของ dplyr left_join()
แผนภาพด้านล่างแสดงให้เห็นถึงสิ่งที่เกิดขึ้นระหว่างการดำเนินการ left_join()
left_join(df_primary, df_secondary, by ='ID')
Output:
## # A tibble: 5 x 3 ## ID y.x y.y ## <chr> <dbl> <dbl> ## 1 A 5 30 ## 2 B 5 21 ## 3 C 8 22 ## 4 D 0 25 ## 5 F 9 NA
โปรดทราบว่าเมื่อทั้งสองตารางมีคอลัมน์ที่มีชื่อเดียวกัน dplyr จะแยกแยะความแตกต่างโดยใช้คำต่อท้าย .x และ .y ดังที่แสดงไว้ข้างต้น
dplyr right_join()
ฟังก์ชัน right_join() ทำงานเหมือนกับ left_join() ทุกประการ ข้อแตกต่างเพียงอย่างเดียวคือแถวที่ถูกทิ้ง ค่า E ที่มีอยู่ในกรอบข้อมูลปลายทางมีอยู่ในตารางใหม่ และรับค่า NA สำหรับคอลัมน์ y
ตัวอย่างของ dplyr right_join()
แผนภาพด้านล่างแสดงภาพสะท้อนในกระจก
right_join(df_primary, df_secondary, by = 'ID')
Output:
## # A tibble: 5 x 3 ## ID y.x y.y ## <chr> <dbl> <dbl> ## 1 A 5 30 ## 2 B 5 21 ## 3 C 8 22 ## 4 D 0 25 ## 5 E NA 29
dplyr inner_join()
เมื่อข้อมูลที่ไม่ตรงกันไม่มีประโยชน์เลย เราสามารถส่งคืนได้ เพียง แถวที่มีอยู่ใน ทั้งสอง ชุดข้อมูล นี่คือตัวเลือกที่เหมาะสมเมื่อเราต้องการชุดข้อมูลที่สมบูรณ์และไม่ต้องการเติมค่าที่หายไปด้วยค่าเฉลี่ยหรือค่ามัธยฐาน
ฟังก์ชัน inner_join() จะเข้ามาช่วยในกรณีนี้ โดยจะตัดแถวที่ไม่ตรงกันออกจากทั้งสองด้าน
ตัวอย่างของ dplyr inner_join()
แผนภาพด้านล่างแสดงให้เห็นถึงรหัสประจำตัวทั้งสี่ที่ยังคงอยู่หลังจากการเชื่อมต่อเสร็จสิ้น
inner_join(df_primary, df_secondary, by ='ID')
Output:
## # A tibble: 4 x 3 ## ID y.x y.y ## <chr> <dbl> <dbl> ## 1 A 5 30 ## 2 B 5 21 ## 3 C 8 22 ## 4 D 0 25
dplyr full_join()
สุดท้าย ฟังก์ชัน full_join() จะเก็บข้อมูลทั้งหมดไว้ และแทนที่ค่าที่หายไปด้วย NA
ตัวอย่างของ dplyr full_join()
แผนภาพด้านล่างแสดงให้เห็นว่า ID ทั้งหมดจากทั้งสองตารางยังคงอยู่รอดจากการเชื่อมต่อ (join)
full_join(df_primary, df_secondary, by = 'ID')
Output:
## # A tibble: 6 x 3 ## ID y.x y.y ## <chr> <dbl> <dbl> ## 1 A 5 30 ## 2 B 5 21 ## 3 C 8 22 ## 4 D 0 25 ## 5 F 9 NA ## 6 E NA 29
หลายคู่คีย์
สุดท้ายนี้ เราสามารถมีคีย์หลายตัวในชุดข้อมูลของเราได้ ลองพิจารณาชุดข้อมูลต่อไปนี้ ซึ่งเรามีปีและรายการสินค้าที่ลูกค้าซื้อ ภาพหน้าจอด้านล่างแสดงตารางสองตารางและคอลัมน์ ID และปีที่ใช้ระบุแถว
ถ้าเราเชื่อมตารางทั้งสองโดยใช้ ID เพียงอย่างเดียว ทุกปีจะถูกจับคู่กับทุกปี และจำนวนแถวจะเพิ่มขึ้นอย่างมาก เพื่อแก้ไขปัญหานี้ เราสามารถส่งตัวแปรคู่คีย์สองตัวแปรได้ นั่นคือ ID และปี ซึ่งปรากฏอยู่ในทั้งสองชุดข้อมูล เราสามารถใช้โค้ดต่อไปนี้เพื่อรวมตารางที่ 1 และตารางที่ 2:
df_primary <- tribble( ~ID, ~year, ~items, "A", 2015,3, "A", 2016,7, "A", 2017,6, "B", 2015,4, "B", 2016,8, "B", 2017,7, "C", 2015,4, "C", 2016,6, "C", 2017,6) df_secondary <- tribble( ~ID, ~year, ~prices, "A", 2015,9, "A", 2016,8, "A", 2017,12, "B", 2015,13, "B", 2016,14, "B", 2017,6, "C", 2015,15, "C", 2016,15, "C", 2017,13) left_join(df_primary, df_secondary, by = c('ID', 'year'))
Output:
## # A tibble: 9 x 4 ## ID year items prices ## <chr> <dbl> <dbl> <dbl> ## 1 A 2015 3 9 ## 2 A 2016 7 8 ## 3 A 2017 6 12 ## 4 B 2015 4 13 ## 5 B 2016 8 14 ## 6 B 2017 7 6 ## 7 C 2015 4 15 ## 8 C 2016 6 15 ## 9 C 2017 6 13
ตั้งแต่ dplyr เวอร์ชัน 1.1.0 (มกราคม 2023) สามารถเขียนคีย์เดียวกันได้ในรูปแบบ join_by(ID, year) และ dplyr จะแจ้งเตือนเกี่ยวกับการจับคู่แบบ many-to-many ที่ไม่คาดคิด เนื่องจาก dplyr เวอร์ชัน 1.1.0 เข้าร่วมการประกาศ อธิบาย
ฟังก์ชั่นการล้างข้อมูลใน R
การรวมตารางช่วยแก้ปัญหาได้เพียงครึ่งเดียว เพราะตารางที่รวมกันแล้วยังต้องได้รับการจัดรูปแบบใหม่ ต่อไปนี้คือฟังก์ชันสำคัญสี่อย่างในการจัดระเบียบ (ทำความสะอาด) ข้อมูล:
| ฟังก์ชัน | วัตถุประสงค์ | ข้อโต้แย้ง |
|---|---|---|
| รวมตัว() | แปลงข้อมูลจากกว้างไปยาว | (ข้อมูล คีย์ ค่า na.rm = FALSE) |
| การแพร่กระจาย() | แปลงข้อมูลจากยาวไปเป็นกว้าง | (ข้อมูล คีย์ ค่า) |
| แยก() | แยกตัวแปรหนึ่งตัวออกเป็นสองตัว | (data, col, into, sep = “”, remove = TRUE) |
| รวมกัน() | รวมตัวแปรสองตัวเข้าเป็นตัวแปรเดียว | (data, col, conc, sep = “”, remove = TRUE) |
หมายเหตุเกี่ยวกับเวอร์ชัน: ฟังก์ชัน gather() และ spread() ถูกแทนที่ด้วย pivot_longer() และ pivot_wider() ใน tidyr เวอร์ชัน 1.0.0 และฟังก์ชัน separate() ถูกแทนที่ด้วยตระกูล separate_wider_delim() ใน tidyr เวอร์ชัน 1.3.0 ฟังก์ชันที่ถูกแทนที่ยังคงทำงานได้ ดังนั้นตัวอย่างด้านล่างจึงใช้งานได้ แต่โค้ดใหม่ควรเลือกใช้ตระกูลฟังก์ชันที่ใหม่กว่าตามที่แสดงในตาราง ภาพประกอบแบบหมุนได้ของ tidyr. unite() ยังคงเป็นปัจจุบัน
เราใช้แพ็กเกจ tidyr ซึ่งเป็นส่วนหนึ่งของชุด tidyverse สำหรับการจัดการ การทำความสะอาด และการแสดงภาพข้อมูล หากติดตั้ง R พร้อมกับ Anaconda แล้ว แพ็กเกจนี้จะพร้อมใช้งานอยู่แล้ว https://anaconda.org/r/r-tidyr.
หากยังไม่ได้ติดตั้ง ให้ป้อนคำสั่งต่อไปนี้เพื่อติดตั้ง tidyr:
install.packages("tidyr")
รวมตัว()
วัตถุประสงค์ของฟังก์ชัน gather() คือการแปลงข้อมูลจากรูปแบบกว้างเป็นรูปแบบยาว
วากยสัมพันธ์
gather(data, key, value, na.rm = FALSE) Arguments: -data: The data frame used to reshape the dataset -key: Name of the new column created -value: Select the columns used to fill the key column -na.rm: Remove missing values. FALSE by default
ตัวอย่าง
ด้านล่างนี้ เราสามารถเห็นภาพแนวคิดของเรชาได้ping จากตารางกว้างไปเป็นตารางยาว เราต้องการสร้างคอลัมน์เดียวชื่อ "การเติบโต" โดยให้ค่าของตัวแปรไตรมาสอยู่ในคอลัมน์นั้น รูปด้านล่างแสดงตารางกว้างทางด้านซ้ายและตารางยาวที่ปรับรูปร่างใหม่ทางด้านขวา
library(tidyr) # Create a messy dataset messy <- data.frame( country = c("A", "B", "C"), q1_2017 = c(0.03, 0.05, 0.01), q2_2017 = c(0.05, 0.07, 0.02), q3_2017 = c(0.04, 0.05, 0.01), q4_2017 = c(0.03, 0.02, 0.04)) messy
Output:
## country q1_2017 q2_2017 q3_2017 q4_2017 ## 1 A 0.03 0.05 0.04 0.03 ## 2 B 0.05 0.07 0.05 0.02 ## 3 C 0.01 0.02 0.01 0.04
# Reshape the data
tidier <-messy %>%
gather(quarter, growth, q1_2017:q4_2017)
tidier
Output:
## country quarter growth ## 1 A q1_2017 0.03 ## 2 B q1_2017 0.05 ## 3 C q1_2017 0.01 ## 4 A q2_2017 0.05 ## 5 B q2_2017 0.07 ## 6 C q2_2017 0.02 ## 7 A q3_2017 0.04 ## 8 B q3_2017 0.05 ## 9 C q3_2017 0.01 ## 10 A q4_2017 0.03 ## 11 B q4_2017 0.02 ## 12 C q4_2017 0.04
ในฟังก์ชัน gather() เราสร้างตัวแปรใหม่สองตัวคือ quarter และ growth เนื่องจากชุดข้อมูลเดิมของเรามีตัวแปรกลุ่มเพียงตัวเดียวคือ country และคู่คีย์-ค่า ใน tidyr เวอร์ชัน 1.0.0 และเวอร์ชันที่ใหม่กว่า การปรับรูปร่างแบบเดียวกันนี้เขียนได้เป็น pivot_longer(messy, cols = q1_2017:q4_2017, names_to = “quarter”, values_to = “growth”)
การแพร่กระจาย()
ฟังก์ชัน spread() ทำงานตรงข้ามกับฟังก์ชัน gather()
วากยสัมพันธ์
spread(data, key, value) arguments: data: The data frame used to reshape the dataset key: Column to reshape long to wide value: Rows used to fill the new column
ตัวอย่าง
เราสามารถปรับโครงสร้างชุดข้อมูลที่เป็นระเบียบเรียบร้อยให้กลับไปเป็นชุดข้อมูลที่ยุ่งเหยิงได้อีกครั้งโดยใช้ spread()
# Reshape the data
messy_1 <- tidier %>%
spread(quarter, growth)
messy_1
Output:
## country q1_2017 q2_2017 q3_2017 q4_2017 ## 1 A 0.03 0.05 0.04 0.03 ## 2 B 0.05 0.07 0.05 0.02 ## 3 C 0.01 0.02 0.01 0.04
รูปแบบที่ทันสมัยกว่าคือ pivot_wider(tidier, names_from = quarter, values_from = growth)
แยก()
ฟังก์ชัน separate() จะแบ่งคอลัมน์ออกเป็นสองส่วนโดยใช้ตัวคั่น ฟังก์ชันนี้มีประโยชน์ในกรณีที่ตัวแปรเป็นวันที่ การวิเคราะห์ของเราอาจต้องการเน้นที่เดือนและปี และเราต้องการแยกคอลัมน์นั้นออกเป็นสองตัวแปรใหม่
วากยสัมพันธ์
separate(data, col, into, sep= "", remove = TRUE) arguments: -data: The data frame used to reshape the dataset -col: The column to split -into: The name of the new variables -sep: Indicates the symbol used that separates the variable, i.e.: "-", "_", "&" -remove: Remove the old column. By default sets to TRUE.
ตัวอย่าง
เราสามารถแยกไตรมาสออกจากปีในชุดข้อมูลที่เป็นระเบียบยิ่งขึ้นได้โดยใช้ฟังก์ชัน Separate()
separate_tidier <-tidier %>% separate(quarter, c("Qrt", "year"), sep ="_") head(separate_tidier)
Output:
## country Qrt year growth ## 1 A q1 2017 0.03 ## 2 B q1 2017 0.05 ## 3 C q1 2017 0.01 ## 4 A q2 2017 0.05 ## 5 B q2 2017 0.07 ## 6 C q2 2017 0.02
รวมกัน()
ฟังก์ชัน unite() จะรวมสองคอลัมน์เข้าเป็นคอลัมน์เดียว
วากยสัมพันธ์
unite(data, col, conc ,sep= "", remove = TRUE) arguments: -data: The data frame used to reshape the dataset -col: Name of the new column -conc: Name of the columns to concatenate -sep: Indicates the symbol used that unites the variable, i.e: "-", "_", "&" -remove: Remove the old columns. By default, sets to TRUE
ตัวอย่าง
ในตัวอย่างข้างต้น เราแยกไตรมาสออกจากปี แล้วถ้าเราต้องการรวมเข้าด้วยกันล่ะ? เราใช้โค้ดต่อไปนี้:
unit_tidier <- separate_tidier %>%
unite(Quarter, Qrt, year, sep ="_")
head(unit_tidier)
Output:
## country Quarter growth ## 1 A q1_2017 0.03 ## 2 B q1_2017 0.05 ## 3 C q1_2017 0.01 ## 4 A q2_2017 0.05 ## 5 B q2_2017 0.07 ## 6 C q2_2017 0.02
โครงสร้างข้อมูลที่ปรับรูปแบบใหม่พร้อมแล้วสำหรับขั้นตอนการสร้างแบบจำลองซึ่งจะกล่าวถึงในส่วนที่เหลือของบทความนี้ ชุดบทเรียน R.







