为什么 jsonlite 将数据解析为列表对象?
Why jsonlite parses data into a list object ?
我尝试使用 jsonlite
解析来自网络 API 的数据,但由于某种原因,它 returns 的对象是一个列表。
jsonlite
包文档中说简化过程会自动将 JSON 列表转换为更具体的 R class 但在我的情况下它不起作用。
就像simplifyVector
、simplifyDataFrame
和simplifyMatrix
功能被禁用,但默认情况下每个功能都是启用的。
我想要一个数据框来检索 $Name
数据(EAC、EFL、ELC 等)。
我也尝试使用 rjson
库,但仍然是同样的问题。
知道哪里出了问题吗?
谢谢,
请找到我使用的代码:
raw <- getURL("https://www.cryptocompare.com/api/data/coinlist")
library(jsonlite)
data <- fromJSON(txt=raw)
> class(data)
[1] "list"
> typeof(data)
[1] "list"
> str(data)
[...]
..$ EAC :List of 13
.. ..$ Id : chr "4437"
.. ..$ Url : chr "/coins/eac/overview"
.. ..$ ImageUrl : chr "/media/19690/eac.png"
.. ..$ Name : chr "EAC"
.. ..$ CoinName : chr "EarthCoin"
.. ..$ FullName : chr "EarthCoin (EAC)"
.. ..$ Algorithm : chr "Scrypt"
.. ..$ ProofType : chr "PoW"
.. ..$ FullyPremined : chr "0"
.. ..$ TotalCoinSupply : chr "13500000000"
.. ..$ PreMinedValue : chr "N/A"
.. ..$ TotalCoinsFreeFloat: chr "N/A"
.. ..$ SortOrder : chr "100"
..$ EFL :List of 13
.. ..$ Id : chr "4438"
.. ..$ Url : chr "/coins/efl/overview"
.. ..$ ImageUrl : chr "/media/19692/efl.png"
.. ..$ Name : chr "EFL"
.. ..$ CoinName : chr "E-Gulden"
.. ..$ FullName : chr "E-Gulden (EFL)"
.. ..$ Algorithm : chr "Scrypt"
.. ..$ ProofType : chr "PoW"
.. ..$ FullyPremined : chr "0"
.. ..$ TotalCoinSupply : chr "21000000 "
.. ..$ PreMinedValue : chr "N/A"
.. ..$ TotalCoinsFreeFloat: chr "N/A"
.. ..$ SortOrder : chr "101"
..$ ELC :List of 13
.. ..$ Id : chr "4439"
.. ..$ Url : chr "/coins/elc/overview"
.. ..$ ImageUrl : chr "/media/19694/elc.png"
.. ..$ Name : chr "ELC"
.. ..$ CoinName : chr "Elacoin"
.. ..$ FullName : chr "Elacoin (ELC)"
.. ..$ Algorithm : chr "Scrypt"
.. ..$ ProofType : chr "PoW"
.. ..$ FullyPremined : chr "0"
.. ..$ TotalCoinSupply : chr "75000000"
.. ..$ PreMinedValue : chr "N/A"
.. ..$ TotalCoinsFreeFloat: chr "N/A"
.. ..$ SortOrder : chr "102"
.. [list output truncated]
$ Type : int 100
NULL
我回答我自己的问题 - 已经在评论部分说过 - 返回的对象已经是最简单的形式。可能 jsonlite
无法从多个列表(列表叠层)创建数据框。
我找到的解决方案是像这样使用 unlist
和 data.frame
:
> df <- data.frame(unlist(data))
> class(df)
[1] "data.frame"
您显示了结构的下端,但在结构的顶部看到了关于为什么未返回数据帧的问题的答案:
# note: needed `require(RCurl)` to obtain getURL
> str(data)
List of 6
$ Response : chr "Success"
$ Message : chr "Coin list succesfully returned!"
$ BaseImageUrl: chr "https://www.cryptocompare.com"
$ BaseLinkUrl : chr "https://www.cryptocompare.com"
$ Data :List of 492
..$ BTC :List of 13
.. ..$ Id : chr "1182"
.. ..$ Url : chr "/coins/btc/overview"
.. ..$ ImageUrl : chr "/media/19633/btc.png"
.. ..$ Name : chr "BTC"
.. ..$ CoinName : chr "Bitcoin"
.. ..$ FullName : chr "Bitcoin (BTC)"
.. ..$ Algorithm : chr "SHA256"
# ------snipped the many, many pages of output that followed---------
此外,该列表的 $Data 节点长度不规则,因此一步强制转换为数据帧可能很困难:
> table( sapply(data$Data, length))
12 13 14
2 478 12
加载 pkg:plyr 后,它提供了一个有用的函数来绑定相似但不相同的数据帧,我能够为进一步分析构建一个有用的起点:
require(plyr)
money <- do.call(rbind.fill, lapply( data$Data, data.frame, stringsAsFactors=FALSE))
str(money)
#------------
'data.frame': 492 obs. of 14 variables:
$ Id : chr "1182" "3808" "3807" "5038" ...
$ Url : chr "/coins/btc/overview" "/coins/ltc/overview" "/coins/dash/overview" "/coins/xmr/overview" ...
$ ImageUrl : chr "/media/19633/btc.png" "/media/19782/ltc.png" "/media/20626/dash.png" "/media/19969/xmr.png" ...
$ Name : chr "BTC" "LTC" "DASH" "XMR" ...
$ CoinName : chr "Bitcoin" "Litecoin" "DigitalCash" "Monero" ...
$ FullName : chr "Bitcoin (BTC)" "Litecoin (LTC)" "DigitalCash (DASH)" "Monero (XMR)" ...
$ Algorithm : chr "SHA256" "Scrypt" "X11" "CryptoNight" ...
$ ProofType : chr "PoW" "PoW" "PoW/PoS" "PoW" ...
$ FullyPremined : chr "0" "0" "0" "0" ...
$ TotalCoinSupply : chr "21000000" "84000000" "22000000" "0" ...
$ PreMinedValue : chr "N/A" "N/A" "N/A" "N/A" ...
$ TotalCoinsFreeFloat: chr "N/A" "N/A" "N/A" "N/A" ...
$ SortOrder : chr "1" "3" "4" "5" ...
$ TotalCoinsMined : chr NA NA NA NA ...
如果您希望能够通过这些加密货币的缩写访问行,您可以这样做:
rownames(money) <- names(data$Data)
现在可以让您这样做:
> money[ "BTC", ]
Id Url ImageUrl Name CoinName
BTC 1182 /coins/btc/overview /media/19633/btc.png BTC Bitcoin
FullName Algorithm ProofType FullyPremined TotalCoinSupply
BTC Bitcoin (BTC) SHA256 PoW 0 21000000
PreMinedValue TotalCoinsFreeFloat SortOrder TotalCoinsMined
BTC N/A N/A 1 <NA>
之前的访问会比较笨拙:
> money[ money$Name=="BTC", ]
我尝试使用 jsonlite
解析来自网络 API 的数据,但由于某种原因,它 returns 的对象是一个列表。
jsonlite
包文档中说简化过程会自动将 JSON 列表转换为更具体的 R class 但在我的情况下它不起作用。
就像simplifyVector
、simplifyDataFrame
和simplifyMatrix
功能被禁用,但默认情况下每个功能都是启用的。
我想要一个数据框来检索 $Name
数据(EAC、EFL、ELC 等)。
我也尝试使用 rjson
库,但仍然是同样的问题。
知道哪里出了问题吗?
谢谢,
请找到我使用的代码:
raw <- getURL("https://www.cryptocompare.com/api/data/coinlist")
library(jsonlite)
data <- fromJSON(txt=raw)
> class(data)
[1] "list"
> typeof(data)
[1] "list"
> str(data)
[...]
..$ EAC :List of 13
.. ..$ Id : chr "4437"
.. ..$ Url : chr "/coins/eac/overview"
.. ..$ ImageUrl : chr "/media/19690/eac.png"
.. ..$ Name : chr "EAC"
.. ..$ CoinName : chr "EarthCoin"
.. ..$ FullName : chr "EarthCoin (EAC)"
.. ..$ Algorithm : chr "Scrypt"
.. ..$ ProofType : chr "PoW"
.. ..$ FullyPremined : chr "0"
.. ..$ TotalCoinSupply : chr "13500000000"
.. ..$ PreMinedValue : chr "N/A"
.. ..$ TotalCoinsFreeFloat: chr "N/A"
.. ..$ SortOrder : chr "100"
..$ EFL :List of 13
.. ..$ Id : chr "4438"
.. ..$ Url : chr "/coins/efl/overview"
.. ..$ ImageUrl : chr "/media/19692/efl.png"
.. ..$ Name : chr "EFL"
.. ..$ CoinName : chr "E-Gulden"
.. ..$ FullName : chr "E-Gulden (EFL)"
.. ..$ Algorithm : chr "Scrypt"
.. ..$ ProofType : chr "PoW"
.. ..$ FullyPremined : chr "0"
.. ..$ TotalCoinSupply : chr "21000000 "
.. ..$ PreMinedValue : chr "N/A"
.. ..$ TotalCoinsFreeFloat: chr "N/A"
.. ..$ SortOrder : chr "101"
..$ ELC :List of 13
.. ..$ Id : chr "4439"
.. ..$ Url : chr "/coins/elc/overview"
.. ..$ ImageUrl : chr "/media/19694/elc.png"
.. ..$ Name : chr "ELC"
.. ..$ CoinName : chr "Elacoin"
.. ..$ FullName : chr "Elacoin (ELC)"
.. ..$ Algorithm : chr "Scrypt"
.. ..$ ProofType : chr "PoW"
.. ..$ FullyPremined : chr "0"
.. ..$ TotalCoinSupply : chr "75000000"
.. ..$ PreMinedValue : chr "N/A"
.. ..$ TotalCoinsFreeFloat: chr "N/A"
.. ..$ SortOrder : chr "102"
.. [list output truncated]
$ Type : int 100
NULL
我回答我自己的问题 - 已经在评论部分说过 - 返回的对象已经是最简单的形式。可能 jsonlite
无法从多个列表(列表叠层)创建数据框。
我找到的解决方案是像这样使用 unlist
和 data.frame
:
> df <- data.frame(unlist(data))
> class(df)
[1] "data.frame"
您显示了结构的下端,但在结构的顶部看到了关于为什么未返回数据帧的问题的答案:
# note: needed `require(RCurl)` to obtain getURL
> str(data)
List of 6
$ Response : chr "Success"
$ Message : chr "Coin list succesfully returned!"
$ BaseImageUrl: chr "https://www.cryptocompare.com"
$ BaseLinkUrl : chr "https://www.cryptocompare.com"
$ Data :List of 492
..$ BTC :List of 13
.. ..$ Id : chr "1182"
.. ..$ Url : chr "/coins/btc/overview"
.. ..$ ImageUrl : chr "/media/19633/btc.png"
.. ..$ Name : chr "BTC"
.. ..$ CoinName : chr "Bitcoin"
.. ..$ FullName : chr "Bitcoin (BTC)"
.. ..$ Algorithm : chr "SHA256"
# ------snipped the many, many pages of output that followed---------
此外,该列表的 $Data 节点长度不规则,因此一步强制转换为数据帧可能很困难:
> table( sapply(data$Data, length))
12 13 14
2 478 12
加载 pkg:plyr 后,它提供了一个有用的函数来绑定相似但不相同的数据帧,我能够为进一步分析构建一个有用的起点:
require(plyr)
money <- do.call(rbind.fill, lapply( data$Data, data.frame, stringsAsFactors=FALSE))
str(money)
#------------
'data.frame': 492 obs. of 14 variables:
$ Id : chr "1182" "3808" "3807" "5038" ...
$ Url : chr "/coins/btc/overview" "/coins/ltc/overview" "/coins/dash/overview" "/coins/xmr/overview" ...
$ ImageUrl : chr "/media/19633/btc.png" "/media/19782/ltc.png" "/media/20626/dash.png" "/media/19969/xmr.png" ...
$ Name : chr "BTC" "LTC" "DASH" "XMR" ...
$ CoinName : chr "Bitcoin" "Litecoin" "DigitalCash" "Monero" ...
$ FullName : chr "Bitcoin (BTC)" "Litecoin (LTC)" "DigitalCash (DASH)" "Monero (XMR)" ...
$ Algorithm : chr "SHA256" "Scrypt" "X11" "CryptoNight" ...
$ ProofType : chr "PoW" "PoW" "PoW/PoS" "PoW" ...
$ FullyPremined : chr "0" "0" "0" "0" ...
$ TotalCoinSupply : chr "21000000" "84000000" "22000000" "0" ...
$ PreMinedValue : chr "N/A" "N/A" "N/A" "N/A" ...
$ TotalCoinsFreeFloat: chr "N/A" "N/A" "N/A" "N/A" ...
$ SortOrder : chr "1" "3" "4" "5" ...
$ TotalCoinsMined : chr NA NA NA NA ...
如果您希望能够通过这些加密货币的缩写访问行,您可以这样做:
rownames(money) <- names(data$Data)
现在可以让您这样做:
> money[ "BTC", ]
Id Url ImageUrl Name CoinName
BTC 1182 /coins/btc/overview /media/19633/btc.png BTC Bitcoin
FullName Algorithm ProofType FullyPremined TotalCoinSupply
BTC Bitcoin (BTC) SHA256 PoW 0 21000000
PreMinedValue TotalCoinsFreeFloat SortOrder TotalCoinsMined
BTC N/A N/A 1 <NA>
之前的访问会比较笨拙:
> money[ money$Name=="BTC", ]