在前面的章节中,我们已经学习了存储表的关系型数据库,支持嵌套数据结构的非关
系型数据库。在 R 中,最常见的嵌套数据结构就是列表对象。之前的章节都关注操作表格
数据。本节,我们一起玩转作者开发的 rlist 包,这是一个为操作非表格数据设计的包。
rlist 的设计和 dplyr 非常相似。它提供了针对列表对象的映射、筛选、选择、排
序、分组和聚合功能。运行以下代码来从 CRAN 安装 rlist 包:
install.packages("rlist")
我们有一个非表格式版本的产品数据,储存在 data/products.json。在这个文件
中,每个产品都以 JSON 形式表达,如下:
{
"id": "T01",
"name": "SupCar",
"type": "toy",
"class": "vehicle",
"released": true,
"stats": {
"material": "Metal",
"size": 120,
"weight": 10
},
"tests": {
"quality": null,
"durability": 10,
"waterproof": false
},
"scores": [8, 9, 10, 10, 6, 5]
}
所有的产品都被存储在一个 JSON 数组中,就像这样: [ {...}, {...} ]。不同
于将数据储存在不同的表中,我们把所有与产品相关的东西都放入一个对象中。然后使
用 rlist 的函数来处理这种格式的数据。首先载入 rlist 包:
library(rlist)
为了把数据以列表的形式载入 R 中,我们需要使用 jsonlite::fromJSON( ),或
者就直接使用 rlist 提供的 list.load( )函数:
products <- list.load("data/products.json")
str(products[[1]])
## List of 8
## $ id : chr "T01"
## $ name : chr "SupCar"
## $ type : chr "toy"
## $ class : chr "vehicle"
## $ released: logi TRUE
## $ stats :List of 3
## ..$ material: chr "Metal"
## ..$ size : int 120
## ..$ weight : int 10
## $ tests :List of 3
## ..$ quality : NULL
## ..$ durability: int 10
## ..$ waterproof: logi FALSE
## $ scores : int [1:6] 8 9 10 10 6 5
现在,列表 products 存储了所有产品的信息。products 的每个成分都包含了一个
产品的所有相关信息。
可以调用 list.map( ) 函数,在每个成分的语义中计算表达式:
str(list.map(products, id))
## List of 6
## $ : chr "T01"
## $ : chr "T02"
## $ : chr "M01"
## $ : chr "M02"
## $ : chr "M03"
## $ : chr "M04"
这个函数迭代计算 products 中每个成分的 id 并返回一个新的列表,其中包含所有
相关的结果。list.mapv( ) 函数简化了这个列表,返回一个向量:
list.mapv(products, name)
## [1] "SupCar" "SupPlane" "JeepX" "AircraftX"
## [5] "Runner" "Dancer"
为了对 products 进行筛选,我们可以调用 list.filter( )函数并配合使用逻辑
条件。只有所有条件都返回 TRUE 的 products 的元素,才会被筛选出来:
released_products <- list.filter(products, released)
list.mapv(released_products, name)
## [1] "SupCar" "JeepX" "AircraftX" "Runner"
注意到, rlist 的函数设计也和 dplyr 的函数设计很相似,也就是说,输入的数据永
远作为第 1 个参数。因此我们可以使用管道操作符将结果逐步向前传送:
products %>%
list.filter(released) %>%
list.mapv(name)
## [1] "SupCar" "JeepX" "AircraftX" "Runner"
可以使用 list.select( ) 函数将输入列表的每个成分的某些特定字段都筛选出来:
products %>%
list.filter(released, tests$waterproof) %>%
list.select(id, name, scores) %>%
str()
## List of 3
## $ :List of 3
## ..$ id : chr "M01"
## ..$ name : chr "JeepX"
## ..$ scores: int [1:6] 6 8 7 9 8 6
## $ :List of 3
## ..$ id : chr "M02"
## ..$ name : chr "AircraftX"
## ..$ scores: int [1:7] 9 9 10 8 10 7 9
## $ :List of 3
## ..$ id : chr "M03"
## ..$ name : chr "Runner"
## ..$ scores: int [1:10] 6 7 5 6 5 8 10 9 8 9
除此之外,还可以用 list.select( ) 函数创建新的字段:
products %>%
list.filter(mean(scores) >= 8) %>%
list.select(name, scores, mean_score = mean(scores)) %>%
str()
## List of 3
## $ :List of 3
## ..$ name : chr "SupCar"
## ..$ scores : int [1:6] 8 9 10 10 6 5
## ..$ mean_score: num 8
## $ :List of 3
## ..$ name : chr "SupPlane"
## ..$ scores : int [1:5] 9 9 10 10 10
## ..$ mean_score: num 9.6
## $ :List of 3
## ..$ name : chr "AircraftX"
## ..$ scores : int [1:7] 9 9 10 8 10 7 9
## ..$ mean_score: num 8.86
也可以用 list.sort( ) 函数,按照特定字段或值对列表元素进行排序,再使
用 list.stack( ) 将所有元素整合成一个数据框:
products %>%
list.select(name, mean_score = mean(scores)) %>%
list.sort(-mean_score) %>%
list.stack()
## name mean_score
## 1 SupPlane 9.600000
## 2 AircraftX 8.857143
## 3 SupCar 8.000000
## 4 Dancer 7.833333
## 5 JeepX 7.333333
## 6 Runner 7.300000
为了给列表分组,可以调用 list.group( ) 创建一个嵌套列表,其中所有元素都被
分组变量的字段值分割开来:
products %>%
list.select(name, type, released) %>%
list.group(type) %>%
str()
## List of 2
## $ model:List of 4
## ..$ :List of 3
## .. ..$ name : chr "JeepX"
## .. ..$ type : chr "model"
## .. ..$ released: logi TRUE
## ..$ :List of 3
## .. ..$ name : chr "AircraftX"
## .. ..$ type : chr "model"
## .. ..$ released: logi TRUE
## ..$ :List of 3
## .. ..$ name : chr "Runner"
## .. ..$ type : chr "model"
## .. ..$ released: logi TRUE
## ..$ :List of 3
## .. ..$ name : chr "Dancer"
## .. ..$ type : chr "model"
## .. ..$ released: logi FALSE
## $ toy :List of 2
## ..$ :List of 3
## .. ..$ name : chr "SupCar"
## .. ..$ type : chr "toy"
## .. ..$ released: logi TRUE
## ..$ :List of 3
## .. ..$ name : chr "SupPlane"
## .. ..$ type : chr "toy"
## .. ..$ released: logi FALSE
rlist 也提供了许多其他函数,从而能够方便地操作非表格式数据。举个例子,函数
list.table( ) 便是 table( ) 的加强版,它使得 table( ) 可以直接作用于列表元素:
products %>%
list.table(type, class)
## class
## type people vehicle
## model 2 2
## toy 0 2
通过在输入列表的语义中计算每个参数,它也支持多维表格:
products %>%
list.filter(released) %>%
list.table(type, waterproof = tests$waterproof)
## waterproof
## type FALSE TRUE
## model 0 3
## toy 1 0
尽管数据是通过非表格形式存储的,我们仍然可以进行复杂的数据操作,并用表格形
式展示结果。例如,假设我们需要计算两个产品的平均得分,并统计有多少种不同的得分。
其中,这两个产品具有最高的平均得分,且至少包含 5 种得分。
我们可以将这个任务分解成几个数据操作的小任务,这些小任务可以轻松地通
过 rlist 的函数处理。由于数据操作中需要的步骤较多,我们使用管道操作来组织工作流:
products %>%
list.filter(length(scores) >= 5) %>%
list.sort(-mean(scores)) %>%
list.take(2) %>%
list.select(name,
mean_score = mean(scores),
n_score = length(scores)) %>%
list.stack()
## name mean_score n_score
## 1 SupPlane 9.600000 5
## 2 AircraftX 8.857143 7
以上代码看起来很直观,而且可以很方便地预测和分析每一步操作。如果最终结果可
以用表格展示,我们就调用 list.stack( ),这样就能够将所有列表元素组合成一个数据框。
想了解更多关于 rlist 的函数,可以阅读 rlist 教程(https://renkun.me/rlist-tutorial/)。还
有很多处理嵌套数据结构的包,它们具有不同的设计理念,例如 purrr(https://github. com/
hadley/purrr)。如果感兴趣,可以访问他们的网站。

使用 rlist 包处理嵌套数据结构的更多相关文章

  1. jar包有嵌套的jar的打包成jar的方法

    1.先写一个类,将其打包成jar包. 代码如下: package com.wjy.jar; public class GetUserName { public String getUserName() ...

  2. R语言︱非结构化数据处理神器——rlist包

    本文作者:任坤,厦门大学王亚南经济研究院金融硕士生,研究兴趣为计算统计和金融量化交易,pipeR,learnR,rlist等项目的作者. 近年来,非关系型数据逐渐获得了更广泛的关注和使用.下面分别列举 ...

  3. 解析复杂的嵌套数据结构-jsonpath

    JsonPath是一种简单的方法来提取给定JSON文档的部分内容. JsonPath有许多编程语言,如Javascript,Python和PHP,Java. JsonPath提供的json解析非常强大 ...

  4. 【数据结构的JavaScript版实现】data-struct-js的npm包初版作成

    [数据结构的JavaScript版实现]data-struct-js的npm包初版作成 码路工人 CoderMonkey [数据结构的JavaScript版实现] 拖了这么久,终于趁着春节假期把初版( ...

  5. 引擎设计跟踪(九.9) 文件包系统(Game Package System)

    很早之前,闪现过写文件包系统的想法, 但是觉得还没有到时候. 由于目前工作上在做android ndk开发, 所以业余时间趁热做了android的移植, 因为android ndk提供的mountab ...

  6. js处理层级数据结构的一些总结

    开发者对复杂的数据结构的处理能力也是体现开发者水平的一个度量吧...最近发现自己对一些嵌套数据结构.层级数据结构的处理能力不大足...经常被这些把自己绕晕...严重影响开发效率...就稍微低总结了一下 ...

  7. UML之包图

    包图是UML中用类似于文件夹的符号表示的模型元素的组合,系统中的每个元素都只能为一个包所有,一个包可嵌套在另一个包中,使用包图可将相关元素归入一个系统,一个包中包含附属包.图表或单个元素.简单的来说, ...

  8. day 16 包的导入

    包的认识 '''包通过文件夹来管理一系列功能相近的模块​包:一系列模块的集合体重点:包中一定有一个专门用来管理包中所有模块的文件包名:存放一系列模块的文件夹名字包名(包对象)存放的是管理模块的那个文件 ...

  9. Python 入门基础13 --模块与包

    本节内容: 一.模块及使用 1.模块及使用 2.起别名.from导入 3.自执行与模块 二.包的使用 2.1 包中模块的使用:import 2.2 包的嵌套 2.3 包中模块的使用:from ...i ...

随机推荐

  1. ArcGIS 10——地理数据库管理GIS数据

    写本文的最初意向是当前正在进行的项目中有实现ESRI版本化数据管理的功能模块,碰到一些棘手的问题,几经周折还是决定系统学习ArcGIS10的帮助文档.(文章摘抄的比较多) 地理数据库是用于保存数据集集 ...

  2. zookeeper 安装以及集群搭建

    安装环境: jdk1.7 zookeeper-3.4.10.tar.gz VM虚拟机redhat6.5-x64:192.168.1.200  192.168.1.201  192.168.1.202 ...

  3. Python: re.compile最短匹配模式,只取双引号内的值\“

    用正则表达式匹配某个文本模式 1.只取双引号内的值 2.长短匹配模式对比 贪婪模式:     模式r'\"(.*)\" '的意图是匹配被双引号包含的文本,但是这个表达式中*是贪婪的 ...

  4. 为什么学Python语言,只需四步全面了解Python语言

    为什么学Python语言,只需四步全面了解Python语言每个时代都会悄悄犒赏会选择的人,Python现在风口的语言Python--第三大主流编程语言Python , 是一种面向对象的解释型计算机程序 ...

  5. SQL学习之SQL注入学习总结

    所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. 测试数据库 我们本文就以如下数据库作为测试数据库,完成我们的注入分析 ...

  6. mysql主备切换[高可用]

    到这一步的时候, 是主备部署已经处理好, 请关注:mysql主备部署[高可用] 这次使用的是keepalived-1.2.22.tar.gz版, 官网地址:keeplived官网 笼统知识请自行查询百 ...

  7. 20145317彭垚《网络对抗》Exp2 后门原理与实践

    20145317彭垚<网络对抗>Exp2 后门原理与实践 基础问题回答 例举你能想到的一个后门进入到你系统中的可能方式? 在网上下载软件的时候,后门很有可能被捆绑在下载的软件当中: 例举你 ...

  8. linux内核分析 第四周

    一.系统调用的三层皮 内核态.用户态 Intel x86 CPU有四个权限分级,0-3.Linux只取两种,0是内核态,3是用户态. 0xc0000000以上的空间只能在内核态下访问 0x000000 ...

  9. spring与spring-data-redis整合redis

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  10. TeeChart取消3D

    tChart1.Aspect.View3D = false;//此属性默认是true 3d的效果 2d平面的效果 题外话,在使用控件的时候,需要注意: 在TChart控件上增加Series,   se ...