0Pricing
R Academy · บทเรียน

การซ้อนและคลายการซ้อนดาต้าเฟรม

ใช้ nest() และ unnest() เพื่อทำงานกับคอลัมน์รายการในกระบวนงาน tidy

การซ้อนและคลายการซ้อนดาต้าเฟรม เป็นบทเรียน R Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน R Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส R Academy มีบทเรียนทั้งหมด 4 บทเรียน

คอลัมน์แบบรายการและข้อมูลซ้อนกัน

คอลัมน์แบบรายการ คือคอลัมน์ใน data frame ที่แต่ละเซลล์เก็บออบเจ็กต์ของ R ไว้ (เวกเตอร์ data frame โมเดล หรือรายการ) ทำให้สามารถเก็บข้อมูลย่อยที่มีโครงสร้างไว้ร่วมกับคอลัมน์อื่นได้ และรองรับกระบวนการทำงานแบบแยกตามกลุ่มที่มีประสิทธิภาพ

library(tidyr)
library(dplyr)

# A simple data frame with a list-column
df <- data.frame(
  group = c('A','B','C'),
  n = c(3, 2, 4)
)
df$values <- list(c(1,2,3), c(4,5), c(6,7,8,9))

print(df)
print(df$values[[1]])  # Access the first list element

nest() — การสร้าง data frame แบบซ้อนกัน

nest(df, data = c(col1, col2)) จัดกลุ่มแถวตามคอลัมน์ที่ไม่ได้ซ้อนกัน แล้วบรรจุคอลัมน์ที่ระบุลงในคอลัมน์แบบรายการซึ่งประกอบด้วย data frame โดยแต่ละกลุ่มมีหนึ่งแถว และแต่ละแถวมี data frame ขนาดย่อมของกลุ่มนั้น

library(tidyr)
library(dplyr)

df <- data.frame(
  region = c('East','East','East','West','West'),
  month = c(1,2,3,1,2),
  sales = c(100,120,110,200,190)
)

nested <- df %>%
  nest(data = c(month, sales))

print(nested)
print(nested$data[[1]])  # East region's data

nest() กับ group_by()

รูปแบบที่ใช้บ่อยที่สุดคือ ใช้ group_by() แล้วตามด้วย nest() เพื่อสร้างหนึ่งแถวต่อหนึ่งกลุ่ม โดยบรรจุคอลัมน์ที่เหลือทั้งหมดไว้ในคอลัมน์แบบรายการ data ซึ่งเทียบเท่ากับ nest(.by = group_col) ใน tidyr รุ่นใหม่กว่า

library(tidyr)
library(dplyr)

df <- data.frame(
  category = c('A','A','A','B','B','C','C','C','C'),
  x = c(1,2,3,4,5,6,7,8,9),
  y = c(2,4,3,8,7,5,6,9,8)
)

nested <- df %>%
  group_by(category) %>%
  nest()

print(nested)
cat('Rows per category B:', nrow(nested$data[[2]]))

map() กับ data frame แบบซ้อนกัน

เมื่อซ้อนข้อมูลแล้ว ให้ใช้ purrr::map() เพื่อใช้ฟังก์ชันกับ data frame ขนาดย่อมแต่ละรายการ ฟังก์ชันจะได้รับ data frame ครั้งละหนึ่งรายการ และผลลัพธ์จะกลายเป็นคอลัมน์แบบรายการใหม่ ซึ่งมักเป็นโมเดลที่ปรับให้เข้ากับข้อมูลแล้ว

library(tidyr)
library(dplyr)
library(purrr)

df <- data.frame(
  group = c('A','A','A','B','B','B'),
  x = c(1,2,3,1,2,3),
  y = c(2.1,4.0,5.9,3.2,5.8,9.1)
)

models <- df %>%
  group_by(group) %>%
  nest() %>%
  mutate(model = map(data, ~lm(y ~ x, data = .x)))

print(models)

การดึงผลลัพธ์ของโมเดลด้วย map()

หลังจากปรับโมเดลแยกตามกลุ่มแล้ว ให้ใช้ map() ร่วมกับฟังก์ชันอย่าง broom::tidy() หรือ coef() เพื่อดึงผลลัพธ์จากแต่ละโมเดล ผลลัพธ์จะเป็นคอลัมน์แบบรายการอีกคอลัมน์หนึ่ง ซึ่งภายหลังสามารถคลายการซ้อนได้

library(tidyr)
library(dplyr)
library(purrr)

df <- data.frame(
  group = c('A','A','A','B','B','B'),
  x = c(1,2,3,1,2,3),
  y = c(2.1,4.0,5.9,3.2,5.8,9.1)
)

df %>%
  group_by(group) %>%
  nest() %>%
  mutate(
    model = map(data, ~lm(y ~ x, data = .x)),
    r_squared = map_dbl(model, ~summary(.x)$r.squared),
    intercept = map_dbl(model, ~coef(.x)[1]),
    slope = map_dbl(model, ~coef(.x)[2])
  ) %>%
  select(group, r_squared, intercept, slope)

unnest() — ขยายคอลัมน์แบบรายการ

unnest(df, cols = data) เป็นการทำงานย้อนกลับของ nest() โดยขยายคอลัมน์แบบรายการกลับเป็นคอลัมน์ปกติ และทำซ้ำคอลัมน์ตัวระบุตามความจำเป็น ใช้ cols เพื่อระบุคอลัมน์แบบรายการที่ต้องการคลายการซ้อน

library(tidyr)
library(dplyr)

nested <- data.frame(
  region = c('East','West')
)
nested$data <- list(
  data.frame(month=1:3, sales=c(100,120,110)),
  data.frame(month=1:2, sales=c(200,190))
)

unnested <- unnest(nested, cols = data)
print(unnested)

unnest_longer() — ขยายรายการเป็นแถว

unnest_longer(df, col) ขยายคอลัมน์แบบรายการ โดยให้สมาชิกแต่ละรายการกลายเป็นหนึ่งแถว แตกต่างจาก unnest() ที่คาดว่าจะได้รับ data frame ตรงที่ unnest_longer() ใช้ได้กับรายการเวกเตอร์หรือค่ามาตราส่วน

library(tidyr)

df <- data.frame(
  person = c('Alice','Bob','Carol')
)
df$skills <- list(
  c('R','Python','SQL'),
  c('Excel','Tableau'),
  c('R','Julia','Stan','BUGS')
)

unnest_longer(df, skills)

unnest_wider() — ขยายรายการเป็นคอลัมน์

unnest_wider(df, col) ขยายสมาชิกแต่ละรายการเป็นชุดคอลัมน์ใหม่ รายการนั้นต้องมีสมาชิกที่มีชื่อกำกับ โดยชื่อเหล่านั้นจะกลายเป็นชื่อคอลัมน์ เหมาะสำหรับโครงสร้างข้อมูลลักษณะ JSON ที่ซ้อนกัน

library(tidyr)

df <- data.frame(id = 1:3)
df$info <- list(
  list(name='Alice', age=30, city='NYC'),
  list(name='Bob', age=25, city='LA'),
  list(name='Carol', age=35, city='Chicago')
)

unnest_wider(df, info)

รูปแบบกระบวนการทำงานกับข้อมูลซ้อนกันแบบครบถ้วน

กระบวนการทำงานกับ data frame แบบซ้อนกันอย่างครบถ้วนคือ group_by() + nest() → ใช้ฟังก์ชันด้วย map() → ดึงผลลัพธ์ → ใช้ unnest() เพื่อกลับเป็น data frame แบบแบน รูปแบบนี้ช่วยให้ดำเนินการวิเคราะห์ใด ๆ แยกตามกลุ่มได้

library(tidyr)
library(dplyr)
library(purrr)

df <- data.frame(
  region = c('East','East','East','West','West','West'),
  month = c(1,2,3,1,2,3),
  revenue = c(100,120,115,200,195,210)
)

df %>%
  group_by(region) %>%
  nest() %>%
  mutate(
    mean_rev = map_dbl(data, ~mean(.x$revenue)),
    trend = map_dbl(data, ~coef(lm(revenue~month, data=.x))[2])
  ) %>%
  select(region, mean_rev, trend)

การซ้อนหลายคอลัมน์

คุณสามารถเลือกได้ว่าจะให้คอลัมน์ใดเข้าไปอยู่ใน data frame แบบซ้อนกัน ระบุคอลัมน์เหล่านั้นอย่างชัดเจนใน nest(data = c(...)) คอลัมน์ที่ไม่ได้ระบุจะยังคงเป็นคอลัมน์ปกติใน data frame ชั้นนอก และอยู่ร่วมกับคอลัมน์แบบรายการ

library(tidyr)
library(dplyr)

df <- data.frame(
  region = c('East','East','West','West'),
  year = c(2023,2024,2023,2024),
  q1 = c(100,110,200,210),
  q2 = c(105,115,195,215),
  target = c(105,112,198,212)
)

# Only nest quarterly data, keep target as outer column
nested <- df %>%
  group_by(region, year) %>%
  nest(quarters = c(q1, q2))

print(nested)

เมื่อใดควรใช้ data frame แบบซ้อนกัน

data frame แบบซ้อนกันเหมาะอย่างยิ่งเมื่อคุณต้องการปรับโมเดลเดียวกันกับหลายกลุ่ม จำลองข้อมูลแยกตามกลุ่ม ใช้การแปลงที่ซับซ้อนกับชุดย่อย หรือทำงานกับข้อมูลลำดับชั้นลักษณะ JSON โดยจะช่วยจัดระเบียบข้อมูลเฉพาะกลุ่มไว้ร่วมกับข้อมูลเมทาดาทาระดับกลุ่ม

library(tidyr)
library(dplyr)
library(purrr)

# Bootstrap confidence interval per group
df <- data.frame(
  group = c('A','A','A','A','B','B','B','B'),
  value = c(10,12,11,13,20,22,19,21)
)

set.seed(42)
df %>%
  group_by(group) %>%
  nest() %>%
  mutate(
    boot_means = map(data, function(d) {
      replicate(100, mean(sample(d$value, replace=TRUE)))
    }),
    ci_low = map_dbl(boot_means, ~quantile(.x, 0.025)),
    ci_high = map_dbl(boot_means, ~quantile(.x, 0.975))
  ) %>%
  select(group, ci_low, ci_high)

ตรวจสอบความเข้าใจ

วิธีที่ถูกต้องในการขยายคอลัมน์แบบรายการของ data frame ให้กลับเป็น data frame แบบแบนคืออะไร

สรุป: การซ้อนและการคลายการซ้อน

ประเด็นสำคัญสำหรับกระบวนการทำงานกับ data frame แบบซ้อนกัน:

  • nest(data = c(cols)) — บรรจุคอลัมน์ลงในคอลัมน์แบบรายการของ data frame โดยมีหนึ่งรายการต่อกลุ่ม
  • group_by() + nest() — รูปแบบมาตรฐานสำหรับซ้อนข้อมูลตามกลุ่ม
  • map(nested$data, fn) — ใช้ฟังก์ชันใด ๆ กับ data frame แบบซ้อนกันแต่ละรายการ
  • unnest(cols = data) — ขยายคอลัมน์แบบรายการของ data frame กลับเป็นรูปแบบแบน
  • unnest_longer(col) — ขยายรายการเวกเตอร์หรือค่ามาตราส่วนเป็นแถว
  • unnest_wider(col) — ขยายรายการที่มีชื่อกำกับเป็นคอลัมน์
  • เหมาะสำหรับการสร้างโมเดลแยกตามกลุ่ม การสุ่มตัวอย่างซ้ำ และการประมวลผลข้อมูล JSON
library(tidyr)
library(dplyr)
library(purrr)

data.frame(
  team = c('A','A','B','B'),
  x = c(1,2,1,2),
  y = c(2,4,3,6)
) %>%
  group_by(team) %>%
  nest() %>%
  mutate(
    model = map(data, ~lm(y ~ x, data = .x)),
    slope = map_dbl(model, ~coef(.x)['x'])
  ) %>%
  select(team, slope)

คำถามที่พบบ่อย

บทเรียน “การซ้อนและคลายการซ้อนดาต้าเฟรม” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การซ้อนและคลายการซ้อนดาต้าเฟรม” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส R Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส R Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การซ้อนและคลายการซ้อนดาต้าเฟรม”

ใช้ nest() และ unnest() เพื่อทำงานกับคอลัมน์รายการในกระบวนงาน tidy คุณปฏิบัติ R Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน R Academy หรือไม่

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

บทเรียน “การซ้อนและคลายการซ้อนดาต้าเฟรม” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน R Academy นี้ได้ไหม

ได้ บทเรียน R Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. จากแบบกว้างเป็นแบบยาวด้วย pivot_longer()
  2. จากแบบยาวเป็นแบบกว้างด้วย pivot_wider()
  3. separate() และ unite() สำหรับคอลัมน์สตริง
  4. การซ้อนและคลายการซ้อนดาต้าเฟรม
← กลับไปที่ R Academy