Những bạn nào làm với R lâu, bằng cách này hoặc cách khác, sẽ phải gặp 2 gói sử lí dữ liệu nổi tiếng soái ca soái tỉ đó là dplyr và data.table. Riêng mình, mình chỉ sử dụng dplyr, nhưng dạo này đọc nhiều thứ viết bằng data.table quá nên đọc sơ qua để biết.
Sau đây là một bài trình bày ngắn gọn, so sánh giữa dplyr và data.table. Viết để giữ lại. Nếu các bạn muốn xem bài trước về dplyr, ggplot2 và dygraph có thể xem ở bài trước mình post: http://rpubs.com/tkvit/228141
library(data.table)
library(tidyverse)
library(microbenchmark)
rm(list=ls())
filecloud <- "/Volumes/Public/Work_test/Data_R/Us_baby_names/StateNames.csv"
filehdd <- "/Volumes/TKV 900Go/Work_test/Data_R/Us_baby_names/StateNames.csv"
df <-tbl_df(fread(filecloud,
colClasses = c("numeric","character","numeric","character","character","numeric")))
df1 <- as.data.table(df)
df_backup <- df
Ở phần này mình chia ra df thuộc dạng data.frame, df1 thuộc dạng data.table.
dim(df)
## [1] 5647426 6
head(df)
## # A tibble: 6 × 6
## Id Name Year Gender State Count
## <dbl> <chr> <dbl> <chr> <chr> <dbl>
## 1 1 Mary 1910 F AK 14
## 2 2 Annie 1910 F AK 12
## 3 3 Anna 1910 F AK 10
## 4 4 Margaret 1910 F AK 8
## 5 5 Helen 1910 F AK 7
## 6 6 Elsie 1910 F AK 6
Dữ liệu gồm 5647426 dòng và 6 cột. Bây giờ mình bắt đầu xử lí bằng dplyr và data.table
#dplyr
top5a <- df %>% filter(Gender == "F") %>%
group_by(Name) %>%
summarise(name_count = sum(Count),
num_years = n_distinct(Year)) %>% #Sometime need to reset...
ungroup() %>%
arrange(desc(name_count)) %>%
slice(1:5)
#data.table
top5b <- df1[Gender == "F",.(name_count = sum(Count),num_years = uniqueN(Year)),by=Name
][order (-name_count)][1:5]
top5a
## # A tibble: 5 × 3
## Name name_count num_years
## <chr> <dbl> <int>
## 1 Mary 3730856 105
## 2 Patricia 1567779 105
## 3 Elizabeth 1500462 105
## 4 Jennifer 1461813 82
## 5 Linda 1446300 105
top5b
## Name name_count num_years
## 1: Mary 3730856 105
## 2: Patricia 1567779 105
## 3: Elizabeth 1500462 105
## 4: Jennifer 1461813 82
## 5: Linda 1446300 105
all.equal(top5a,top5b)
## [1] TRUE
#dplyr
top1a <- df %>%
filter(Name == top5a$Name[1]) %>%
group_by(Year) %>%
summarise(n_count =sum(Count)) %>% ungroup()
#data.table
top1b <- df1[Name == top5b$Name[1],.(n_count = sum(Count)), by = Year]
top1a %>%
ggplot(aes(x= Year, y=n_count)) + geom_bar(stat = "identity",color = "#3399FF") +
theme_bw() + ggtitle(top5a$Name[1])
top1b %>%
ggplot(aes(x= Year, y=n_count)) + geom_bar(stat = "identity",color = "#3399FF") +
theme_bw() + ggtitle(top5a$Name[1])
all.equal(top1a,top1b)
## [1] TRUE
#dplyr
top1a_f <- df %>%
group_by(State) %>%
summarise(nc_female = sum(Count[Name == top5a$Name[1]])) %>% ungroup()
#data.table
top1b_f <- df1[Name == top5b$Name[1], .(nc_female = sum(Count)),by=State]
all.equal(top1a_f,top1b_f)
## [1] TRUE
Sự khác nhau về tốc độ tuy có nhưng không đáng kể ở các phần trước. Ở phần này data.table nhanh hơn rõ rệt
#dplyr
name2010a <- df %>%
group_by(Name,Year) %>%
filter(Year > 2010) %>%
group_by(Name) %>%
summarise(n_count = sum(Count)) %>% ungroup() %>%
filter(n_count >100)
#data.table
name2010b <- df1[Year > 2010,.(n_count = sum(Count)), by = Name][n_count>100,]
all.equal(name2010a,name2010b)
## [1] TRUE
#dplyr
notuse2010a <- df %>%
filter(Gender == "M") %>%
group_by(Name) %>%
summarise(n_count = sum(Count),
first_use = min(Year),
last_use = max(Year)) %>%
filter(first_use>1910,last_use<2000) %>%
ungroup() %>%
arrange(desc(n_count)) %>%
slice(1:2)
#data.table
notuse2010b <- df1[Gender == "M", .(n_count = sum(Count),
first_use = min(Year),
last_use = max(Year)),by = Name
][first_use >1910 | last_use <2000,][order (-n_count)][1:2]
Microbenchmark cho 2 đoạn code trên
## Unit: milliseconds
## expr min lq mean median uq max neval cld
## dplyr 478.3774 534.7571 560.8748 559.1787 585.5486 661.5337 100 b
## datatable 128.4965 146.4850 162.1112 153.6922 166.1464 312.0254 100 a