本文作者:任坤,厦门大学王亚南经济研究院金融硕士生,研究兴趣为计算统计和金融量化交易,pipeR,learnR,rlist等项目的作者。

近年来,非关系型数据逐渐获得了更广泛的关注和使用。下面分别列举了一个典型的关系型数据表和一个典型的非关系型数据集。

关系型数据:一组学生的基本数据,包括姓名(Name)、性别(Gender)、年龄(Age)以及专业(Major)。

NAME GENDER AGE MAJOR
Ken Male 24 Finance
Ashley Female 25 Statistics
Jennifer Female 23 Computer Science

非关系型数据:一组程序开发者的基本信息,包括姓名(Name)、年龄(Age)、兴趣爱好(Interest)、编程语言以及使用年数(Language)。

NAME AGE INTEREST LANGUAGE
Ken 24 reading, music,movies R:2, C#:4, Python:3
James 25 sports, music R:3, Java:2, C++:5
Penny 24 movies, reading R:1, C++:4, Python:2

可以发现,第一个表中的关系型数据可以简单地放入矩形的数据表,而第二个表中的非关系型数据中InterestLanguage本身并不是单一值的字段,因而如果在关系型数据库中表示,可能需要建立多个表和关系来存储。

对于这种数据的处理,MongoDB是较为成熟的解决方案之一。在R中,data.frame可以用来很好地描述关系型数据表,也有data.tabledplyr等扩展包可以方便地处理这类数据。而list对象可以很好地表征结构灵活的非关系型数据,但是却缺乏可以灵活地处理list对象中存储非关系型数据的扩展包。

这就是 rlist 扩展包诞生的原因:让人们可以使用全部R的函数和功能,方便地访问list对象中存储的非关系型数据,从而轻松地、直观地进行非关系型数据映射 (mapping)、筛选(filtering)、分组(grouping)、排序(sorting)、更新(updating)等等。

可以用devtools扩展包直接从GitHub安装rlist最新的开发版本:

devtools::install_github("rlist","renkun-ken")

下面将通过一些例子来分别介绍这个扩展包的主要功能。下面的例子基本都在以下数据中进行。

library(rlist)
devs <- list(p1=list(name="Ken",age=24,interest=c("reading","music","movies"),lang=list(r=2,csharp=4,python=3)),p2=list(name="James",age=25,interest=c("sports","music"),lang=list(r=3,java=2,cpp=5)),p3=list(name="Penny",age=24,interest=c("movies","reading"),lang=list(r=1,cpp=4,python=2)))
str(devs)
List of 3$ p1:List of 4..$ name    : chr "Ken"..$ age     : num 24..$ interest: chr [1:3] "reading" "music" "movies"..$ lang    :List of 3.. ..$ r     : num 2.. ..$ csharp: num 4.. ..$ python: num 3$ p2:List of 4..$ name    : chr "James"..$ age     : num 25..$ interest: chr [1:2] "sports" "music"..$ lang    :List of 3.. ..$ r   : num 3.. ..$ java: num 2.. ..$ cpp : num 5$ p3:List of 4..$ name    : chr "Penny"..$ age     : num 24..$ interest: chr [1:2] "movies" "reading"..$ lang    :List of 3.. ..$ r     : num 1.. ..$ cpp   : num 4.. ..$ python: num 2

上面的代码是直接在R中建立一个名为devs的list对象,里面包含的正是前面提到的非关系型数据。由于直接输出数据占用篇幅较长,在后面的例子中可能采用str函数来显示数据。

映射(mapping)

list.map函数提供了list中元素的映射功能。

将每个元素映射到年龄(age):

list.map(devs, age)
$p1
[1] 24$p2
[1] 25$p3
[1] 24

将每个元素映射到使用编程语言的平均年数:

list.map(devs, mean(as.numeric(lang)))
$p1
[1] 3$p2
[1] 3.333$p3
[1] 2.333

将每个元素映射到使用的编程语言名称:

list.map(devs, names(lang))
$p1
[1] "r"      "csharp" "python"$p2
[1] "r"    "java" "cpp" $p3
[1] "r"      "cpp"    "python"

筛选(filtering)

筛选出年龄不低于25岁的个体:

str(list.filter(devs, age>=25))
List of 1$ p2:List of 4..$ name    : chr "James"..$ age     : num 25..$ interest: chr [1:2] "sports" "music"..$ lang    :List of 3.. ..$ r   : num 3.. ..$ java: num 2.. ..$ cpp : num 5

筛选出使用R语言的个体:

str(list.filter(devs, "r" %in% names(lang)))
List of 3$ p1:List of 4..$ name    : chr "Ken"..$ age     : num 24..$ interest: chr [1:3] "reading" "music" "movies"..$ lang    :List of 3.. ..$ r     : num 2.. ..$ csharp: num 4.. ..$ python: num 3$ p2:List of 4..$ name    : chr "James"..$ age     : num 25..$ interest: chr [1:2] "sports" "music"..$ lang    :List of 3.. ..$ r   : num 3.. ..$ java: num 2.. ..$ cpp : num 5$ p3:List of 4..$ name    : chr "Penny"..$ age     : num 24..$ interest: chr [1:2] "movies" "reading"..$ lang    :List of 3.. ..$ r     : num 1.. ..$ cpp   : num 4.. ..$ python: num 2

筛选出使用Python年限不低于3年的个体:

str(list.filter(devs, lang$python >= 3))
List of 1$ p1:List of 4..$ name    : chr "Ken"..$ age     : num 24..$ interest: chr [1:3] "reading" "music" "movies"..$ lang    :List of 3.. ..$ r     : num 2.. ..$ csharp: num 4.. ..$ python: num 3

分组(grouping)

按照年龄做互斥分组:

str(list.group(devs, age))
List of 2$ 24:List of 2..$ p1:List of 4.. ..$ name    : chr "Ken".. ..$ age     : num 24.. ..$ interest: chr [1:3] "reading" "music" "movies".. ..$ lang    :List of 3.. .. ..$ r     : num 2.. .. ..$ csharp: num 4.. .. ..$ python: num 3..$ p3:List of 4.. ..$ name    : chr "Penny".. ..$ age     : num 24.. ..$ interest: chr [1:2] "movies" "reading".. ..$ lang    :List of 3.. .. ..$ r     : num 1.. .. ..$ cpp   : num 4.. .. ..$ python: num 2$ 25:List of 1..$ p2:List of 4.. ..$ name    : chr "James".. ..$ age     : num 25.. ..$ interest: chr [1:2] "sports" "music".. ..$ lang    :List of 3.. .. ..$ r   : num 3.. .. ..$ java: num 2.. .. ..$ cpp : num 5

按照兴趣做非互斥分组:

str(list.class(devs, interest))
List of 4$ movies :List of 2..$ p1:List of 4.. ..$ name    : chr "Ken".. ..$ age     : num 24.. ..$ interest: chr [1:3] "reading" "music" "movies".. ..$ lang    :List of 3.. .. ..$ r     : num 2.. .. ..$ csharp: num 4.. .. ..$ python: num 3..$ p3:List of 4.. ..$ name    : chr "Penny".. ..$ age     : num 24.. ..$ interest: chr [1:2] "movies" "reading".. ..$ lang    :List of 3.. .. ..$ r     : num 1.. .. ..$ cpp   : num 4.. .. ..$ python: num 2$ music  :List of 2..$ p1:List of 4.. ..$ name    : chr "Ken".. ..$ age     : num 24.. ..$ interest: chr [1:3] "reading" "music" "movies".. ..$ lang    :List of 3.. .. ..$ r     : num 2.. .. ..$ csharp: num 4.. .. ..$ python: num 3..$ p2:List of 4.. ..$ name    : chr "James".. ..$ age     : num 25.. ..$ interest: chr [1:2] "sports" "music".. ..$ lang    :List of 3.. .. ..$ r   : num 3.. .. ..$ java: num 2.. .. ..$ cpp : num 5$ reading:List of 2..$ p1:List of 4.. ..$ name    : chr "Ken".. ..$ age     : num 24.. ..$ interest: chr [1:3] "reading" "music" "movies".. ..$ lang    :List of 3.. .. ..$ r     : num 2.. .. ..$ csharp: num 4.. .. ..$ python: num 3..$ p3:List of 4.. ..$ name    : chr "Penny".. ..$ age     : num 24.. ..$ interest: chr [1:2] "movies" "reading".. ..$ lang    :List of 3.. .. ..$ r     : num 1.. .. ..$ cpp   : num 4.. .. ..$ python: num 2$ sports :List of 1..$ p2:List of 4.. ..$ name    : chr "James".. ..$ age     : num 25.. ..$ interest: chr [1:2] "sports" "music".. ..$ lang    :List of 3.. .. ..$ r   : num 3.. .. ..$ java: num 2.. .. ..$ cpp : num 5

排序(sorting)

按照年龄升序排列:

str(list.sort(devs, age))
List of 3$ p1:List of 4..$ name    : chr "Ken"..$ age     : num 24..$ interest: chr [1:3] "reading" "music" "movies"..$ lang    :List of 3.. ..$ r     : num 2.. ..$ csharp: num 4.. ..$ python: num 3$ p3:List of 4..$ name    : chr "Penny"..$ age     : num 24..$ interest: chr [1:2] "movies" "reading"..$ lang    :List of 3.. ..$ r     : num 1.. ..$ cpp   : num 4.. ..$ python: num 2$ p2:List of 4..$ name    : chr "James"..$ age     : num 25..$ interest: chr [1:2] "sports" "music"..$ lang    :List of 3.. ..$ r   : num 3.. ..$ java: num 2.. ..$ cpp : num 5

按照使用兴趣数量降序排列,然后按照R语言使用年数降序排列:

str(list.sort(devs, desc(length(interest)), desc(lang$r)))
List of 3$ p1:List of 4..$ name    : chr "Ken"..$ age     : num 24..$ interest: chr [1:3] "reading" "music" "movies"..$ lang    :List of 3.. ..$ r     : num 2.. ..$ csharp: num 4.. ..$ python: num 3$ p2:List of 4..$ name    : chr "James"..$ age     : num 25..$ interest: chr [1:2] "sports" "music"..$ lang    :List of 3.. ..$ r   : num 3.. ..$ java: num 2.. ..$ cpp : num 5$ p3:List of 4..$ name    : chr "Penny"..$ age     : num 24..$ interest: chr [1:2] "movies" "reading"..$ lang    :List of 3.. ..$ r     : num 1.. ..$ cpp   : num 4.. ..$ python: num 2

更新(updating)

去除interestlang两个字段,加入nlang表示掌握语言数目,以及expert使用时间最长的语言名称:

str(list.update(devs, interest=NULL, lang=NULL, nlang=length(lang),expert={longest <- sort(unlist(lang))[1]names(longest)}))
List of 3$ p1:List of 4..$ name  : chr "Ken"..$ age   : num 24..$ nlang : int 3..$ expert: chr "r"$ p2:List of 4..$ name  : chr "James"..$ age   : num 25..$ nlang : int 3..$ expert: chr "java"$ p3:List of 4..$ name  : chr "Penny"..$ age   : num 24..$ nlang : int 3..$ expert: chr "r"

Lambda表达式

rlist中所有支持表达式计算的函数都支持 Lambda 表达式,允许用户访问列表元素的元数据(metadata),即元素本身、元素索引编号(index)、元素名称(name)。

x <- list(a=c(1,2,3),b=c(3,4,5))
list.map(x, sum(.))
$a
[1] 6$b
[1] 12

在上面的代码中,.表示每个元素本身。此例中由于列表中每个元素都是一个数值向量,因此可以分别通过sum函数求和。如果不使用.来表示元素本身,可以通过形如 x -> f(x) 或者 x ~ f(x) 的 Lambda 表达式自定义符号。

list.map(x, x -> sum(x))
$a
[1] 6$b
[1] 12

默认情况下,.i表示当前元素的索引,.name表示当前元素的名称。下面用list.iter函数遍历x中的各个元素,对于每个元素显示自定义字符串。

list.iter(x, cat(.name,":",.i,"\n"))
a : 1
b : 2 

通过 Lambda 表达式自定义这些符号时,可以采用 f(x,i,name) -> expression 的形式,例如:

list.map(x, f(x,i) -> x*i)
$a
[1] 1 2 3$b
[1]  6  8 10

管道操作

由于rlist中函数结构设计具有很强的一致性,推荐和pipeR扩展包中定义的管道操作符一同使用,使得R中的非关系型数据操作易读、可维护。

下面的代码通过结合管道操作选择出喜欢音乐并且使用R的开发者的名字和年龄,结果组合成一个data.frame

library(pipeR)
devs %>>% list.filter("music" %in% interest & "r" %in% names(lang)) %>>%list.select(name,age) %>>%list.rbind %>>%data.frame
    name age
p1   Ken  24
p2 James  25

包含结构化对象的列表

下面是一个更为复杂的例子,其中涉及到生成一列 data.frame、处理一列线性模型等等:

set.seed(1)
1:10 %>>%list.map(i -> {x <- rnorm(1000)y <- i * x + rnorm(1000)data.frame(x=x,y=y)}) %>>%list.map(df -> lm(y~x)) %>>%list.update(summary = m -> summary(m)) %>>%list.sort(m -> desc(summary$r.squared)) %>>%list.map(c(rsq=summary$r.squared, coefficients)) %>>%list.rbind %>>%data.frame
      rsq X.Intercept.     x
1  0.9896    -0.032250 9.986
2  0.9871     0.031999 8.970
3  0.9832    -0.001191 7.993
4  0.9802     0.004400 6.958
5  0.9684    -0.034238 6.008
6  0.9626     0.007260 4.941
7  0.9450    -0.004309 3.995
8  0.8997    -0.012472 2.962
9  0.7994     0.016558 2.011
10 0.5008    -0.016187 1.006

其他功能

除了上述函数之外,rlist扩展包还提供了许多其他函数,这里只做简单介绍:

  • list.join:根表达式合并两个list
  • list.parse:将其他类型的对象转换为结构相同的list
  • list.loadlist.save:读写JSON, YAML, RData格式的list
  • list.iflist.whichlist.anylist.all:list元素的逻辑判断
  • list.findlist.findi:在list中按照表达式寻找指定数量的元素

详细介绍请参见帮助文档:

help(package = rlist)

以及应用手册:

vignette("introduction", package = "rlist")

参考:http://cos.name/2014/07/rlist-package/

R语言︱非结构化数据处理神器——rlist包相关推荐

  1. 非结构化数据处理方案

    非结构化数据&结构化处理方案 一. 非结构化数据处理需求    企业拥有的非结构化数据增长迅速.非结构化数据是计算机或人生成的信息,其中的数据并不一定遵循标准的数据结构(如模式定义规范的行和列 ...

  2. AI非结构化数据处理和分析软件公司Zilliz宣布完成4300万美元B轮融资

    "数据猿年度重磅活动预告:2020年度金猿策划活动(金猿榜单发布+金猿奖杯颁发+2.0版产业图谱+落地颁奖大会)即将推出,敬请咨询期待! 数据猿发布产业全景图--2020中国数据智能产业图谱 ...

  3. R语言学习笔记之——数据处理神器data.table

    前言 数据处理在数据分析流程中的地位相信大家都有目共睹,也是每一个数据从业者面临的最为繁重的工作任务. 在实际应用场景下,虽然SQL(SQL类专业的etl语言)是数据处理的首选明星语言,性能佳.效率高 ...

  4. 知识图谱学习笔记-非结构化数据处理

    非结构话数据到知识图谱 非结构数据-> 信息抽取(命名实体识别.关系抽取)-> 图谱构建(实体消歧.链接预测)-> 图分析算法 一.文本分析关键技术 拼写纠错 分词 词干提取 词的过 ...

  5. MaxCompute与OSS非结构化数据读写互通(及图像处理实例)

    为什么80%的码农都做不了架构师?>>>    摘要: MaxCompute作为阿里巴巴集团内部绝大多数大数据处理需求的核心计算组件,拥有强大的计算能力,随着集团内外大数据业务的不断 ...

  6. MaxCompute(ODPS)上处理非结构化数据的Best Practice

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 随着MaxCompute(ODPS)2.0的上线,新增的非结构化数据处理框架也推出一系列的介绍文章,包括 MaxCom ...

  7. 我被“非结构化数据包围了”,请求支援!

    阿里妹导读:非结构化数据的内容占据了当前数据海洋的80%.换句话来说,就是我们都被"非结构化数据"包围了.由于非结构化数据的信息量和信息的重要程度很难被界定,因此对非结构化数据的使 ...

  8. 【作业】非结构化数据相关知识整理

    文章目录 1.非结构化数据是什么 2.非结构化数据处理困难的原因 3.处理非结构化数据的方法 1.非结构化数据是什么 非结构化数据是数据结构不规则或不完整,没有预定义的数据模型,不方便用数据库二维逻辑 ...

  9. 如何理解结构化、非结构化和半结构化数据?

    计算机信息化系统中的数据分为结构化数据.非结构化数据和半结构化数据 1.结构化数据(Structured Data) 定义:结构化数据也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据 ...

最新文章

  1. 蓝桥杯第九届决赛-交换次数-java
  2. prompt-toolkit 版本问题
  3. 使用maxscale数据库中间件解决读负载均衡
  4. oracle隐式转换函数,隐式数据类型转换案例一则
  5. LeetCode Algorithm 704. 二分查找
  6. 格力宣布11月11日一天让利7亿元 全场空调最高降3900元
  7. ArcGIS 10.2安装之 ArcSDE的使用
  8. Voxengo Peakbuster for mac(音频谐波增强插件)
  9. Myeclipse如何使用自带git工具向远程仓库提交代码(转)
  10. 【bzoj4542】[Hnoi2016]大数 莫队算法
  11. 王道考研机试指南重写
  12. 用python画满天星_Python用27行代码绘制一幅满天星
  13. Learning Multi-granularity Consecutive User Intent Unit for Session-based Recommendation
  14. android压力测试之monkey详解
  15. 三次握手与四次挥手的爱恨情仇
  16. 【下载】Step7 V5.4 中文版【绝对能安装使用】
  17. vue+高德地图绘制路径
  18. 尾部相关性尾部风险价圣分
  19. 打印机CCC认证费用、周期
  20. fedora 35 通过docker 使用微信

热门文章

  1. 编译原理_P1001
  2. Java23个设计模式的简明教程
  3. JS弹窗确认Ajax封装方法
  4. 一天一种设计模式之二-----备忘录模式
  5. 框架源码深入需要准备的知识之解析XML
  6. Java的I/O总结
  7. Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds
  8. 使用winpcap定制TCP包发送
  9. [收藏]Mysql日期和时间函数
  10. html5.0用什么编程语言,HTML5.0,求好心人详解,谢谢