Lấy và làm sạch dữ liệu với R: Gom nhóm và kĩ thuật Chaining với dplyr

Ở bài viết trước, chúng ta đã học về năm thao tác chính trong dplyr: select(), filter(), arrange(), mutate(), và summarize(). Hàm summarize() rất mạnh mẽ trong việc áp dụng dữ liệu đã gom nhóm. Chúng ta tiếp tục làm việc với tập dữ liệu 225,000 packages của R. Ở đây, ta dùng file log July 8, 2014 (http://cran-logs.rstudio.com/).

Gom nhóm dữ liệu

Đầu tiên, chúng ta sẽ nạp thư viện dplyr và thực hiện các bước như ở phần trước.

library(dplyr)
# tạo biến cran thuộc kiểu dữ liệu data frame tbl
cran <- tbl_df(mydf)
# loại bỏ dữ liệu cũ để tránh nhầm lẫn
rm("mydf")
# in biến cran ra màn hình
cran
Source: local data frame [225,468 x 11]

    X       date     time    size r_version r_arch      r_os      package
1   1 2014-07-08 00:54:41   80589     3.1.0 x86_64   mingw32    htmltools
2   2 2014-07-08 00:59:53  321767     3.1.0 x86_64   mingw32      tseries
3   3 2014-07-08 00:47:13  748063     3.1.0 x86_64 linux-gnu        party
4   4 2014-07-08 00:48:05  606104     3.1.0 x86_64 linux-gnu        Hmisc
5   5 2014-07-08 00:46:50   79825     3.0.2 x86_64 linux-gnu       digest
6   6 2014-07-08 00:48:04   77681     3.1.0 x86_64 linux-gnu randomForest
7   7 2014-07-08 00:48:35  393754     3.1.0 x86_64 linux-gnu         plyr
8   8 2014-07-08 00:47:30   28216     3.0.2 x86_64 linux-gnu      whisker
9   9 2014-07-08 00:54:58    5928        NA     NA        NA         Rcpp
10 10 2014-07-08 00:15:35 2206029     3.0.2 x86_64 linux-gnu     hflights
.. ..        ...      ...     ...       ...    ...       ...          ...
Variables not shown: version (chr), country (chr), ip_id (int)

Tiếp theo ta sẽ gom nhóm biến cran theo thuộc tính package và lưu kết quả vào biến mới gọi là by_package.

by_package <- group_by(cran, package)
by_package
Source: local data frame [225,468 x 11]
Groups: package

    X       date     time    size r_version r_arch      r_os      package
1   1 2014-07-08 00:54:41   80589     3.1.0 x86_64   mingw32    htmltools
2   2 2014-07-08 00:59:53  321767     3.1.0 x86_64   mingw32      tseries
3   3 2014-07-08 00:47:13  748063     3.1.0 x86_64 linux-gnu        party
4   4 2014-07-08 00:48:05  606104     3.1.0 x86_64 linux-gnu        Hmisc
5   5 2014-07-08 00:46:50   79825     3.0.2 x86_64 linux-gnu       digest
6   6 2014-07-08 00:48:04   77681     3.1.0 x86_64 linux-gnu randomForest
7   7 2014-07-08 00:48:35  393754     3.1.0 x86_64 linux-gnu         plyr
8   8 2014-07-08 00:47:30   28216     3.0.2 x86_64 linux-gnu      whisker
9   9 2014-07-08 00:54:58    5928        NA     NA        NA         Rcpp
10 10 2014-07-08 00:15:35 2206029     3.0.2 x86_64 linux-gnu     hflights
.. ..        ...      ...     ...       ...    ...       ...          ...
Variables not shown: version (chr), country (chr), ip_id (int)

Ở dòng trên cùng, ta thấy “Groups: package” cho chúng ta biết tbl này đã được gom nhóm theo thuộc tính package. Các phép toán áp dụng sau này của chúng ta sẽ tác động lên từng nhóm đã gom được này.

Khi áp dụng hàm mean(size) tlb_df thông qua hàm summarize(). Ta nhận được một giá trị mean duy nhất thể hiện giá trị trung bình của cột thuộc tính này. Nhưng nếu ta muốn biết giá trị download trung bình của từng package thì sao.

summarize(by_package, mean(size))
Source: local data frame [6,023 x 2]

       package mean(size)
1           A3   62194.96
2  ABCExtremes   22904.33
3     ABCoptim   17807.25
4        ABCp2   30473.33
5       ACCLMA   33375.53
6          ACD   99055.29
7         ACNE   96099.75
8        ACTCD  134746.27
9    ADGofTest   12262.91
10        ADM3 1077203.47
..         ...        ...

Thay vì trả về một giá trị, hàm summarize() bây giờ trả về giá trị download trung bình của từng package mà chúng ta đã gom nhóm trước đó. Ta phân tích dòng lệnh sau:

pack_sum <- summarize(by_package,
                      count = n(),
                      unique = n_distinct(ip_id),
                      countries = n_distinct(country),
                      avg_bytes = mean(size))

# in pack_sum ra màn hình
pack_sum
Source: local data frame [6,023 x 5]

       package count unique countries  avg_bytes
1           A3    25     24        10   62194.96
2  ABCExtremes    18     17         9   22904.33
3     ABCoptim    16     15         9   17807.25
4        ABCp2    18     17        10   30473.33
5       ACCLMA    15     14         9   33375.53
6          ACD    17     16        10   99055.29
7         ACNE    16     15        10   96099.75
8        ACTCD    15     14         9  134746.27
9    ADGofTest    47     44        20   12262.91
10        ADM3    17     16        10 1077203.47
..         ...   ...    ...       ...        ...

Cột thuộc tính ‘count’ được tạo ra bởi hàm n(), chứa số lượng downloads của từng package. Cột thuộc tính ‘unique’ được tạo bởi hàm n_distinct(ip_id), chứa số lượng download từ địa chỉ ip người dùng. Cột thuộc tính ‘countries’ được tạo bởi hàm n_distinct(country), chứa số lượng các quốc gia download package này. Cuối cùng là cột thuộc tính ‘avg_bytes’ được tạo bởi hàm mean(size), chứa giá trị download trung bình của từng package.

Điều quan trọng là ta hiểu được ý nghĩa của từng cột thuộc tính của pack_sum và chúng được tạo ra như thế nào. Bây giờ chúng ta đã biết cách summarize() dữ liệu cho từng nhóm package. Tiếp theo, chúng ta thử làm một vài ví dụ khác để ôn lại những gì đã học.

Một cách tự nhiên, chúng ta sẽ muốn biết những package nào phổ biến nhất. Chúng ta bắt đầu bằng việc tách ra top 1% nhóm các package có số lượng download nhiều nhất dựa trên cột thuộc tính “count”. Ta sẽ dùng bách phân vị 99% (quartile) để xác định giá trị của nhóm 99%. Từ đó, ta sẽ biết được ngưỡng để lấy 1% nhóm còn lại.

quantile(pack_sum$count, probs = 0.99)
   99% 
679.56

Bây giờ, ta sẽ dùng ngưỡng 679 để tách ra nhóm 1%. Sử dụng hàm filter() giúp chọn ra các dòng dữ liệu có ‘count’ lớn hơn 679. Sau đó, lưu kết quả này vào biến top_counts.

top_counts <- filter(pack_sum, count > 679)
top_counts
Source: local data frame [61 x 5]

        package count unique countries  avg_bytes
1           DBI  2599    492        48  206933.25
2       Formula   852    777        65  155742.00
3         Hmisc   954    812        69 1367675.91
4          LPCM  2335     17        10  526814.23
5          MASS   834    698        66  981152.18
6        Matrix   932    801        66 3220134.17
7  RColorBrewer  1890   1584        79   22763.99
8         RCurl  1504   1207        73 1903505.32
9         RJDBC   809    107        28   18715.44
10      RJSONIO   751    585        60 1208103.99
..          ...   ...    ...       ...        ...

Chỉ có 61 package trong top 1% vì vậy ta muốn xem toàn bộ kết quả. Trong khi dplyr chỉ cho chúng ta xem 10 dòng dữ liệu đầu tiên, chúng ta có thể dùng hàm View() để xem toàn bộ dữ liệu.

# xem toàn bộ 61 dòng dữ liệu
View(top_counts)
Top download packages

Top download packages

Chúng ta muốn các package có giá trị cao nhất xuất hiện đầu bảng, nghĩa là chúng ta sẽ sắp xếp giảm dần cột thuộc tính count.

top_counts_sorted <- arrange(top_counts, desc(count))
View(top_counts_sorted)
Top sorted download packages

Top sorted download packages

Theo kết quả thống kê trên, ta thấy dẫn đầu là package ggplot2 với 4602 lượt download, theo đó là Rcpp, plyr, rJava, … Cuối cùng ta thấy swirl package đứng thứ 43 với 820 lượt download. Thật thú vị.

Kĩ thuật chaining

Kĩ thuật chaining cho phép chúng ta gọi các hàm nối tiếp nhau nhờ vậy mà code của chúng ta dễ đọc hơn trong khi vẫn cho ra cùng kết quả ban đầu. Cụ thể, ta sẽ tính toán lại các thao tác trên với kĩ thuật chaining.

  cran %>%
  group_by(package) %>%
  summarize(count = n(),
            unique = n_distinct(ip_id),
            countries = n_distinct(country),
            avg_bytes = mean(size)
  ) %>%
  filter(count > 679) %>%
  arrange(desc(count))
  View()

Qua bài viết này, ta đã học được cách gom nhóm và sử dụng kĩ thuật chaining với dplyr. Kết hợp với những gì đã học ở phần trước ta đã có thêm các công cụ mạnh mẽ, chính xác, và hiệu quả. Chào mừng đến với thế giới của dplyr.

Nguồn tham khảo: http://swirlstats.com/

Advertisements

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Đăng xuất / Thay đổi )

Connecting to %s