我正在尝试从数据框中获取JSON数组对象,其中每个JSON对象都是数据框的子集

> x <- 1:5
> y <-c('a','b','c','d','e')
> z <-c(1,1,1,2,2)
> df <-data.frame(x,y,z)
> df
    x y z
  1 1 a 1
  2 2 b 1
  3 3 c 1
  4 4 d 2
  5 5 e 2
> rjson::toJSON(df)
[1] "{\"x\":[1,2,3,4,5],\"y\":[\"a\",\"b\",\"c\",\"d\",\"e\"],\"z\":[1,1,1,2,2]}"
> df1 = toJSONArray2(na.omit(df), json = F, names = F)
> rjson::toJSON(df1)
[1] "[[1,\"a\",1],[2,\"b\",1],[3,\"c\",1],[4,\"d\",2],[5,\"e\",2]]"

我需要的输出是

[[[1,a],[2,b],[3,c]],[[4,d],[5,e]]]

下面的方法我能够按预期获取数据帧列表,但无法获取所需的json输出。
> x <- foreach(i=1:2) %do% { subset(df,df$z==i)[c(1,2)]}
> x
 [[1]]
   x y
 1 1 a
 2 2 b
 3 3 c

 [[2]]
   x y
 4 4 d
 5 5 e

找到了解决方案。
> x <- foreach(i=1:2) %do% {
   tmp <-subset(df,df$z==i)[c(1,2)]
   toJSONArray2(na.omit(tmp), json = F, names = F)
   }
> rjson::toJSON(x)

我需要一个没有toJSONArray2的实现,这很慢

最佳答案

toJSONArray2中的rCharts函数很慢,主要是因为使用了RJSONIO。我正在使用rjson将其更新为更快的实现。这是我到目前为止所拥有的。我从orient借用了pandas参数的想法。

to_json = function(df, orient = "columns", json = T){
  dl = as.list(df)
  dl = switch(orient,
    columns = dl,
    records = do.call('zip_vectors_', dl),
    values = do.call('zip_vectors_', setNames(dl, NULL))
  )
  if (json){
    dl = rjson::toJSON(dl)
  }
  return(dl)
}

zip_vectors_ = function(..., names = F){
  x = list(...)
  y = lapply(seq_along(x[[1]]), function(i) lapply(x, pluck_(i)))
  if (names) names(y) = seq_along(y)
  return(y)
}

pluck_ = function (element){
  function(x) x[[element]]
}

下面的示例将向您显示to_jsontoJSONArray2快20倍,其中大部分是由于使用了rjson而不是RJSONIO而引起的。
N = 10^3

df <- data.frame(
  x = rpois(N, 10),
  y = sample(LETTERS, N, replace = T),
  z = rpois(N, 5)
)

library(microbenchmark)
autoplot(microbenchmark(
  to_json(df, orient = "values", json = T),
  toJSONArray2(df, names = F),
  times = 5
))

更新:在更仔细地阅读您的问题时,我意识到我们可以通过使用dplyrto_json进一步加快速度
library(dplyr)

dfl = df %.%
  group_by(z) %.%
  do(function(x){
    to_json(x[-3], orient = 'values', json = F)
  })

09-04 13:33
查看更多