Chuyển đến nội dung chính

Chuyển đổi dữ liệu Long ↔ Wide trong R

Tìm hiểu lý do bạn nên chuyển đổi dữ liệu giữa định dạng long và wide, và cách thực hiện trong R với melt() và dcast()!
· 15 phút đọc

Khám phá cùng AI

Sẽ có lúc bạn cần chuyển dữ liệu ở định dạng dài (bạn gọi là "long-form" và ý nghĩa sẽ rõ ở phần sau) sang định dạng rộng và ngược lại. Dữ liệu trong thực tế có đủ mọi định dạng, nhưng hầu hết các hàm trong R được thiết kế cho một dạng cụ thể.

Chẳng hạn, lme4::lmer() cho mô hình tuyến tính hỗn hợp, ggplot2::ggplot() để trực quan hóa được thiết kế cho long-form. Nhưng cũng có những hàm được thiết kế cho wide-form như mosaicplot(). Điều đó có nghĩa là bạn cần chuyển đổi định dạng để phân tích hoặc trực quan hóa trừ khi dữ liệu đã được xử lý sẵn và ở đúng định dạng.

Có một số lựa chọn trong R để chuyển đổi định dạng nhưng có thể khá rối khi bạn mới bắt đầu.

Hướng dẫn này sẽ giúp bạn hiểu cơ chế chuyển đổi dữ liệu giữa long-form và wide-form. Bạn sẽ khám phá các chủ đề sau:

  • Bạn sẽ hiểu rõ hơn về định dạng dài.
  • Sau đó, bạn sẽ làm quen với định dạng rộng.
  • Bạn sẽ điểm lại sự khác nhau giữa hai định dạng dài và rộng;
  • Tiếp theo, bạn sẽ thấy các bước cần thực hiện để chuyển từ định dạng này sang định dạng kia.
  • Cuối cùng, bạn sẽ triển khai tất cả bằng R. Bạn sẽ học cách đi từ định dạng dài sang định dạng rộng với các hàm melt() và dcast().

Dữ liệu

Bảng 01
namegenderyear2011year2012year2013year2014year2015
Jackson SmithM74.6984.9991.73105.11111.04
Sophia JohnsonFNANANANA75.89
Emma WilliamsFNANA75.7486.5091.50
Aiden JonesMNANANA71.8981.42
Liam BrownM88.2496.91101.85108.13112.45
Lucas DavisM70.6083.7894.17100.03106.35
Olivia MillerF64.7880.7687.3097.13103.80
Ava WilsonF88.7796.45104.72112.84NA

Bảng này cho thấy chiều cao của trẻ sơ sinh ở một khu vực nhỏ. Chiều cao được đo từ năm 2011 đến năm 2015. Như bạn có thể đã biết, NA nghĩa là ‘Không có sẵn’. Từ vị trí các NA, bạn có thể suy ra độ tuổi của các bé, nhưng tuổi chính xác thì không có trong bảng. Bảng trông có vẻ gọn gàng, nhưng với bất kỳ ai muốn nghiên cứu sự phát triển của trẻ, có một vấn đề: thông tin quan trọng không phải là thời điểm tuyệt đối khi một bé được đo mà là độ tuổi của bé khi được đo. Bạn có thể chèn thông tin này vào bảng không? Dưới đây là một cách:

Bảng 02
namegenderage0age1age2age3age4age5age6
Jackson SmithMNA76.6984.9197.06105.73107.32NA
Sophia JohnsonFNA76.05NANANANANA
Emma WilliamsF72.6582.4691.76NANANANA
Aiden JonesM69.7679.89NANANANANA
Liam BrownMNANA85.3493.22105.78105.84114.82
Lucas DavisM71.5984.8792.10100.73104.21NANA
Olivia MillerF62.7481.3992.0298.32106.44NANA
Ava WilsonFNANA88.39100.67107.58111.52NA

Số lượng NA đã tăng lên. ## Dữ liệu dạng rộng Nhưng bạn sẽ làm gì nếu muốn thể hiện số tháng tuổi của một bé? Sẽ trông như thế này:

Bảng 03
namegenderm4m6m7m10m12...m55m60m65m72
Jackson SmithMNANANANA76.69...NA107.32NANA
Sophia JohnsonFNANANANA76.05...NANANANA
Emma WilliamsFNANANA72.65NA...NANANANA
Aiden JonesMNA69.76NANANA...NANANANA
Liam BrownMNANANANANA...NA105.84NA114.82
Lucas DavisMNANA71.59NANA...104.21NANANA
Olivia MillerF62.74NANANANA...NANANANA
Ava WilsonFNANANANANA...NANA111.52NA

Có vô số NA trong bảng trên. Nếu các bé khác nhau về thời điểm đo lường tương đối, wide-form có thể lãng phí rất nhiều chỗ. Một lựa chọn khác là chỉ đưa độ tuổi của các bé khi đến năm 2015, nhưng điều đó chỉ khả thi khi các thời điểm đo tuyệt đối đều giống nhau. Nếu khác nhau theo tháng và bạn muốn biết tuổi theo tháng, cách đó không dùng được. Khi ấy ví dụ này có vẻ là cách duy nhất. Trong trường hợp này, bạn có thể cân nhắc dùng long-form. ## Dữ liệu dạng dài Trong khi tất cả phép đo của một bé hiển thị trên một hàng ở wide-form, ở long-form bạn chỉ thấy một phép đo của một bé trên một hàng. Cách đơn giản nhất để có dạng sau là hiển thị tên trẻ, thời điểm đo và phép đo (chiều cao) trên một hàng. Bảng sau chính là như vậy:

Bảng 04
namegendermonthheight
Olivia MillerF462.74
Aiden JonesM669.76
Lucas DavisM771.59
Emma WilliamsF1072.65
Jackson SmithM1276.69
............
Liam BrownM72114.82

Nếu bạn sắp xếp dữ liệu theo tên, bạn sẽ có bảng như dưới. Rõ ràng bảng này chiếm ít chỗ hơn Bảng 3 ở trên!

Bảng 05
namegendermonthheight
Jackson SmithM1276.69
Jackson SmithM2484.91
Jackson SmithM3697.06
Jackson SmithM48105.73
Jackson SmithM60107.32
Sophia JohnsonF1276.05
Emma WilliamsF1072.65
............
Ava WilsonF65111.52

Dạng Dài và Dạng Rộng

Lưu ý lại sự khác biệt cơ bản giữa wide-form và long-form: một khác biệt đơn giản là wide-form hiển thị nhiều phép đo của một cá thể trên một hàng và tên cột cho biết các phép đo đó là gì.

Bảng này cho thấy chiều cao của Liam Brown trong các năm 2011-2015 trên một hàng:

Bảng 06
namegenderyear2011year2012year2013year2014year2015
Liam BrownM88.2496.91101.85108.13112.45

Ở long-form chiều cao của Liam Brown được hiển thị trong một cột:

Bảng 07
namegender_
Liam BrownM85.34
Liam BrownM93.22
Liam BrownM105.78
Liam BrownM105.84
Liam BrownM114.82

Như bạn thấy, bạn không thể biết các phép đo là gì. Nếu viết tên cột, nó sẽ như thế này:

Bảng 08
namegenderyear2011, 2012, 2013, 2014, 2015
Liam BrownM85.34
Liam BrownM93.22
Liam BrownM105.78
Liam BrownM105.84
Liam BrownM114.82

Nhưng cách này lại có vấn đề riêng. Chiều cao của Sophia Johnson không được đo trong các năm 2011-2014. Nên như dưới đây, bạn khó có thể đặt tên cột một cách dễ dàng:

Bảng 09
namegender?
Liam BrownM85.34
Liam BrownM93.22
Liam BrownM105.78
Liam BrownM105.84
Liam BrownM114.82
Sophia JohnsonF76.05

Từ Dạng Rộng sang Dạng Dài

Chuyển wide-form sang long-form có thể xem như một quy trình từng bước. Trước khi chuyển các phép đo trên một hàng vào một cột, bạn có thể làm cho bảng chỉ chứa một phép đo trên mỗi hàng. Hãy làm điều đó cho bảng này:

Bảng 10
namegenderage0age1age2age3age4age5age6
Emma WilliamsF72.6582.4691.76NANANANA
Aiden JonesM69.7679.89NANANANANA

Kết quả như bảng dưới đây:

Bảng 11
namegenderage0age1age2age3age4age5age6
Emma WilliamsF72.65  NANANANA
Emma WilliamsF 82.46    NA
Emma WilliamsF  91.76    
Aiden JonesM69.76 NANANANANA
Aiden JonesM 79.89     

Trước khi gom các phép đo đang rải rác qua nhiều cột vào một cột, bạn cần tạo thêm một cột để nói rõ các phép đo đó là gì, như dưới đây:

Bảng 12
namegendermeasureage0age1age2age3age4age5age6
Emma WilliamsFage072.65  NANANANA
Emma WilliamsFage1 82.46    NA
Emma WilliamsFage2  91.76    
Aiden JonesMage069.76 NANANANANA
Aiden JonesMage1 79.89     

Tên cột thường là “measure” hoặc “key”. Bạn có thể nhận thấy trong bảng trên có “age0”, “age1”, “age2”, “age3”, “age4”, “age5” xuất hiện cả ở tên cột và trong một cột. Nếu bỏ tên các cột, bảng sẽ như dưới.

Bảng 13
namegendermeasure____________________________
Emma WilliamsFage072.65  NANANANA
Emma WilliamsFage1 82.46     
Emma WilliamsFage2  91.76    
Aiden JonesMage069.76 NANANANANA
Aiden JonesMage1 79.89     

Vì mỗi hàng chỉ có một phép đo, bạn có thể gom chúng vào một cột và kết quả sẽ như sau:

Bảng 14
namegendermeasure 
Emma WilliamsFage072.65
Emma WilliamsFage182.46
Emma WilliamsFage291.76
Aiden JonesMage069.76
Aiden JonesMage179.89

Hãy đặt tên cột mới cho tất cả các phép đo. Thường được đặt là "value":

Bảng 15
namegendermeasurevalue
Emma WilliamsFage072.65
Emma WilliamsFage182.46
Emma WilliamsFage291.76
Aiden JonesMage069.76
Aiden JonesMage179.89

Nhìn vào bảng trên. Bạn có nhận ra từ "age" bị lặp lại không? Bạn có thể lược bỏ phần lặp, sẽ cho kết quả sau:

Bảng 16
namegenderagevalue
Emma WilliamsF072.65
Emma WilliamsF182.46
Emma WilliamsF291.76
Aiden JonesM069.76
Aiden JonesM179.89

Age, vốn lặp lại ở mọi hàng, giờ trở thành tên cột. Tên cột value trong bảng trên có thể cụ thể hơn. Bạn thay bằng height, rõ nghĩa hơn. Kết quả như bảng dưới:

Bảng 17
namegenderageheight
Emma WilliamsF072.65
Emma WilliamsF182.46
Emma WilliamsF291.76
Aiden JonesM069.76
Aiden JonesM179.89

Hãy so sánh Bảng 15 với Bảng 17. value, một trong các tên cột của Bảng 15, có thể là bất cứ thứ gì, còn height ở Bảng 17 có nghĩa rất cụ thể: chỉ có thể là chiều cao, trong khi value ở Bảng 15 có thể là bất cứ giá trị nào như chiều cao, cân nặng, tốc độ hoặc màu sắc. Một cách khác như sau:

Bảng 18
namegendermeasurevalue
Emma WilliamsFheight.age072.65
Emma WilliamsFheight.age182.46
Emma WilliamsFheight.age291.76
Aiden JonesMheight.age069.76
Aiden JonesMheight.age179.89

Hãy xét tình huống các phép đo đa dạng. Nếu phép đo là chiều cao, cân nặng và BMI, sẽ như bảng dưới. Nhưng trong trường hợp này, cột value có các giá trị số ở thang đo khác nhau nên có thể gây khó hiểu khi đọc. Trong bảng này, chiều cao đo bằng centimet và cân nặng bằng kilogram:

Bảng 19
namegendermeasurevalue
Emma WilliamsFheight72.65
Emma WilliamsFweight8.22
Emma WilliamsFBMI22.60
Aiden JonesMheight69.76
Aiden JonesMweight8.51

Vì vậy khi chuyển wide-form sang long-form, bạn cần quyết định những giá trị nào sẽ được gom vào một cột. Sau đó, bạn có thể quyết định tên cột.

Hãy tóm tắt những gì đã nói đến giờ: để chuyển wide-form sang long-form bạn cần quyết định những cột nào sẽ được chỉnh để đưa vào một cột. Khi làm vậy, nhiều cột được gộp lại thành một cột. Vì thế bạn cần một tên cột cho cột đó, như bạn thấy ở các bảng sau:

Bảng 20
id1id2age0age1age2
Emma WilliamsFNA82.4691.76
Aiden JonesM69.7679.89NA
Emma WilliamsFNA82.4691.76
Bảng 21
id1id2age0age1age2
Emma WilliamsFNA  
Emma WilliamsF 82.46 
Emma WilliamsF  91.76
Aiden JonesM69.76  
Aiden JonesM 79.89 
Aiden JonesM  NA
Emma WilliamsFNA  
Emma WilliamsF 82.46 
Emma WilliamsF  91.76
Bảng 22
id1id2age_age0age1age2
Emma WilliamsFage0NA  
Emma WilliamsFage1 82.46 
Emma WilliamsFage2  91.76
Aiden JonesMage069.76  
Aiden JonesMage1 79.89 
Aiden JonesMage2  NA
Emma WilliamsFage0NA  
Emma WilliamsFage1 82.46 
Emma WilliamsFage2  91.76
Bảng 23
id1id2age_ 
Emma WilliamsFage0NA
Emma WilliamsFage182.46
Emma WilliamsFage291.76
Aiden JonesMage069.76
Aiden JonesMage179.89
Aiden JonesMage2NA
Emma WilliamsFage0NA
Emma WilliamsFage182.46
Emma WilliamsFage291.76
Bảng 24
id1id2keyvalue
Emma WilliamsFage0NA
Emma WilliamsFage182.46
Emma WilliamsFage291.76
Aiden JonesMage069.76
Aiden JonesMage179.89
Aiden JonesMage2NA
Emma WilliamsFage0NA
Emma WilliamsFage182.46
Emma WilliamsFage291.76
Bảng 25
id1id2keyvalue
Emma WilliamsFage182.46
Emma WilliamsFage291.76
Aiden JonesMage069.76
Aiden JonesMage179.89
Emma WilliamsFage182.46
Emma WilliamsFage291.76

Hãy xem các cột id1 và id2 trong bảng trên. id2 không chỉ một cá nhân mà là thuộc tính (giới tính) của một cá nhân. Nói cách khác, bạn có thể coi nó là một phép đo. Vì vậy bạn có thể chuyển nó sang dạng dài hơn. Dạng dài nhất được tạo thành từ ba cột, đó là id, key và value.

Bảng 26
idkeyvalue
Emma WilliamsgenderF
Emma Williamsage182.46
Emma Williamsage291.76
Aiden JonesgenderF
Aiden Jonesage069.76
Aiden Jonesage179.89
Emma WilliamsgenderF
Emma Williamsage182.46
Emma Williamsage291.76

Bảng trên cho thấy dạng dài nhất từ bảng 25. Nhưng những người khác nhau có thể trùng tên.

Trong trường hợp đó, long-form có thể gây nhầm lẫn vì id không thể xác định một người duy nhất. Bạn có thể thêm một số phía sau tên để phân biệt (ví dụ dùng hàm R make.unique()), nhưng bạn không thể phân biệt tên đã bị chỉnh sửa và tên gốc có kèm số. Hãy nghĩ đến một người thực sự có tên là "John.2"!

Cách rõ ràng là gán một mã số ID khác nhau cho từng người. Khi đó, tên lại trở thành một phép đo khác.

Bảng tiếp theo cho thấy ngay cả tên cũng được coi là phép đo. Theo nghĩa nào đó, đây mới là dạng dài nhất thực sự.

Bảng 27
idkeyvalue
1nameEmma Williams
1genderF
1age182.46
1age291.76
2nameAiden Jones
2genderF
2age069.76
2age179.89
3nameEmma Williams
3genderF
3age182.46
3age291.76

Dạng dài nhất là dạng dễ nhất để tạo ra dạng rộng. Nếu bạn đảo ngược quá trình chuyển từ dạng rộng sang dạng dài như ở các bảng 20 đến 25, bạn sẽ thu được dạng rộng. Các bảng dưới đây minh họa quá trình này:

Bảng 28. Các phép đo trong cột key được lặp lại ở tên cột
idkeynamegenderage0age1age2
1nameEmma Williams    
1gender F   
1age1   82.46 
1age2    91.76
2nameAiden Jones    
2gender F   
2age0  69.76  
2age1   79.89 
3nameEmma Williams    
3gender F   
3age1   82.46 
3age2    91.76
Bảng 29. Có thể xóa cột key
idnamegenderage0age1age2
1Emma Williams    
1 F   
1   82.46 
1    91.76
2Aiden Jones    
2 F   
2  69.76  
2   79.89 
3Emma Williams    
3 F   
3   82.46 
3    91.76
Bảng 30. Có thể gộp các hàng có cùng id thành một hàng
idnamegenderage0age1age2
1Emma WilliamsF 82.4691.76
1     
1     
1     
2Aiden JonesF69.7679.89 
2     
2     
2     
3Emma WilliamsF 82.4691.76
3     
3     
3     
Bảng 31. Xóa mọi hàng không có phép đo nào
idnamegenderage0age1age2
1Emma WilliamsF 82.4691.76
2Aiden JonesF69.7679.89 
3Emma WilliamsF 82.4691.76

Yếu tố then chốt khi chuyển đổi từ dạng rộng sang dạng dài là quyết định những cột nào sẽ được gom vào một cột.

Nhưng không nhất thiết chỉ là một cột. Bạn có thể dùng hai cột nếu cần, như trong bảng dưới đây:

Bảng 32
namegenderh2011h2012w2011w2012
Jackson SmithM74.6984.999.6012.0
Olivia MillerFNA80.767.1510.7
Ava WilsonF88.7796.45NA15.0

Bạn có thể chuyển nó sang long-form không?

Các cột h2011, h2012, w2011, w2012 lần lượt là chiều cao và cân nặng trong các năm 2011 và 2012. height và weight được đo trên các thang đo khác nhau - cm, kg. Vì vậy bạn có thể dùng chỉ một cột cho cả chiều cao và cân nặng hoặc dùng hai cột, như trong bảng này:

Bảng 33
namegenderyearheightweight
Jackson SmithM201174.699.60
Jackson SmithM201284.9912.00
Olivia MillerF2011NA80.76
Olivia MillerF20127.1510.70
Ava WilsonF201188.7796.45
Ava WilsonF2012NA15.00

Đây là long-form hay wide-form?

Từ dữ liệu Long sang Wide trong R

Hãy thực hiện việc chuyển đổi giữa long-form và wide-form với R. Có nhiều hàm và gói có sẵn cho tác vụ này.

Bảng 34
funcpackageto_long_formto_wide_form
stack/unstackutilsstackunstack
reshapestatsreshape(direction="long", ...)reshape(direction="wide", ...)
melt/dcastreshape2meltdcast
gather/spreadtidyrgatherspread

Tại đây tôi sẽ giải thích cách dùng các hàm melt() và dcast() của gói reshape2. Lý do là stack() và unstack() là các hàm cơ bản nên cần hậu xử lý kết quả từ chúng. Lưu ý rằng gather() và spread() là các hàm của tidyr cũng rất phổ biến, nhưng sẽ không được đề cập trong hướng dẫn này.

Một hàm khác bạn có thể dùng là reshape() thuộc gói stats. Thực tế, đừng nhầm lẫn với hàm này vì còn có một gói tên là reshape! Gói này, cùng với reshape2, được phát triển cho những ai gặp khó khăn với reshape(). Ngoài ra, hàm reshape() dường như giả định dữ liệu là dạng dọc (longitudinal), nghĩa là các phép đo được lặp lại theo thời gian.

Hãy chuyển dữ liệu ở bảng 35 sang long-form. Giả sử bảng dưới lưu một data.frame tên là dat.

Bảng 35
namegenderyear2011year2012year2013
Jackson SmithM74.6984.9991.73
Emma WilliamsFNANA75.74
Liam BrownM88.24NA101.85
Ava WilsonF88.7796.45NA

babies = data.frame(name= c("Jackson Smith", "Emma Williams", "Liam Brown", "Ava Wilson"), gender = c("M", "F", "M", "F"), year2011= c(74.69, NA, 88.24, 88.77), year2012=c(84.99, NA, NA, 96.45), year2013=c(91.73, 75.74, 101.83, NA)) babies

##            name gender year2011 year2012 year2013
## 1 Jackson Smith      M    74.69    84.99    91.73
## 2 Emma Williams      F       NA       NA    75.74
## 3    Liam Brown      M    88.24       NA   101.83
## 4    Ava Wilson      F    88.77    96.45       NA

Câu hỏi bạn cần đặt ra là: "những cột nào cần gộp thành một cột?".

Đó là các cột year2011, year2012, year2013. Khi dùng hàm melt(), các cột này nên được liệt kê cho measure.vars:

melt(babies, measure.vars = c("year2011", "year2012", "year2013"))

##             name gender variable  value
## 1  Jackson Smith      M year2011  74.69
## 2  Emma Williams      F year2011     NA
## 3     Liam Brown      M year2011  88.24
## 4     Ava Wilson      F year2011  88.77
## 5  Jackson Smith      M year2012  84.99
## 6  Emma Williams      F year2012     NA
## 7     Liam Brown      M year2012     NA
## 8     Ava Wilson      F year2012  96.45
## 9  Jackson Smith      M year2013  91.73
## 10 Emma Williams      F year2013  75.74
## 11    Liam Brown      M year2013 101.83
## 12    Ava Wilson      F year2013     NA

year2011, year2012, year2013 là các cột nằm ở vị trí thứ 3, 4, 5 nên bạn có thể dùng cách đó:

melt(babies, measure.vars = 3:5)

##             name gender variable  value
## 1  Jackson Smith      M year2011  74.69
## 2  Emma Williams      F year2011     NA
## 3     Liam Brown      M year2011  88.24
## 4     Ava Wilson      F year2011  88.77
## 5  Jackson Smith      M year2012  84.99
## 6  Emma Williams      F year2012     NA
## 7     Liam Brown      M year2012     NA
## 8     Ava Wilson      F year2012  96.45
## 9  Jackson Smith      M year2013  91.73
## 10 Emma Williams      F year2013  75.74
## 11    Liam Brown      M year2013 101.83
## 12    Ava Wilson      F year2013     NA

Kết quả nằm trong bảng phía trên. Lưu ý tên cột variable và value. Bảng 23 và bảng 24 cho thấy các tên cột mới là cần thiết. Hàm melt() có các tên mặc định cho cột mới là variable và value. Bạn có thể ghi đè giá trị mặc định bằng cách dùng đối số variable.name= và value.name=. Hãy làm điều này bên dưới:

melt(babies, measure.vars=3:5, variable.name="year", value.name="height")

##             name gender     year height
## 1  Jackson Smith      M year2011  74.69
## 2  Emma Williams      F year2011     NA
## 3     Liam Brown      M year2011  88.24
## 4     Ava Wilson      F year2011  88.77
## 5  Jackson Smith      M year2012  84.99
## 6  Emma Williams      F year2012     NA
## 7     Liam Brown      M year2012     NA
## 8     Ava Wilson      F year2012  96.45
## 9  Jackson Smith      M year2013  91.73
## 10 Emma Williams      F year2013  75.74
## 11    Liam Brown      M year2013 101.83
## 12    Ava Wilson      F year2013     NA

Các phép đo đã được chỉ định trong các ví dụ trên. Với các thiết lập bạn đang xử lý, Id có thể gián tiếp chỉ định các phép đo. Vì vậy bạn có thể chọn các cột cho id thay vì cho phép đo.

Kết quả là như nhau cho cả hai cách dưới đây. Cách thứ nhất chọn các cột cho id, cách thứ hai chọn các cột để gom lại:

melt(babies, id.vars=c("name","gender"))

melt(babies, measure.vars = c("year2011", "year2012", "year2013"))

##             name gender variable  value
## 1  Jackson Smith      M year2011  74.69
## 2  Emma Williams      F year2011     NA
## 3     Liam Brown      M year2011  88.24
## 4     Ava Wilson      F year2011  88.77
## 5  Jackson Smith      M year2012  84.99
## 6  Emma Williams      F year2012     NA
## 7     Liam Brown      M year2012     NA
## 8     Ava Wilson      F year2012  96.45
## 9  Jackson Smith      M year2013  91.73
## 10 Emma Williams      F year2013  75.74
## 11    Liam Brown      M year2013 101.83
## 12    Ava Wilson      F year2013     NA

Nếu bạn chỉ định cả id.vars và measure.vars, các cột không thuộc bất kỳ nhóm nào trong hai nhóm này sẽ bị loại khỏi kết quả. Ví dụ, xem đoạn mã dưới đây:

melt(babies, id.vars=c("name"), measure.vars=c("year2011", "year2012"))

##            name variable value
## 1 Jackson Smith year2011 74.69
## 2 Emma Williams year2011    NA
## 3    Liam Brown year2011 88.24
## 4    Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 6 Emma Williams year2012    NA
## 7    Liam Brown year2012    NA
## 8    Ava Wilson year2012 96.45

Ngoài ra, na.rm=T có thể loại bỏ các giá trị NA:

melt(babies, id.vars=c("name"), measure.vars=c("year2011", "year2012"), na.rm=T)

##            name variable value
## 1 Jackson Smith year2011 74.69
## 3    Liam Brown year2011 88.24
## 4    Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8    Ava Wilson year2012 96.45

Hàm dcast() thực hiện thao tác ngược lại với melt(). id, variable và value là các cột của dạng dài nhất. dcast(data, id ~ variable, value.var="value") chuyển từ dạng dài nhất sang dạng rộng.

babiesLong <- melt(babies, id.vars=c("name"), measure.vars=c("year2011", "year2012"), na.rm=T)
babiesLong

##            name variable value
## 1 Jackson Smith year2011 74.69
## 3    Liam Brown year2011 88.24
## 4    Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8    Ava Wilson year2012 96.45

babiesLong có name cho id, variable cho variable, và value cho value. Vì vậy bạn có thể dùng dcast() để đưa nó về dạng rộng:

dcast(babiesLong, name ~ variable, value.var="value")

##            name year2011 year2012
## 1    Ava Wilson    88.77    96.45
## 2 Jackson Smith    74.69    84.99
## 3    Liam Brown    88.24       NA

Kết luận

Vậy là hầu như xong. Trong hướng dẫn này, bạn tập trung vào việc hiểu logic và quy trình tái cấu trúc dữ liệu. Thông thường, dạng dài được ưu tiên cho phân tích nhưng vẫn có ngoại lệ. Trình bày dữ liệu ở dạng rộng có thể tiết kiệm không gian khi phù hợp, nhưng khi số lượng giá trị khuyết tăng lên, bạn nên chuyển sang dạng dài.

Đối với việc chuyển đổi định dạng, bạn cần tập trung vào cái gì là phép đo. Châm ngôn cho dạng dài là mỗi hàng một phép đo, còn dạng rộng có nhiều phép đo trong một hàng. Khi bạn gộp các phép đo trải khắp nhiều cột vào một cột, tên cột gốc cần được giữ lại trong một cột bổ sung. Khi bạn trải các phép đo trong một cột ra nhiều cột, bạn cần xác định tên cột dựa trên cột variable.

Một khi hiểu quy trình, việc dùng các hàm như dcast() và melt() sẽ dễ dàng hơn rất nhiều!

Chủ đề

Liên quan