每每以为攀得众山小,可、每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~

———————————————————————————

由于业务中接触的数据量很大,于是不得不转战开始寻求数据操作的效率。于是,data.table这个包就可以很好的满足对大数据量的数据操作的需求。

data.table可是比dplyr以及Python中的pandas还好用的数据处理方式。

网络上充斥的是data.table很好,很棒,性能棒之类的,但是从我实际使用来看,就得泼个水,网上博客都是拿一些简单的案例数据,但是实际数据结构很复杂的情况下,批量操作对于data.table编码来说,会显得很繁琐,相比来说,让我多等1分钟的data.frame结构,我还是愿意等的。

data.table包的语法简洁,并且只需一行代码就可以完成很多事情。进一步地,data.table在某些情况下执行效率更高。(参考来源:R高效数据处理包dplyr和data.table,你选哪个?

在使用data.table时候,需要预先布置一下环境:

  1. data<-data.table(data)

如果不布置环境,很多内容用不了。或者通过as.data.table的操作来构建数据集。

一些老式的数据操作方法可以见我的其他博客:

R语言︱数据集分组、筛选(plit – apply – combine模式、dplyr、data.table)

同时,data.table与data.frame数据呈现方面,还有有所不同的。

data.table包提供了一个非常简洁的通用格式:DT[i,j,by],可以理解为:对于数据集DT,选取子集行i,通过by分组计算j。

注意:

data.table之后,一些常规的data.frame的操作就失效了,譬如:

data[,-1]、data[,1]这样的操作就不是这么用的了。

——————————————————————————————————————————————

一、重要的key()

data.table中的key是整个框架里面的灵魂,通过设置,data.table整个数据就会按照key变量重新排序。这意味着,输出的数据也是按照某种规律的,而且通过设置了Key,配套的代码编译也受到了简化。

设置key的方式有很多种:

1、创建数据时直接设置key

dt <- data.table(a=c('A','B','C','A','A','B'),b=rnorm(6),key="a")

2、setkey()函数设置

setkey(dt,a)

setkey(DT, colA, colB),可以使得检索和分组更加快速。同时设置两个key变量的方式,也是可以的。

查看数据集是否有key的方式:

key(data)    #检查该数据集key是什么?
haskey(data) #检查是否有Key
attributes(data)

key()可以告诉你,数据集中的Key是哪几个变量? 

haskey()输出结果为:true/false

——————————————————————————————————————————————

二、数据筛选

1、列筛选 .()

from_dplyr = select(tb, ID)
from_data_table = tb[,"ID"]
from_data_table = tb[,.(ID)]  

三种数据筛选的方式,dplyr包、base基础包、data.table包。其中,dplyr是select语句,data.table中要注意.()的表达方式。

而且,.()格式只在data.table格式下有效,不然会报错。data.table中,还有一个比较特立独行的函数:

使用:=引用来添加或更新一列(参考:R语言data.table速查手册

DT[, c("V1","V2") := list(round(exp(V1),2), LETTERS[4:6])]
DT[, c("V1","V2") := NULL]

通过list的方式来更新了数据,以及使用null的方式来删除列。

2、按条件行筛选

从前用subset的方式进行筛选比较多,

new<-subset(x,a>=14,select=a:f)

(1)单变量

现在data.table与dplyr

from_dplyr = filter(hospital_spending,State %in% c('CA','MA',"TX"))
from_data_table = hospital_spending_DT[State %in% c('CA','MA',"TX")]

dplyr用filter,content满足某种条件的进行筛选,而data.table的筛选方式很传统,比较简单。筛选hospital_spending_DT数据集中,State变量,满足"CA"、“MA”、"TX"内容的行。

在筛选列变量的数据,也可以与%in%集合运算联用(集合运算见博客:R语言︱集合运算)。

(2)多变量筛选,用&|等

from_dplyr = filter(tb,State=='CA' & Claim.Type!="Hospice")
from_data_table = hospital_spending_DT[State=='CA' & Claim.Type!="Hospice"]

(3)还有一些复杂结构:

dt[a=='B' & c2>3, b:=100]   #其他结构

在dt数据集中,筛选a变量等于"B",c2变量大于3,同时将添加b变量,数值等于100.

(4)★key的改造

通过预先设置key,然后再来进行筛选的方法,更加高效,而且节省时间。来看看例子:

ans1 <- try[try$gender=="M" & try$buy_online=="Y",]
#使用”==”操作符,那么它会扫描整个数组,虽然data.table用这种方法也可以提取,但很慢,要尽量避免。

setkey(try,gender,buy_online)  #设置key为两个变量,数据已经按照x值进行了重新排序
ans2 <- DT[list("M","Y")]      #更为简洁,并且迅速

这里有一个重要的点:使用”==”操作符,那么它会扫描整个数组,虽然data.table用这种方法也可以提取,但很慢,要尽量避免。
这里先设置key,然后直接通过list(M,Y)就可以达到第一条代码的效能,而且时间更短。

——————————————————————————————————————————————

三、数据排序

有了key,其实有了一定排序功能在里面。

from_dplyr = arrange(hospital_spending, State)
from_data_table = setorder(hospital_spending_DT, State)

from_dplyr = arrange(hospital_spending, desc(State))
from_data_table = setorder(hospital_spending_DT, -State)

dplyr中是arrange函数,而data.table是setorder函数,同时降序的方式。

dplyr的降序是,arrange(data,desc(x)),而data.table的降序是setorder(data,-x)

——————————————————————————————————————————————

四、分组求和、求平均

mygroup= group_by(try,gender,buy_online)
from_dplyr<-summarize(mygroup,mean=mean(new_car))                          #dplyr用两步    

from_data_table<-try[,.(mean=mean(new_car)),by=.(gender,buy_online)]       #data.table用一步

dplyr:先用group_by设置分组,然后利用summarize求平均,mean=mean();

data.table,在try数据集中,通过by=.(x,y)来分组,而且可以设定x/y两种分组,来求new_car的平均值。

(1)data.table多种方式混合输出:

mydata[,.(sum(Ozone,na.rm=T),sd(Ozone,na.rm=T))]                           #求和、求标准差操作
DT[,list(MySum=sum(v),
         MyMin=min(v),
         MyMax=max(v)),
   by=.(x)]                                                                #多种方式联合

多种方式混合,而且代码编译上也会有很多不同之处。DT数据集按照x分组,然后计算v变量的和、最小值、最大值。

(2)dplyr函数利用%>%(链式操作)来改进:

链式操作是啥意思呢?

%>%的功能是用于实现将一个函数的输出传递给下一个函数的第一个参数。注意这里的,传递给下一个函数的第一个参数,然后就不用写第一个参数了。在dplyr分组求和的过程中,还是挺有用的。

from_dplyr=try %>% group_by(gender,buy_online) %>% summarize(mean=mean(new_car))

——————————————————————————————————————————————

五、数据合并

最常见的合并函数就是merge,还有sql的方式(常见的合并方式可见:

R语言数据集合并、数据增减、不等长合并

)。

在data.table中有三类数据合并的方式:

1、直接用[]

data_one[data_two,nomatch=NA,mult="all"]

以第一个数据为基准,依据key进行合并,只出现重复部分(data_one数据必须设置key,data_two默认第一行为Key)。很简洁的方式,举例:

DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9)
X = data.table(c("b","c"),foo=c(4,2))
#以DT为基准
setkey(DT,x)
DT[X]
#以X数据集为基准
setkey(X,V1)
X[DT]

现在有DT、X两个数据集,先设置DT数据集的key,然后DT[X]来合并,后者相同。还有nomatch的设置可以见第六小节。

nomatch用来设置未匹配到的数据如何处理,nomatch=0则认为未匹配到的删除。

melt用来设置是否都显示匹配内容。

2、on=""方式

DT[X, on="x"]

这里的on指的是DT变量中的变量名称,X还是按照key,如果没设置就会默认第一行为key。

3、第三种方式:key-merge

setkey(DT,x)
setkey(X,V1)
merge(DT, X)

预先设置两个数据集的key后,也可以用比较常见的merge函数来进行数据合并。

——————————————————————————————————————————————

六、额外的参数(来源:R语言data.table速查手册

1、mult参数

mult参数是用来控制i匹配到的哪一行的返回结果默认情况下会返回该分组的所有元素 
返回匹配到键值所在列(V2列)所有行中的第一行

> DT["A", mult ="first"]
   V1 V2 V3 V4
1: 1 A -1.1727 1

2、nomatch参数——未匹配样本处理

nomatch参数用于控制,当在i中没有到匹配数据的返回结果,默认为NA,也能设定为0。0意味着对于没有匹配到的行将不会返回。 
返回匹配到键值所在列(V2列)所有包含变量值A或D的所有行:

 DT[c("A","D"), nomatch = 0]
   V1 V2    V3 V4
1: 1 A -1.1727 1
2: 2 A  0.6651 4
3: 1 A -1.0604 7
4: 2 A -0.3825 10

nomatch=0对于没有匹配到的将不显示。跟merge中的all差不多。

3、.SD和.SDcols

> DT[, lapply(.SD,sum), by=V2,
+    .SDcols = c("V3","V4")]
   V2      V3 V4
1:  A -1.2727 22
2:  B -1.2727 26
3:  C -1.2727 30

.SD是一个data.table,他包含了各个分组,除了by中的变量的所有元素。.SD只能在位置j中使用。
.SDcols常于.SD用在一起,他可以指定.SD中所包含的列,也就是对.SD取子集。

4、修改列名、行名

#把名字为"old"的列,设置为"new"
> setnames(DT,"old","new")
#把"V2","V3"列,设置为"V2.rating","V3.DataCamp"
> setnames(DT,c("V2","V3"),c("V2.rating","V3.DataCamp")) 

5、setcolorder()

#setcolorder()可以用来修改列的顺序。
setcolorder(DT,c("V2","V1","V4","V3"))
#这段代码会使得列的顺序变成:
 "V2" "V1" "V4" "V3"

——————————————————————————————————————————————

实战一:在data.table如何选中列,如何循环提取、操作data.table中的列?

在data.table行操作跟data.frame很像,可以data[1,]就可以获得第一行的数据,同时也可以用,data[1]来获得行信息,这个是data.table特有的。

除了行,就是列的问题了。在data.table操作列,真的是费劲。。。

常规来看,

data[,.(x)]   还有 data$x

如果有很多名字很长的指标,data.table中如果按列进行遍历呢?

data[,1]是不行的,选中列的方式是用列名。于是只能借助get+names的组合。

for (i in 1:5){
data[,.(get(names(data)[i]))]
}

这个是我目前在遍历时候用到的代码,不知道观众有没有更好的呢?

2016-11-28补充:


留言区大神给了一个比较好的选中列的方式,其中主要就是对with的使用:

data.table取列时,可以用data[,1,with=FALSE]取data的第一列,相对于对数据框的操作

这样就可以像普通的数据框一样使用,谢谢留言区大神!!!!

参考文献:

些许案例,代码参考自以下博客,感谢你们的辛勤:

1、R语言data.table简介

2、超高性能数据处理包data.table

3、R语言data.table速查手册

4、R高效数据处理包dplyr和data.table,你选哪个?

R︱高效数据操作——data.table包(实战心得、dplyr对比、key灵活用法、数据合并)的更多相关文章

  1. R语言数据分析利器data.table包—数据框结构处理精讲

    R语言数据分析利器data.table包-数据框结构处理精讲 R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代 ...

  2. R语言数据分析利器data.table包 —— 数据框结构处理精讲

        R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代码简洁,只要一行命令就可以完成诸多任务,另一方面是处理 ...

  3. R语言data.table包fread读取数据

    R语言处理大规模数据速度不算快,通过安装其他包比如data.table可以提升读取处理速度. 案例,分别用read.csv和data.table包的fread函数读取一个1.67万行.230列的表格数 ...

  4. data.table包简介

    data.table包主要特色是:设置keys.快速分组和滚得时序的快速合并.data.table主要通过二元检索法大大提高数据操作的效率,同时它也兼容适用于data.frame的向量检索法. req ...

  5. 使用 data.table 包操作数据

    在第一节中,我们回顾了许多用于操作数据框的内置函数.然后,了解了 sqldf 扩展包,它使得简单的数据查询和统计变得更简便.然而,两种方法都有各自的局限性.使用内置函数可能既繁琐又缓慢,而相对于各式各 ...

  6. R读取大数据data.table包之fread

    >library(data.table)>data=fread("10000000.txt")>Read 9999999 rows and 71 (of 71) ...

  7. data.table包

    data.table 1.生成一个data.table对象 生成一个data.table对象,记为DT. library(data.table) :],V3=round(rnorm(),),V4=:) ...

  8. data.table包使用应该注意的一些细节

    fread中nThread 参数的使用   注意默认nThread=getDTthreads(),即使用所有能用的核心,但并不是核心用的越多越好,本人亲自测试的情况下,其实单核具有较强的性能,只有在数 ...

  9. R语言学习笔记(十七):data.table包中melt与dcast函数的使用

    melt函数可以将宽数据转化为长数据 dcast函数可以将长数据转化为宽数据 > DT = fread("melt_default.csv") > DT family_ ...

随机推荐

  1. ios中pch文件的创建与配置

     PCH文件(Precompile Prefix Header File),也就是预编译头文件,其作用就是,方便你一次性导入在多个文件中同时用到的头文件.宏或者URL地址等(全局使用),可以有效的帮你 ...

  2. java indexof、BigDecimal、字符串替换

    自我总结,有什么需要改正弥补的地方,请指出,感激不尽! 本次总结了indexof的用法,BigDecimal的乘法.移位运算,Decimal的格式化输出,字符串替换 上代码: 测试类 Test.jav ...

  3. Android Training Note

    版本适配 Tip:为了能在几个Android版本中都能提供最好的特性和功能,你应该在你的app中使用Android Support Library,它能使你的app能在旧平台上使用最近的几个平台的AP ...

  4. 基于tomcat+springMVC搭建基本的前后台交互系统

    一.摘要 1.所需软件列表: 1) tomcat :  apache-tomcat-7.0.54  服务端容器 2) Intellij: Intellij IDEA 14.0.3         开发 ...

  5. js、jQuery实现2048小游戏

    2048小游戏 一.游戏简介:  2048是一款休闲益智类的数字叠加小游戏 二. 游戏玩法: 在4*4的16宫格中,您可以选择上.下.左.右四个方向进行操作,数字会按方向移动,相邻的两个数字相同就会合 ...

  6. web框架之Django基础

    1. Django的简介 Django是一个由python写成的开放源代码的Web应用框架. Django的目的是使常见的Web开发任务,快速和容易. 2. Django框架的特点 1. 遵循MVC开 ...

  7. 修改MacBook Pro主机名,共享电脑名

    https://support.apple.com/kb/PH25384?viewlocale=zh_CN&locale=zh_CN http://www.ituring.com.cn/art ...

  8. Django——ContentType及ContentType-signals的使用

    一.ContentType 在django中,有一个记录了项目中所有model元数据的表,就是ContentType,表中一条记录对应着一个存在的model,所以可以通过一个ContentType表的 ...

  9. sphinx初识

    sphinx(SQL Phrase Index),查询词组索引. 定义:Sphinx是一个全文检索引擎. 特性: 1.高速索引 (在新款CPU上,近10 MB/秒); 2.高速搜索 (2-4G的文本量 ...

  10. iOS中的定时器

    据我所知,iOS中的定时器有两种.一个叫NSTimer,一个叫CADisplayLink.还有一种是使用GCD,不常用,这里就不介绍了. 下边说下两个定时器分别得用法: =============== ...