R高效数据处理包

R高效数据处理包

标签(空格分隔): R dplyr data.table


之前在某公司实习的时候,需要结合shiny从数据库选取数据进行网页实时交互的可视化。然而我发现每次类似于 updateSelectizeInput 的更新数据,我都会直接操作数据库select * from * where *,结果运行的时候发现实时更新贼慢,根本不是实时交互啊,至少延迟一分钟(几十万级数据集)。于是,去请教总工,总工就指导我学习dplyrdata.table,一试简直让我喜极而泣啊,延迟减少到了十秒钟。由于效果显著,就把它献给我的第一篇博客,上交学习心得体会。

dplyr

高效处理大量数据,可以高效快速的对数据进行筛选、变形、汇总、分组、管道等各式各样的数据处理操作

1. 数据集

本文用datasets中的airquality来做实验。

library(dplyr)
library(datasets)
head(airquality) ##dplyr有类似的函数tbl_df()
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6

2.管道操作符 %>%

R的管道操作符%>%,可以省略第一个参数,可以链接一长串的操作函数。当对数据进行一系列的操作而又不想一个一个保存中间值,这无疑是一个最佳选择。

airquality%>%filter(Month==5)%>%group_by(Month)%>%summarize(mean(Temp,na.rm=TRUE))

 Month `mean(Temp, na.rm = TRUE)`
  <int>                      <dbl>
1     5                   65.54839

3.筛选:select/filter

3.1 筛选列select()

根据列名选取某几列:
airquality%>%select(Ozone,Month,Day)

 Ozone Month Day
1    41     5   1
2    36     5   2
3    12     5   3
4    18     5   4
5    NA     5   5
6    28     5   6

:,根据范围选择列:
airquality%>%select(Ozone:Month)

  Ozone Solar.R Wind Temp Month
1    41     190  7.4   67     5
2    36     118  8.0   72     5
3    12     149 12.6   74     5
4    18     313 11.5   62     5
5    NA      NA 14.3   56     5
6    28      NA 14.9   66     5

-,选取除该列之外的列:
airquality%>%select(-Ozone,-Month)

  Solar.R Wind Temp Day
1     190  7.4   67   1
2     118  8.0   72   2
3     149 12.6   74   3
4     313 11.5   62   4
5      NA 14.3   56   5
6      NA 14.9   66   6

starts_with(),选取以某字符串开头列名的列:
airquality%>%select(starts_with('S'))

  Solar.R
1     190
2     118
3     149
4     313
5      NA
6      NA

ends_with(),选取以某字符串结尾的列名的列:
airquality%>%select(ends_with('d'))

 Wind
1  7.4
2  8.0
3 12.6
4 11.5
5 14.3
6 14.9

contains(),选取包含某字符串的列名的列:
airquality%>%select(contains('o'))

 Ozone Solar.R Month
1    41     190     5
2    36     118     5
3    12     149     5
4    18     313     5
5    NA      NA     5
6    28      NA     5

matcthes(),选取符合正则匹配的列名的列:
airquality%>%select(matches('So?'))

  Solar.R
1     190
2     118
3     149
4     313
5      NA
6      NA

one_of(),从一组列名里选择列:
airquality%>%select(one_of('Day','year','Month'))

  Day Month
1   1     5
2   2     5
3   3     5
4   4     5
5   5     5
6   6     5
3.2 筛选行filter()

使用逻辑操作符(>、<、>=、<=、%in%,&,|等)来构成逻辑表达式

airquality%>%filter(Month==5 & Day>=10)

 Ozone Solar.R Wind Temp Month Day
1    NA     194  8.6   69     5  10
2     7      NA  6.9   74     5  11
3    16     256  9.7   69     5  12
4    11     290  9.2   66     5  13
5    14     274 10.9   68     5  14
6    18      65 13.2   58     5  15

airquality%>%filter(Month %in% c(6,7,10))

Ozone Solar.R Wind Temp Month Day
1    NA     286  8.6   78     6   1
2    NA     287  9.7   74     6   2
3    NA     242 16.1   67     6   3
4    NA     186  9.2   84     6   4
5    NA     220  8.6   85     6   5
6    NA     264 14.3   79     6   6

4. 对行排序 arrange()

airquality%>%arrange(desc(Month),Day)

 Ozone Solar.R Wind Temp Month Day
1      96     167  6.9   91     9   1
2      78     197  5.1   92     9   2
3      73     183  2.8   93     9   3
4      91     189  4.6   93     9   4
5      47      95  7.4   87     9   5
6      32      92 15.5   84     9   6
7      20     252 10.9   80     9   7
8      23     220 10.3   78     9   8
9      21     230 10.9   75     9   9
10     24     259  9.7   73     9  10

airquality%>%arrange(Month,Day)%>%filter(Month<=8)%>%head

Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6

5. 添加新列,mutate()

airquality%>%mutate(TempInC=(Temp-32)*5/9)%>%head

Ozone Solar.R Wind Temp Month Day  TempInC
1    41     190  7.4   67     5   1 19.44444
2    36     118  8.0   72     5   2 22.22222
3    12     149 12.6   74     5   3 23.33333
4    18     313 11.5   62     5   4 16.66667
5    NA      NA 14.3   56     5   5 13.33333
6    28      NA 14.9   66     5   6 18.88889

6. 计算某个变量的统计特性,summarise()

summarise()可以计算某列的统计特征,结合如sd(),mean(),min(),max(),median(),sum(),n()(返回变量向量的长度),first()(返回向量的第一个值),last()n_distinct()(变量向量中不同值的数量)等函数

airquality%>%summarise(min(Wind))

  min(Wind)
1       1.7

summarise_each()允许对多列同时进行统计(PS:我在R上试验,提醒已经逐渐弃用summarise_each(),推荐使用summarise_at())

airquality%>%summarise_at(c('Month','Day'),mean)
airquality%>%summarise_each(funs(mean),Month,Day)

     Month      Day
1 6.993464 15.80392

7. 根据某列值去掉重复行,distinct()

airquality%>%distinct(Month,.keep_all=TRUE) ## keep_all参数设置选择所有列,默认为FALSE

Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    NA     286  8.6   78     6   1
3   135     269  4.1   84     7   1
4    39      83  6.9   81     8   1
5    96     167  6.9   91     9   1

8. 分组,group_by

group_by
group_by()是dplyr中的一个重要函数。正如我们之前提到的,它与“分拆适用组合”的概念有关。我们实际上想要通过一些变量拆分数据观测值,将功能应用于各组数据,然后组合输出。

airquality%>%group_by(Month)%>%summarise(min(Wind))

Month `min(Wind)`
  <int>       <dbl>
1     5         5.7
2     6         1.7
3     7         4.1
4     8         2.3
5     9         2.8

ungroup()从数据中移除分组信息

9. dplyr中关于结合两个数据表(x,y)的函数

inner_join :只包含同时出现在x,y表中的行
left_join: 包含所有x中以及y中匹配的行
right_join: 包含所有y中以及x中匹配的行
full_join: 包含x,y中所有的行和列
semi_join:包含x中,在y中有匹配的行
anti_join: 包含x中不匹配y的行


data.table

fread()Similar to read.table but faster and more convenient. fread() accepts http and https URLs directly as well as operating system commands such as sed and awk output

data=fread('E:/ds/R dplyr/flights2014.csv')

data.table与数据库相对应的语法规则,对于数据集DT,i选取行,根据分组by对列j进行计算

DT[i, j, by]

##   R:      i                 j        by
## SQL:  where   select | update  group by

1. Basics-数据筛选

1.1 按条件筛选行

对应于R的基本函数subset()、dplyr的filter(),data.table()筛选行的方式比较简单。

单变量筛选
data[month %in% c(5,6,7,8)]

      year month day dep_time dep_delay arr_time arr_delay
     1: 2014     5   1     1743        43     1955         5
     2: 2014     5   1      759        -1     1057       -38
     3: 2014     5   1     1540         0     1854        14
     4: 2014     5   1     1823        78     2104        54
     5: 2014     5   1      756        -4      912         2
    ---                                                     
106459: 2014     8  31     1123        -7     1251       -29
106460: 2014     8  31     1542        -8     1714       -11
106461: 2014     8  31     1502        -8     1638       -12
106462: 2014     8  31     1847        18     2039        25
106463: 2014     8  31     1441       126     1557       107

多变量筛选
data[month %in% c(5,6,7,8) & day>=20]

  year month day dep_time dep_delay arr_time arr_delay
    1: 2014     5  20     1656        -4     1933        -7
    2: 2014     5  20      758        -7     1143         8
    3: 2014     5  20     1620         0     1841       -39
    4: 2014     5  20     1710        -5     1959       -16
    5: 2014     5  20      815        -5      924        -6
   ---                                                     
41115: 2014     8  31     1123        -7     1251       -29
41116: 2014     8  31     1542        -8     1714       -11
41117: 2014     8  31     1502        -8     1638       -12
41118: 2014     8  31     1847        18     2039        25
41119: 2014     8  31     1441       126     1557       107

切片操作
data[1:5]

year month day dep_time dep_delay arr_time arr_delay
1: 2014     1   1      914        14     1238        13
2: 2014     1   1     1157        -3     1523        13
3: 2014     1   1     1902         2     2224         9
4: 2014     1   1      722        -8     1014       -26

根据变量对行进行排序
data[order(-month,arr_time)] ##默认升序,加‘-‘表示降序排

  year month day dep_time dep_delay arr_time arr_delay
     1: 2014    10   1     2113        43        1        70
     2: 2014    10   1     2255       146        1       130
     3: 2014    10   2     2014        49        1       132
     4: 2014    10   5     2109        84        1        59
     5: 2014    10  12     2100         0        1       -24
1.2 筛选列

筛选列,返回的形式为vector
head(data[,arr_delay])

[1]  13  13   9 -26   1   0

筛选列,返回的形式为data.table,使用list()装饰列或者DT[,.(colnames)]
head(data[,list(arr_delay)])
head(data[,.(arr_delay)])

  arr_delay
1:        13
2:        13
3:         9
4:       -26
5:         1
6:         0

对筛选出的重命名
head(data[,.(delay_arr=arr_delay)])

 delay_arr
1:        13
2:        13
3:         9
4:       -26
5:         1
6:         0

Special Notes:使用参数with=False,可以像普通的数据框一样对行/列进行操作,使用列的名称或者索引筛选列
data[,c('day','month'),with=FALSE]
data[,c(3,2),with=FALSE]

   day month
     1:   1     1
     2:   1     1
     3:   1     1
     4:   1     1
     5:   1     1
1.3 对筛选的列进行操作和计算

data.table的j可以处理不仅仅是选择列 ——它可以处理表达式,即对列进行计算。这不应该是令人惊讶的,因为列可以被称为是变量。那么我们应该能够通过调用这些变量的函数来计算。

data[,sum((arr_delay+dep_delay)<0)]

141814
1.4 筛选行并对列进行计算

data[origin=='JFK'&month==6,.(m_arr=mean(arr_delay),m_dep=mean(dep_delay))]

 m_arr    m_dep
1: 5.839349 9.807884

Special symbol .N:
.N是一个特殊的内置变量,用于保存当前组中的观察次数。当我们与gruop_by结合在一起特别有用。没有分组操作的情况下,它只返回子集中的行数。相当于对筛选出的行任何一列,执行length()函数
data[origin=='JFK'&month==6,.N]
nrow(data[origin=='JFK'&month==6])

8422

2. 整合函数

2.1 使用by进行分组

data[,.(.N),by=.(origin)]
data[,.(.N),by='origin']

 origin     N
1:    JFK 81483
2:    LGA 84433
3:    EWR 87400

j中只有一个列或表达式被引用时,我们可以删除符号。这纯粹是为了方便。我们可以改为:
data[,.N,by=origin]

by可以接受多列作为输入,我们只需要提供分组所需的列:
data[carrier=='AA',.(.N),by=.(origin,dest)]

 origin dest    N
 1:    JFK  LAX 3387
 2:    LGA  PBI  245
 3:    EWR  LAX   62
 4:    JFK  MIA 1876
 5:    JFK  SEA  298
 6:    EWR  MIA  848
 7:    JFK  SFO 1312

data[carrier=='AA',.(arr_mean=mean(arr_delay),dep_mean=mean(dep_delay)),by=.(origin,dest,month)]

 origin dest month   arr_mean   dep_mean
  1:    JFK  LAX     1   6.590361 14.2289157
  2:    LGA  PBI     1  -7.758621  0.3103448
  3:    EWR  LAX     1   1.366667  7.5000000
  4:    JFK  MIA     1  15.720670 18.7430168
  5:    JFK  SEA     1  14.357143 30.7500000
2.2 排序-keyby

data[carrier=='AA',.(arr_mean=mean(arr_delay),dep_mean=mean(dep_delay)),keyby=.(origin,dest,month)]

origin dest month   arr_mean   dep_mean
  1:    EWR  DFW     1   6.427673 10.0125786
  2:    EWR  DFW     2  10.536765 11.3455882
  3:    EWR  DFW     3  12.865031  8.0797546
  4:    EWR  DFW     4  17.792683 12.9207317
  5:    EWR  DFW     5  18.487805 18.6829268

Special Notes:实际上,keyby做的不仅仅是排序,它也可以通过设置一个叫sorted的属性值在排序之后设置一个key值。

2.3 联合操作

可以一个接一个地表达形式,形成一连串的操作 DT[ … ][ … ][ … ].
或者:
DT[ …
][ …
][ …
]

data[carrier=='AA',.(arr_mean=mean(arr_delay),dep_mean=mean(dep_delay)),keyby=.(origin,dest,month)][order(origin,-dest)]

 origin dest month  arr_mean   dep_mean
  1:    EWR  PHX     7 -5.103448  0.2758621
  2:    EWR  PHX     8  3.548387  6.2258065
  3:    EWR  PHX     9 -4.233333 -1.6666667
  4:    EWR  PHX    10 -3.032258 -4.2903226
  5:    EWR  MIA     1 11.011236 12.1235955
2.4 by中的表达式

data[,.N,.(dep_delay>0,arr_delay>0)]

dep_delay arr_delay      N
1:      TRUE      TRUE  72836
2:     FALSE      TRUE  34583
3:     FALSE     FALSE 119304
4:      TRUE     FALSE  26593
2.5 对多列同时进行运算,j-`.SD

Special symbol:.SD它表示子集或数据, 它本身就是一个data.table,它保存了运行by后的分组数据

DT
  ID a  b  c
1  b 1  7 13
2  b 2  8 14
3  b 3  9 15
4  a 4 10 16
5  a 5 11 17
6  c 6 12 18

DT<-as.data.table(DT)
DT[,print(.SD),by=ID]

 a b  c
1: 1 7 13
2: 2 8 14
3: 3 9 15
   a  b  c
1: 4 10 16
2: 5 11 17
   a  b  c
1: 6 12 18

.SD包含了除分组列外的所有列,并且保存了和原始数据顺序一样的分组数据结果。对多列进行运算,可以使用R的基本函数lapply()

DT[,lapply(.SD,mean),by=ID]

 ID   a    b    c
1:  b 2.0  8.0 14.0
2:  a 4.5 10.5 16.5
3:  c 6.0 12.0 18.0

Special symbol:.SDcols,表示只对指定的几列进行运 算,它的参数为列名或者列的索引。与with=FALSE相似,也可以使用-或者!删除不需要的列,或者选择连续的列colA:colB,不选择某些连续的列!(colA:colB)或者-(colA:colB)

data[carrier=='AA',lapply(.SD,mean),by=.(origin,dest,month),.SDcols=c('arr_delay','dep_delay')]

origin dest month  arr_delay  dep_delay
  1:    JFK  LAX     1   6.590361 14.2289157
  2:    LGA  PBI     1  -7.758621  0.3103448
  3:    EWR  LAX     1   1.366667  7.5000000
  4:    JFK  MIA     1  15.720670 18.7430168
  5:    JFK  SEA     1  14.357143 30.7500000
2.6 使用.SD提取分组后的子集

data[,head(.SD,2),by=month]

 month year day dep_time dep_delay arr_time arr_delay
 1:     1 2014   1      914        14     1238        13
 2:     1 2014   1     1157        -3     1523        13
 3:     2 2014   1      859        -1     1226         1
 4:     2 2014   1     1155        -5     1528         3
 5:     3 2014   1      849       -11     1306        36
 6:     3 2014   1     1157        -3     1529        14
 7:     4 2014   1     1812        -8     1927       -23
 8:     4 2014   1     1812        -8     1949       -11
2.7 位置j使用的灵活性

DT[,.(val=c(a,b)),by=ID]##使用基本函数c()并联向量

ID val
 1:  b   1
 2:  b   2
 3:  b   3
 4:  b   7
 5:  b   8
 6:  b   9
 7:  a   4
 8:  a   5
 9:  a  10
10:  a  11
11:  c   6
12:  c  12

如果想要返回的是一个list型,使用list()来装饰
DT[,.(val=list(c(a,b))),by=ID]

 ID         val
1:  b 1,2,3,7,8,9
2:  a  4, 5,10,11
3:  c        6,12

一旦开始内部使用j,你会意识到语法的强大程度。一个非常有用的方式来理解它是在print()的帮助下。

## (1) look at the difference between
DT[, print(c(a,b)), by = ID]
# [1] 1 2 3 7 8 9
# [1]  4  5 10 11
# [1]  6 12
# Empty data.table (0 rows) of 1 col: ID

## (2) and
DT[, print(list(c(a,b))), by = ID]
# [[1]]
# [1] 1 2 3 7 8 9
# 
# [[1]]
# [1]  4  5 10 11
# 
# [[1]]
# [1]  6 12
# Empty data.table (0 rows) of 1 col: ID

在(1)中,对于每个组,返回一个向量,其长度为6,4,2。然而,(2)返回每个组的长度为1的列表,其第一个元素保持向量为6,4,2。因此(1)返回6 + 4 + 2 = 12的长度,而(2)返回1 + 1 + 1 = 3

基础使用部分就先到这了,更多细节请移步官网https://github.com/Rdatatable/data.table/wiki/Getting-started

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值