[原]數據科學教程:R語言與NoSQL

介紹

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

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

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

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

在R中有一個很是有意思的現象,那就是處理json時,咱們有三個選擇,jsonlite、rjson以及RJSONIO,三者各有特色,有時爲了處理一些問題還必須得混合使用。在實際處理字符串中,必定要注意的就是R中字符串的轉義問題。好比\\表示\\"表示"等等。我曾經由於Python和R中的雙層JSON解析屢次遇到轉義符號的問題。具體能夠參看官方手冊github

jsonlite

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

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

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 處理

談到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)
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 商業使用請聯繫做者。
相關文章
相關標籤/搜索