使用 data.table 包操作数据
在第一节中,我们回顾了许多用于操作数据框的内置函数。然后,了解了 sqldf 扩展
包,它使得简单的数据查询和统计变得更简便。然而,两种方法都有各自的局限性。使用
内置函数可能既繁琐又缓慢,而相对于各式各样的 R 函数来说,SQL 又不够强大,所以用
sqldf 进行数据的汇总统计,也不容易。
data.table 包提供了一个加强版的 data.frame。它运行效率极高,而且能够处
理适合内存的大数据集,它通过 [ ] 实现了一种自然的数据操作语法。如果尚未安装,
请运行以下命令:
install.packages("data.table")
安装成功后,我们就可以加载它,并查看它都提供了些什么:
library(data.table)
##
## Attaching package: 'data.table'
## The following objects are masked from 'package:reshape2':
##
## dcast, melt
注 意 到, 前 面 加 载 的 reshape2 包 中 已 经 定 义 了 dcast( ) 和 melt( ) 。
data.table 包提供了加强版的 dcast( ) 和 melt( ),它们的功能更强大,性能更高,
内存使用也更高效。本节的后续部分我们将介绍它们。
创建一个 data.table 与创建一个 data.frame 非常相似:
dt <- data.table(x = 1:3, y = rnorm(3), z = letters[1:3])
d
## x y z
## 1: 1 -0.2469598 a
## 2: 2 1.4126529 b
## 3: 3 -1.2174483 c
通过 str( ) 查看它的结构:
str(dt)
## Classes 'data.table' and 'data.frame': 3 obs. of 3 variables:
## $ x: int 1 2 3
## $ y: num -0.247 1.413 -1.217
## $ z: chr "a" "b" "c"
## - attr(*, ".internal.selfref") = <externalptr>
很明显,dt 的类是 data.table 和 data.frame,这意味着 data.table 继承自
data.frame。换句话说,它继承了 data.frame 的一些行为,但是增强了其他部分。
data.table 的基本语法 dt[i,j,by]。简单来说,就是使用 i 选择行,用 by 分组,
然后计算 j。接下来我们就看看 data.table 具体继承了什么,增强了什么。
首先,仍然先载入产品数据。但这次我们使用 data.table 包中的 fread( )函数来
读取数据。fread( ) 函数非常快,内存效率很高,而且直接返回了 data.table:
product_info <- fread("data/product-info.csv")
product_stats <- fread("data/product-stats.csv")
product_tests <- fread("data/product-tests.csv")
toy_tests <- fread("data/product-toy-tests.csv")
如果查看 product_info,可以看到它的数据格式与 data.frame 几乎是一样:
product_info
## id name type class released
## 1: T01 SupCar toy vehicle yes
## 2: T02 SupPlane toy vehicle no
## 3: M01 JeepX model vehicle yes
## 4: M02 AircraftX model vehicle yes
## 5: M03 Runner model people yes
## 6: M04 Dancer model people no
再次查看它的结构:
str(product_info)
## Classes 'data.table' and 'data.frame': 6 obs. of 5 variables:
## $ id : chr "T01" "T02" "M01" "M02" ...
## $ name : chr "SupCar" "SupPlane" "JeepX" "AircraftX" ...
## $ type : chr "toy" "toy" "model" "model" ...
## $ class : chr "vehicle" "vehicle" "vehicle" "vehicle" ...
## $ released: chr "yes" "no" "yes" "yes" ...
## - attr(*, ".internal.selfref")=<externalptr>
与 data.frame 不同,如果对 data.table 只提供一个参数来构建子集的话,是选
择行而不是选择列:
product_info[1]
## id name type class released
## 1: T01 SupCar toy vehicle yes
product_info[1:3]
## id name type class released
## 1: T01 SupCar toy vehicle yes
## 2: T02 SupPlane toy vehicle no
## 3: M01 JeepX model vehicle yes
如果为 [ ] 提供负值,意味着排除对应记录(行),这与构建向量子集完全一致:
product_info[-1]
## id name type class released
## 1: T02 SupPlane toy vehicle no
## 2: M01 JeepX model vehicle yes
## 3: M02 AircraftX model vehicle yes
## 4: M03 Runner model people yes
## 5: M04 Dancer model people no
此外,data.table 也提供了许多特殊符号,它们是data.table 的重要组成部分。.N 是
最有用的符号之一,它表示在当前的分组中,对象的数目(即每组的行数)。有了这个符号,我们
就不必再用nrow(product_info) 计算行数。但是在 [ ] 中单独使用 .N 是指提取最后一行:
product_info[.N]
## id name type class released
## 1: M04 Dancer model people no
也可以轻松地选择第一和最后一行:
product_info[c(1, .N)]
## id name type class released
## 1: T01 SupCar toy vehicle yes
## 2: M04 Dancer model people no
在对 data.table 构建子集时,能够根据语义自动地计算表达式。也就是说,在选取列
时,可以直接使用列名,就像使用 subset( )、transform( ) 和 with( )一样。例如,
选择已经发布的产品时,我们可以直接使用 released 作为第 1 个参数来选择满足条件的行:
product_info[released == "yes"]
## id name type class released
## 1: T01 SupCar toy vehicle yes
## 2: M01 JeepX model vehicle yes
## 3: M02 AircraftX model vehicle yes
## 4: M03 Runner model people yes
方括号内的第 1 个参数是行筛选器,第 2 个则对筛选后的数据进行适当地计算(包括
选择某些列或执行某个表达式)。例如,我们可以直接使用 id 来表达 roduct_info$id,
这里提取满足 released 取值为 yes 的 id 列:
product_info[released == "yes", id]
## [1] "T01" "M01" "M02" "M03"
而选择 data.frame 的列的方式(“id”)在这里不起作用。如果把一个字符向量作为
第 2 个参数,就会得到这个字符向量本身,因为一个字符串就只是表示一个字符串,可以
试一下:
product_info[released == "yes", "id"]
## [1] "id"
为了避免这种情况,我们可以设定 with = FALSE。这样,第 2 个参数就可以根据字
符向量选择列,并且不论指定多少列,总是返回 data.table:
product_info[released == "yes", "id", with = FALSE]
## id
## 1: T01
## 2: M01
## 3: M02
## 4: M03
product_info[released == "yes", c("id", "name"), with = FALSE]
## id name
## 1: T01 SupCar
## 2: M01 JeepX
## 3: M02 AircraftX
## 4: M03 Runner
第 2 个参数也可以是表达式。例如,生成一张表,用于反映每种 type 和 class 的组
合中的 released 取值为 yes 的产品数量:
product_info[released == "yes", table(type, class)]
## class
## type people vehicle
## model 1 2
## toy 0 1
要注意是,给第 2 个参数提供 list(),它仍然会被转换为 data.table:
product_info[released == "yes", list(id, name)]
## id name
## 1: T01 SupCar
392 第 12 章 数据操作
## 2: M01 JeepX
## 3: M02 AircraftX
## 4: M03 Runner
此外,我们也可以轻松地生成一个替换原有列的新的 data.table:
product_info[, list(id, name, released = released == "yes")]
## id name released
## 1: T01 SupCar TRUE
## 2: T02 SupPlane FALSE
## 3: M01 JeepX TRUE
## 4: M02 AircraftX TRUE
## 5: M03 Runner TRUE
## 6: M04 Dancer FALSE
还可以利用原有列来创建新列,并生成新的 data.table:
product_stats[, list(id, material, size, weight, density = size / weight)]
## id material size weight density
## 1: T01 Metal 120 10.0 12.000000
## 2: T02 Metal 350 45.0 7.777778
## 3: M01 Plastics 50 NA NA
## 4: M02 Plastics 85 3.0 28.333333
## 5: M03 Wood 15 NA NA
## 6: M04 Wood 16 0.6 26.666667
为了简化,data.table 为 list( ) 提供了缩写.( ),即 .( ) 和 list( ) 是等价的:
product_info[, .(id, name, type, class)]
## id name type class
## 1: T01 SupCar toy vehicle
## 2: T02 SupPlane toy vehicle
## 3: M01 JeepX model vehicle
## 4: M02 AircraftX model vehicle
## 5: M03 Runner model people
## 6: M04 Dancer model people
product_info[released == "yes", .(id, name)]
## id name
## 1: T01 SupCar
## 2: M01 JeepX
## 3: M02 AircraftX
## 4: M03 Runner
通过提供排序索引,我们可以根据既定的要求对记录进行排序:
product_stats[order(size, decreasing = TRUE)]
## id material size weight
## 1: T02 Metal 350 45.0
## 2: T01 Metal 120 10.0
## 3: M02 Plastics 85 3.0
## 4: M01 Plastics 50 NA
## 5: M04 Wood 16 0.6
## 6: M03 Wood 15 NA
前面都是在构建子集之后,又创建了一个新的 data.table。data.table 包还提供
了一个对列进行原地赋值的符号:=。例如,product_stats 原始数据是这样的:
product_stats
## id material size weight
## 1: T01 Metal 120 10.0
## 2: T02 Metal 350 45.0
## 3: M01 Plastics 50 NA
## 4: M02 Plastics 85 3.0
## 5: M03 Wood 15 NA
## 6: M04 Wood 16 0.6
使用 :=,可以直接在 product_stats 中创建新列:
product_stats [, density := size / weight]
虽然并没有返回什么,但原始的 data.table 已经被修改了:
product_stats
## id material size weight density
## 1: T01 Metal 120 10.0 12.000000
## 2: T02 Metal 350 45.0 7.777778
## 3: M01 Plastics 50 NA NA
## 4: M02 Plastics 85 3.0 28.333333
## 5: M03 Wood 15 NA NA
## 6: M04 Wood 16 0.6 26.666667
使用 := 替换已有的列:
product_info[, released := released == "yes"]
product_info
## id name type class released
## 1: T01 SupCar toy vehicle TRUE
## 2: T02 SupPlane toy vehicle FALSE
## 3: M01 JeepX model vehicle TRUE
## 4: M02 AircraftX model vehicle TRUE
## 5: M03 Runner model people TRUE
## 6: M04 Dancer model people FALSE
data.table 包提供 := ,主要是因为原地修改的性能更高,避免了不必要的复制。
使用 data.table 包操作数据的更多相关文章
- R语言数据分析利器data.table包 —— 数据框结构处理精讲
R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代码简洁,只要一行命令就可以完成诸多任务,另一方面是处理 ...
- data.table包简介
data.table包主要特色是:设置keys.快速分组和滚得时序的快速合并.data.table主要通过二元检索法大大提高数据操作的效率,同时它也兼容适用于data.frame的向量检索法. req ...
- R︱高效数据操作——data.table包(实战心得、dplyr对比、key灵活用法、数据合并)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 由于业务中接触的数据量很大,于是不得不转战开始 ...
- R语言data.table包fread读取数据
R语言处理大规模数据速度不算快,通过安装其他包比如data.table可以提升读取处理速度. 案例,分别用read.csv和data.table包的fread函数读取一个1.67万行.230列的表格数 ...
- R语言数据分析利器data.table包—数据框结构处理精讲
R语言数据分析利器data.table包-数据框结构处理精讲 R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代 ...
- data.table包
data.table 1.生成一个data.table对象 生成一个data.table对象,记为DT. library(data.table) :],V3=round(rnorm(),),V4=:) ...
- data.table包使用应该注意的一些细节
fread中nThread 参数的使用 注意默认nThread=getDTthreads(),即使用所有能用的核心,但并不是核心用的越多越好,本人亲自测试的情况下,其实单核具有较强的性能,只有在数 ...
- R读取大数据data.table包之fread
>library(data.table)>data=fread("10000000.txt")>Read 9999999 rows and 71 (of 71) ...
- R语言学习笔记(十七):data.table包中melt与dcast函数的使用
melt函数可以将宽数据转化为长数据 dcast函数可以将长数据转化为宽数据 > DT = fread("melt_default.csv") > DT family_ ...
随机推荐
- 使用HttpClient进行远程接口测试
前两天在工作中,项目组长给我了一个远程接口让我给测一下,因为是http协议,所以我首先想到了用httpClient工具类来测试,网上一查,找到了好多示例代码,随便复制了一个demo进行了简单的修改,结 ...
- Oracle的FIXED_DATE参数
今天发现一个有意思的问题, 我们知道,在Oracle数据库中正常执行 select sysdate from dual 都可以返回当前主机的系统时间. 正常修改系统时间,对应的查询结果也会变成修改后的 ...
- http 之 HTTP_X_FORWARDED_FOR
原文 http://www.imququ.com/post/x-forwarded-for-header-in-http.html 主题 HTTP Nginx 我一直认为,对于从事 Web 前端开 ...
- [转]C语言四书五经
我们来说说C语言方面的图书.什么,C语言?有读者奇怪了.没错,这一次的主角就是诞生于1973年如今已经儿孙满堂的C语言.我们之所以要谈及C,不仅仅是因为它的影响深远,这完全可以从C系列语言家族的兴旺发 ...
- entity framework 新增,更新,事务
protected void Button1_Click(object sender, EventArgs e) { yyEntities _db; _db = new yyEntities(); t ...
- Codeforces 1146E Hot is Cold
题意: 给出一个序列,有两种操作: \(>\;x\) 将大于\(x\)的数全都取负 \(<\;x\) 将小于\(x\)的数全都取负 最后输出序列中的所有数最后的状态 思路: 我们先考虑对于 ...
- POJ 分类
初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. ( ...
- ActiveMQ 集群负载平衡
目前的架构: 负载均衡方案:========================================= 第二种方案呢,假设我们整个应用是个食堂,这个食堂里面有好多饭口,每个饭口有好多大爷大妈( ...
- Linux基础命令---find
file 判断指定文件的文件类型,它依据文件内容判断,并不依据扩展名.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法 ...
- Ubuntu系统下使用Jenkins进行项目的自动构建还是项目回滚方法
上面虽然实现了项目的自动部署,但是有时部署失败的时候我们需要回滚到指定版本的构建,这样才能更灵活的进行项目的构建部署.我们可以选择“参数化的构建过程”进行传递不同的参数来选择是进行新的构建还是回滚 如 ...