第五章:数据操作Ⅱ 第四节:数据表:更快、更方便的数据框(上)

数据表相对于数据框,运行速度更快,使用时也更加方便,实际使用时完全可以取代数据框,数据表有两个优势,第一是运行速度更快,第二是运算十分便利。

我们先安装数据表

install.packages("data.table")
library(data.table)

一、创建数据表

跟数据框的创建手法一致,我们可以使用data.table()来创建数据框,此外,我们可以使用as.data.frame()/as.data.table()函数可以在数据框和数据表之间转换

例如,我们将鸢尾花数据集转换为数据表

> (iris.table<-as.data.table(iris))
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
            <num>       <num>        <num>       <num>    <fctr>
  1:          5.1         3.5          1.4         0.2    setosa
  2:          4.9         3.0          1.4         0.2    setosa
  3:          4.7         3.2          1.3         0.2    setosa
  4:          4.6         3.1          1.5         0.2    setosa
  5:          5.0         3.6          1.4         0.2    setosa
 ---                                                           
146:          6.7         3.0          5.2         2.3 virginica
147:          6.3         2.5          5.0         1.9 virginica
148:          6.5         3.0          5.2         2.0 virginica
149:          6.2         3.4          5.4         2.3 virginica
150:          5.9         3.0          5.1         1.8 virginica

我们也可以发现一个特征,就是数据表输出的时候是不会一口气将所有数据输出的,只会输出前面和尾部几行,如果要多输出几行,可以指定行号,例如(iris_table[1:n,])

跟数据框一样,数据表也可以原地创建

> (x<-data.table(x=c(1,2,3),y=c("a","b","c")))
       x      y
   <num> <char>
1:     1      a
2:     2      b
3:     3      c

根据下列代码我们可以得知,数据表类包含数据框data.frame,所以处理数据框所用的函数同样适用于数据表,如果出现了问题,直接用转换函数转换为数据框即可。

> class(data.table())
[1] "data.table" "data.frame"

我们可以使用tables()函数来预览目前创建的所有数据表的简略信息,同时也会告诉你内存消耗量

> tables()
         NAME NROW NCOL MB                                                      COLS KEY
1: iris.table  150    5  0 Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species   
2:          x    3    2  0                                                       x,y   
Total: 0MB using type_size

二、数据访问与分组运算

数据表中的数据采用[行,表达式,选项]的形式进行访问,其中行可以是行号,也可以是用来选择某些行的逻辑值

> DT<-as.data.table(iris)
> DT[1,]
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <num>       <num>        <num>       <num>  <fctr>
1:          5.1         3.5          1.4         0.2  setosa
> DT[DT$Species=="setosa"]
    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
 1:          5.1         3.5          1.4         0.2  setosa
 2:          4.9         3.0          1.4         0.2  setosa
 3:          4.7         3.2          1.3         0.2  setosa
 4:          4.6         3.1          1.5         0.2  setosa

在访问数据表时,[]的第二参数是列名或与列名有关的表达式,若希望得到多个列,可以使用列表罗列,例如,我们向访问iris数据集的第一行的Sepal.length列

> DT[1,Sepal.Length]
[1] 5.1

我们想要得到数据表的多个列,可以使用列表来呈现

> DT[1,list(Sepal.Length,Species)]
   Sepal.Length Species
          <num>  <fctr>
1:          5.1  setosa

 

同时,第二个参数也可以是包含列名的表达式,表达式中含有多种运算,例如,我们计算Sepal.Length平均值

> DT[,mean(Sepal.Length)]
[1] 5.843333

如果我们想将数据表中将[]的第二个参数设置为包含列名的字符串或者列号,则要使用with=False函数,否则第二个参数中的字符会被视为运算表达式

DT<-as.data.table(iris)
> head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
> iris[1,1]
[1] 5.1
> DT[1,1]
   Sepal.Length
          <num>
1:          5.1

注:R已经默认将列名视为对象的一部分,因此不需要显式地设置with参数来进行选择。这种改变使得代码更加简洁和易读。因此这边只算是简单示例一下,提一嘴

数据表的第三个参数用于设置数据分组变量,比如,我们可以设置根据Specise求各品种的Sepal.Length

> DT[,mean(Sepal.Length),by="Species"]
      Species    V1
       <fctr> <num>
1:     setosa 5.006
2: versicolor 5.936
3:  virginica 6.588

当然,在遇到多个分组变量时,只要将其在by中列出即可。例如,我们根据y,z来求x的平均值

> DT<-data.table(x=c(1,2,3,4,5),y=c("a","a","a","b","b"),z=c("c","c","d","d","d"))
> DT
       x      y      z
   <num> <char> <char>
1:     1      a      c
2:     2      a      c
3:     3      a      d
4:     4      b      d
5:     5      b      d
> DT(,mean(x),by="y,z")
Error in DT(, mean(x), by = "y,z") : 没有"DT"这个函数
> DT[,mean(x),by="y,z"]
        y      z    V1
   <char> <char> <num>
1:      a      c   1.5
2:      a      d   3.0
3:      b      d   4.5

三、使用key快速访问数据

数据表可以实现二叉搜索树的索引,让查找数据变得更加便利,比数据框快得多

创建好键后,使用x[j(….),表达式],语法接口通过键来查找含有….中指定值的行,若表达式为空,则原样返回数据表的列,若表达式中含有运算,则返回运算结果

例如:数据框DF中含有X,Y两列,x中保存这连续均匀分布的随机数,y中保存着26个字母,,每个字母重复1000000次,要求从DF中找出y值为C的所有行,我们用system.time()函数来评估查找时间

> DF<-data.frame(X=runif(260000),y=rep(LETTERS,each=1000000))
> str(DF)
'data.frame':        260000000 obs. of  2 variables:
 $ X: num  0.2761 0.6006 0.4095 0.0815 0.1753 ...
 $ y: chr  "A" "A" "A" "A" ...
> head(DF)
           X y
1 0.27607233 A
2 0.60057455 A
3 0.40952382 A
4 0.08149889 A
5 0.17530720 A
6 0.15000765 A
> system.time(DF[DF$y == "C", ])
用户 系统 流逝

0.21 0.00 0.20

我们可以发现花费0.2秒,但当我们对y创建索引,然后使用y值检索时使用索引后,速度会变得非常快尤其是在检索次数很多,数据量很大的时候

> DT<-as.data.table(DF)
> setkey(DT,y)
> system.time(DT[J("C"),])
用户 系统 流逝
   0    0    0

如果我们想将多个列创建为键,只要将多个列在setkey()函数中累出即可,即setkey(DT,列名1,列名2),然后使用J(列名1,列名2….)形式,列出键并检索数据,数据表的第二个参数可以是含有列名的表达式,所以可以在检索同时执行指定运算

例如:

> DT[J("A"),mean(X)]
[1] 0.4998012

如果希望得到多个计算结果,只需在list()中给出表达式,此时,给出表达式形式若为tag=value,则tag作为列名出现在结果中

例如:我们求上述数据表中x的平均值和标准差

> DT[J("A"),list(x_mean=mean(X),x_std=sd(X))]
      x_mean     x_std
       <num>     <num>
1: 0.4998012 0.2885001
  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值