在前面的章节中,我们已经学习了存储表的关系型数据库,支持嵌套数据结构的非关
系型数据库。在 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. git 下载单个文件 已经添加多个远程服务器

    175down vote It is possible to do (in the deployed repository) git fetch followed by git checkout or ...

  2. GNU Make中文手册(一)

    GNU Make 翻译:loverszhaokai 最新版文档请参考github: https://github.com/loverszhaokai/GNUMakeManual_CN 欢迎大家提出修改 ...

  3. liferay笑傲江湖-API之参数的工具类(ParamUtil)

    public class ParamUtil { 036 037 public static boolean get( 038 HttpServletRequest request, String p ...

  4. css样式表--样式表分类

    样式表分类 1.内联式.写在body里.控制精确,可重复性差. <body> <div style="color:#90F">更好发挥的返回结果还 < ...

  5. mvc actionresult返回各种文件

    public ActionResult ReviewFile(string folderName, string fileBasename, string extendName) { //以后根据后缀 ...

  6. 014-配置SSH免密钥登录

    问题:client端需要免密钥登录服务器server如何配置?1.前提:客户端已安装openssh-client;服务端已安装openssh-server;服务器端22号端口已经打开2.需要密钥登录时 ...

  7. unity Texture贴图纹理及相关属性

    Texture资源是Unity3d游戏开发中用途最广泛的资源之一,被引用于诸如界面UI. Mesh模型 .粒子效果等.还有一些特殊的Texture资源,如:Movie Texture:视频资源.Ren ...

  8. Root :: AOAPC I: Beginning Algorithm Contests (Rujia Liu) Volume 7. Graph Algorithms and Implementation Techniques

    uva 10803 计算从任何一个点到图中的另一个点经历的途中必须每隔10千米 都必须有一个点然后就这样 floy 及解决了 ************************************* ...

  9. eclipse调优

    基于Eclipse 4.7.0 (Oxygen) 目的:加快eclipse启动速度 修改eclipse安装目录下配置文件eclipse.ini(1)指定eclipse运行的jre,不让其进行搜索-vm ...

  10. Scrapy: 初识Scrapy

    1.初识Scrapy Scrapy是为了爬取网站数据,提取结构性数据而编写的应用框架.可以应用在包括数据挖掘,信息处理或者存储历史数据等一系列的程序中. 2.选择一个网站 当需要从某个网站获取信息时, ...