knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
我的R语言小伙伴最近分享了自己使用R来做工业级数据清洗的经验,最近我自己在不断测试我的新包tidyfst,因此就拿这个data.table的案例来尝试一下。
本次测试,将不会加载data.table包,但是其实tidyfst里面无处不是data.table的元素,而且也导出了很多内置的data.table函数,比如as.data.table和data.table。所以这些代码在tidyfst中就可以自如地使用。
library(tidyfst) diamonds <- ggplot2::diamonds n = 1e5 #如果想做工业级测试,可以继续增加数量 set.seed(2020) dtranges <- seq.Date(from = as.Date("2011-01-01"), to = as.Date("2020-01-01"), by = 1) n1 <- sample(nrow(diamonds), n, replace = TRUE) dat1 <- as.data.table(diamonds[n1, ]) dat1[, "dt"] <- sample(dtranges, n, replace = TRUE) # 增加dt列 n2 <- sample(nrow(dat1), nrow(dat1)/1000) dat1[n2, "price"] <- NA # price列构造千分之一缺失值 dat2 <- data.table(dt = sample(dtranges, min(n/1000, length(dtranges))), price1 = sample(1000, min(n/1000, length(dtranges)), replace = TRUE)) dat3 <- data.table(dt = sample(dtranges, min(n/1000, length(dtranges))), price2 = sample(1000, min(n/1000, length(dtranges)), replace = TRUE)) print(dat1)
后面的分析,经常要根据日期进行计算。所以,先对日期进行排序,就能够提高运行速度。在tidyfst中,可以使用arrange_dt
函数来对数据进行原位的各种操作,其中就包括排序。
dat1 = arrange_dt(dat1,dt) dat1
那么,现在dat1的数据就按照日期排好序了。
在tidyfst中,我设置了一个sys_time_print
函数,可以方便地输出system.time()
函数返回的结果。
sys_time_print({ r1_1 <- dat1 %>% summarise_dt( by = .(cut,color), mean_price = mean(price, na.rm = TRUE), median_price = median(price, na.rm = TRUE), max_price = max(price, na.rm = TRUE) ) }) r1_1
tidyfst是永远不可能比data.table快的,但是如果你觉得上面的代码更容易掌握、更容易读懂,而在日常工作中多花零点几秒的运行时间没有太大问题(实际上节省了大家的交流时间,甚至就是节省将来自己再次读懂自己代码的时间),tidyfst就值得拥有。
sys_time_print({ r1_2 <- dat1 %>% arrange_dt(dt,-price) %>% drop_na_dt(price) %>% group_dt( by = dt, head(1) ) }) r1_2
实质上,merge函数已经优化得很好。tidyfst设计*_join
系列函数的时候,只是为了一种不一样的语法结构来帮助实现不同的连接,因为它确实更加直观一些。但是实质上它还是merge.data.table函数的包装版本。
sys_time_print({ r2_1 <- dat1 %>% left_join_dt(dat2,by = "dt") }) r2_1
sys_time_print({ mymerge <- function(x, y) left_join_dt(x, y, by = "dt") r2_2 <- Reduce(mymerge, list(dat1, dat2, dat3)) }) r2_2
sys_time_print({ mean1 <- function(x) mean(x, na.rm = TRUE) max1 <- function(x) max(x, na.rm = TRUE) r3_1 <-dat1 %>% wider_dt(cut, value = c("depth", "price"), name = "color", fun = list(mean1,max1)) }) r3_1
sys_time_print({ r3_2 <-dat1 %>% select_dt(cut,color,x,y,z) %>% longer_dt(cut,color, name = "xyz", value = "xyzvalue") }) r3_2
对于填充空值来说,可以这样操作:
sys_time_print({ dat1 %>% fill_na_dt(price) -> dat1 }) dat1
sys_time_print({ mutate_dt(dat1, mean_price = mean(price, na.rm = TRUE), sd_price = sd(price, na.rm = TRUE), by = .(cut, color)) }) dat1
sys_time_print({ dat1 %>% group_dt( by = dt, mutate_dt(id = seq(.N)) ) -> dat1 }) dat1
sys_time_print({ dat1 %>% group_dt( by = color, mutate_dt( MA10_price = frollmean(price, 10), MSD10_price = frollapply(price, 10, FUN = sd) ) ) -> dat1 }) dat1
sessionInfo()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.