[原]數據流編程教程:R語言與非結構化數據共舞

作為分享主義者(sharism),本人所有互聯網發布的圖文均遵從CC版權,轉載請保留作者信息並註明作者 Harry Zhu 的 FinanceR 專欄:FinanceR - SegmentFault,如果涉及源代碼請註明GitHub地址:harryprince (HarryZhu) · GitHub。微信號: harryzhustudio

商業使用請聯繫作者。

介紹

現代化數據科學中的 DataFrame 概念源起R語言,而 Python Pandas 和 Spark DateFrame 都是參考R設計的。不過在實際的網路數據通訊中,類似DateFrame這樣的格式卻並不是主流,真正主流的方式其實是JSON(JavaScript Object Notation),所以討論如何處理非結構化數據就變得非常有意義了。加之,近年來 Redis、MongoDB、ELK等非結構化資料庫的繁榮,MySQL 5.7之後也已經添加了對JSON格式的原生支持(之前可以用blob、longtext等格式存儲),非結構化數據更是在數據處理中變得流行。

本文將從 非結構化數據的轉化、處理以及可視化三個方面討論如何在R中操作非結構化數據。

數據清洗:JSON、List、DataFrame的三國殺

DataFrame 是R中的結構化數據結構,List 是R中的非結構化數據。JSON、List、DataFrame三者之間的互相轉化是數據科學中非常頻繁的一類操作。

在R中有一個非常有意思的現象,那就是處理json時,我們有三個選擇,jsonlite、rjson以及RJSONIO,三者各有特點,有時為了處理一些問題還必須得混合使用。在實際處理字元串中,一定要注意的就是R中字元串的轉義問題。比如表示,"表示"等等。我曾經因為Python和R中的雙層JSON解析多次遇到轉義符號的問題。具體可以參看官方手冊。

jsonlite

jsonlite 是我最常用的一個json處理包,因為jsonlite可以一步將 json 轉成 dataframe 再 從dataframe 轉到 json,在數據處理中可以輕鬆解決常見的 json轉化問題。此外,jsonlite 還完美支持utf-8,在 json 字元串錯誤時會有明顯的錯誤提示。

jsonlite 的劣勢是當出現雙層 json 時,jsonlite 會將json轉成dataframe格式的 list,這直接導致我們在用 length() 或者 dim() 求內層 JSON 的維度會出現錯誤。

jsonlite::fromJSON("{"x":"量化投資","y":"harryzhu"}")n

$xn[1] "量化投資"nn$yn[1] "harryzhu"n

rjson

rjson 和 jsonlite最大不同之處在於,rjson將json轉化為一個list,而list是R語言中非結構化數據的事實標準,類似 python 中的 dict,或者 matlab 中的 cell。

值得注意的是,rjson在json轉化中直接保持所有的浮點型數據,而jsonlite和RJSONIO則可以通過參數控制保留若干位小數的精度。

rjson::fromJSON("{"x":"1","y":"2"}")nrjson::toJSON(pi)n

$xn[1] "1"nn$yn[1] 2nn[1] "3.14159265358979"n

jsonlite::fromJSON(pi,digit=4)n

[1] "[ 3.142 ]"n

RJSONIO

RJSONIO 允許傳入沒有轉義符號的 JSON 字元串,並且支持將缺失值(NA)直接轉成 Null,需要小心的是RJSONIO只支持unicode,如果傳入utf-8則會釀成悲劇。

RJSONIO::fromJSON(RJSONIO::toJSON(c(1,2,NA,4)))n

"[[1]]n[1] 1nn[[2]]n[1] 2nn[[3]]nNULLnn[[4]]n[1] 4"n

更多細節可以參考 A biased comparsion of JSON packages in R

數據處理:List 處理

談到list的處理就不得不談一談 rlist包。rlist包是任坤老師貢獻到CRAN上的,任坤老師既是一個多產的R Developer (pipeR、formattable作者)也是一名量化投資者,目前在做私募方面的創業。想要學習rlist,我們可以參考一下任坤老師的演講:跳出數據框,擁抱非結構化數據和官方教程。

rlist與高階函數

rlist 是支持高階函數表達式的,借鑒了Python、Scala等語言中的MapReduce模型,rlist也為list提供了map、filter、reduce、group、join、search、sort等高級數據操作,熟悉這些操作以後上手sparkR的RDD操作非常有幫助。

示例一:

利用 GitHub API,我們可以知道Hadley 的原創R語言開源項目中討論議題數量最多的10個項目是哪些。

library(rlist)nlibrary(pipeR)n# 分頁讀取數據nrepos <-n"https://api.github.com/users/hadley/repos?per_page=100&page=%d" %>>%nsprintf(1:2) %>>%nlist.load("json") %>>%nlist.ungroupnnrepos %>>%nlist.filter(has_issues, !fork, language == "R") %>>%nlist.names(name) %>>%nlist.mapv(open_issues) %>>%nlist.sort(-.) %>>%nlist.take(10)n# dplyr ggplot2 lubridate devtools staticdocs plyrn# 88 72 54 33 32 28n# stringr roxygen3 scales gtablen# 24 22 22 21n

示例二:

批量讀取非空 csv 文件並且合併成一個 data frame:

"data/" %>>%nlist.files(".csv", full.names = TRUE) %>>%nlist.filter(file.info(.)$size > 0) %>>%nlist.map(read.csv(., header = TRUE, stringsAsFactors = FALSE)) %>>%nlist.stackn

rlist擴展包充分利用了R語言中list對象的特性,定義了一整套函數來幫助用戶靈活快速地按要求處理各種非結構化數據,同時結合pipeR包中管道操作符的使用,使R程序更加具有可讀性,應用更加人性化。

更多操作

下面是rlist中提供的操作:

為了方便在R中可視化JSON數據,jsonview將js中的jsonviewer庫引入到R中。

非結構化數據可視化

我們可以傳入list或者json字元串做非結構化數據的可視化。

library(xmlview)nlibrary(jsonlite)ndevtools::install_github("hrbrmstr/jsonview")njsonview::json_tree_view(fromJSON("https://collector.torproject.org/index.json"))n

下面是timelyportfolio提供的一個結合shiny和jsonview的json編輯器的例子:

install.packages("shiny")ndevtools::install_github("timelyportfolio/listviewer")nlibrary(shiny)nlibrary(listviewer)nn# 數據準備ndata(mtcars)nnui <- shinyUI(n fluidPage(n jsoneditOutput( "jsed" )n )n)nnserver <- function(input,output){n output$jsed <- renderJsonedit({n jsonedit(n as.list( .GlobalEnv )n ,"change" = htmlwidgets::JS(function(){n console.log( event.currentTarget.parentNode.editor.get() )n })n )nn })n}nnrunApp( list( ui = ui, server = server ) )n

接著,在瀏覽器中的對應埠可以打開這個json編輯器應用。

章節附註

除了JSON之外,和NoSQL資料庫的交互在大數據時代也成為了主流,混合使用Redis、Hive、MongoDB等資料庫也成了家常便飯,具體操作可以翻看張丹老師的R利劍NoSQL系列文章。

參考資料

  • A biased comparsion of JSON packages in R

  • 任坤:跳出數據框,擁抱非結構化數據

  • rlist-tutorial

  • jsonview GitHub

推薦閱讀:

數據分析中常見的七種回歸分析以及R語言實現(二)---逐步回歸
ggplot2繪製漂亮的直方圖
離散顏色標度連續化的最佳實踐
R語言 RStudio快捷鍵總結
R語言文本挖掘包安裝方法匯總

TAG:R编程语言 | 数据 | JSON |