現代化數據科學中的 DataFrame 概念源起R語言,而 Python Pandas 和 Spark DateFrame 都是參考R設計的。不過在實際的網絡數據通信中,相似DateFrame這樣的格式卻並非主流,真正主流的方式實際上是JSON(JavaScript Object Notation),因此討論如何處理非結構化數據就變得很是有意義了。加之,近年來 Redis、MongoDB、ELK等非結構化數據庫的繁榮,MySQL 5.7以後也已經添加了對JSON格式的原生支持(以前能夠用blob、longtext等格式存儲),非結構化數據更是在數據處理中變得流行。html
本文將從 非結構化數據的轉化、處理以及可視化三個方面討論如何在R中操做非結構化數據。python
DataFrame 是R中的結構化數據結構,List 是R中的非結構化數據。JSON、List、DataFrame三者之間的互相轉化是數據科學中很是頻繁的一類操做。git
在R中有一個很是有意思的現象,那就是處理json時,咱們有三個選擇,jsonlite、rjson以及RJSONIO,三者各有特色,有時爲了處理一些問題還必須得混合使用。在實際處理字符串中,必定要注意的就是R中字符串的轉義問題。好比\\
表示\
,\"
表示"
等等。我曾經由於Python和R中的雙層JSON解析屢次遇到轉義符號的問題。具體能夠參看官方手冊。github
jsonlite 是我最經常使用的一個json處理包,由於jsonlite能夠一步將 json 轉成 dataframe 再 從dataframe 轉到 json,在數據處理中能夠輕鬆解決常見的 json轉化問題。此外,jsonlite 還完美支持utf-8,在 json 字符串錯誤時會有明顯的錯誤提示。sql
jsonlite 的劣勢是當出現雙層 json 時,jsonlite 會將json轉成dataframe格式的 list,這直接致使咱們在用 length() 或者 dim() 求內層 JSON 的維度會出現錯誤。數據庫
jsonlite::fromJSON("{\"x\":\"量化投資\",\"y\":\"harryzhu\"}")
$x [1] "量化投資" $y [1] "harryzhu"
rjson 和 jsonlite最大不一樣之處在於,rjson將json轉化爲一個list,而list是R語言中非結構化數據的事實標準,相似 python 中的 dict,或者 matlab 中的 cell。json
值得注意的是,rjson在json轉化中直接保持全部的浮點型數據,而jsonlite和RJSONIO則能夠經過參數控制保留若干位小數的精度。segmentfault
rjson::fromJSON("{\"x\":\"1\",\"y\":\"2\"}") rjson::toJSON(pi)
$x [1] "1" $y [1] 2 [1] "3.14159265358979"
jsonlite::fromJSON(pi,digit=4)
[1] "[ 3.142 ]"
RJSONIO 容許傳入沒有轉義符號的 JSON 字符串,而且支持將缺失值(NA)直接轉成 Null,須要當心的是RJSONIO只支持unicode,若是傳入utf-8則會釀成悲劇。api
RJSONIO::fromJSON(RJSONIO::toJSON(c(1,2,NA,4)))
"[[1]] [1] 1 [[2]] [1] 2 [[3]] NULL [[4]] [1] 4"
更多細節能夠參考 A biased comparsion of JSON packages in R瀏覽器
談到list的處理就不得不談一談 rlist包。rlist包是任坤老師貢獻到CRAN上的,任坤老師既是一個多產的R Developer (pipeR、formattable做者)也是一名量化投資者,目前在作私募方面的創業。想要學習rlist,咱們能夠參考一下任坤老師的演講:跳出數據框,擁抱非結構化數據和官方教程。
rlist 是支持高階函數表達式的,借鑑了Python、Scala等語言中的MapReduce模型,rlist也爲list提供了map、filter、reduce、group、join、search、sort等高級數據操做,熟悉這些操做之後上手sparkR的RDD操做很是有幫助。
利用 GitHub API,咱們能夠知道Hadley 的原創R語言開源項目中討論議題數量最多的10個項目是哪些。
library(rlist) library(pipeR) # 分頁讀取數據 repos <- "https://api.github.com/users/hadley/repos?per_page=100&page=%d" %>>% sprintf(1:2) %>>% list.load("json") %>>% list.ungroup repos %>>% list.filter(has_issues, !fork, language == "R") %>>% list.names(name) %>>% list.mapv(open_issues) %>>% list.sort(-.) %>>% list.take(10) # dplyr ggplot2 lubridate devtools staticdocs plyr # 88 72 54 33 32 28 # stringr roxygen3 scales gtable # 24 22 22 21
批量讀取非空 csv 文件而且合併成一個 data frame:
"data/" %>>% list.files("\\.csv", full.names = TRUE) %>>% list.filter(file.info(.)$size > 0) %>>% list.map(read.csv(., header = TRUE, stringsAsFactors = FALSE)) %>>% list.stack
rlist擴展包充分利用了R語言中list對象的特性,定義了一整套函數來幫助用戶靈活快速地按要求處理各類非結構化數據,同時結合pipeR包中管道操做符的使用,使R程序更加具備可讀性,應用更加人性化。
下面是rlist中提供的操做:
分類 | 函數 |
---|---|
映射(Mapping) | list.map, list.mapv, list.select, list.iter, list.maps |
篩選(Filtering) | list.filter, list.find, list.findi, list.first, list.last,list.take, list.skip,list.takeWhile, list.skipWhile, list.is,list.which, list.all, list.any, list.count, list.match |
更新(Updating) | list.update |
排序(Sorting) | list.order, list.sort |
分組(Grouping) | list.group, list.ungroup, list.cases, list.class, list.common,list.table |
合併(Joining) | list.join, list.merge |
搜索(Searching) | list.search |
數據讀寫(I/O) | list.parse, list.load, list.save, list.serialize,list.unserialize |
數據變換 | list.append, list.prepend, list.reverse, list.zip, list.rbind,list.cbind, list.stack, list.flatten, list.names, list.sample |
爲了方便在R中可視化JSON數據,jsonview將js中的jsonviewer庫引入到R中。
咱們能夠傳入list或者json字符串作非結構化數據的可視化。
library(xmlview) library(jsonlite) devtools::install_github("hrbrmstr/jsonview") jsonview::json_tree_view(fromJSON("https://collector.torproject.org/index.json"))
下面是timelyportfolio提供的一個結合shiny和jsonview的json編輯器的例子:
install.packages("shiny") devtools::install_github("timelyportfolio/listviewer") library(shiny) library(listviewer) # 數據準備 data(mtcars) ui <- shinyUI( fluidPage( jsoneditOutput( "jsed" ) ) ) server <- function(input,output){ output$jsed <- renderJsonedit({ jsonedit( as.list( .GlobalEnv ) ,"change" = htmlwidgets::JS('function(){ console.log( event.currentTarget.parentNode.editor.get() ) }') ) }) } runApp( list( ui = ui, server = server ) )
接着,在瀏覽器中的對應端口能夠打開這個json編輯器應用。
除了JSON以外,和NoSQL數據庫的交互在大數據時代也成爲了主流,混合使用Redis、Hive、MongoDB等數據庫也成了屢見不鮮,具體操做能夠翻看張丹老師的R利劍NoSQL系列文章。
做爲分享主義者(sharism),本人全部互聯網發佈的圖文均聽從CC版權,轉載請保留做者信息並註明做者 Harry Zhu 的 FinanceR 專欄: https://segmentfault.com/blog...,若是涉及源代碼請註明GitHub地址: https://github.com/harryprince。微信號: harryzhustudio 商業使用請聯繫做者。