Power BI 中 R 中的嵌套列表 JSON

Nested lists in R to JSON for Power BI

我在 R 中创建了一个数据集,其中包含 20 个变量的 800 个观察值,其中一些是向量(不同长度) 例如 observation1: var1=1, var2="a", vec1=c("a", "b", "c"), vec2 = c(1,2,3) observation2: var1=1, var2="a", vec1=c("a"), vec2 = c(1,2,3,4,5)

我尝试创建单个数据框,但它不喜欢向量的不同长度,因此目前数据以长度为 800 的多个向量(一个用于 var1,一个用于 var2 等)和多个列表的形式存在长度为 800(包含 vec1、vec2 等)

将其组合成单个数据对象的唯一方法是使用嵌套列表吗?

最终我需要输出为 JSON 以引入 Power BI,但我不知道如何组合现有元素来实现。我尝试创建一个嵌套列表,然后创建 JSON(),但这不会解析为带有列的 table(在 Power BI 中),而是每个列表项显示为需要扩展的行分为 800 行。

非常感谢任何帮助!

由于您的最终目标是将此数据集导入 powerBI,因此最好使用数据框,因为在 powerBI 中您必须再次将其转换为表格结构,因此从数据框转换为 json 然后json 数据帧有点过头了。

现在将不同长度的向量转换为数据帧,您会收到错误消息,因为数据帧中的元素需要具有相同的长度。所以诀窍是通过用 NA 填充额外的元素(或任何占位符,如 'blank')来使这些元素具有相同的长度。

#function to generate vectors of varying length
temp_vectors = function(n){
  vector_list = vector('list', n)
  max_size = 0
  
  for(i in 1:n){
    vec_size = sample(1:20, 1)
    vector_list[[i]] = sample(1:10, vec_size, replace=TRUE)
    if(max_size < vec_size) max_size = vec_size
  }
  
  return(list('max_size' = max_size, 'vector_list' = vector_list))
}

x = temp_vectors(10)
vectors = x[['vector_list']]
n = x[['max_size']]

#the above code produces the following vector
vectors[1:2]
#> [[1]]
#>  [1] 6 8 5 5 9 2 1 2 4 7 3 8
#> 
#> [[2]]
#> [1] 1 4 8 8 7 9

#for loop to fill the extra places with NA
for(i in 1:10){
  if(length(vectors[[i]] != n)){
    length(vectors[[i]]) = n
  }
}

vectors[1:2]
#> [[1]]
#>  [1]  6  8  5  5  9  2  1  2  4  7  3  8 NA NA NA NA NA NA NA NA
#> 
#> [[2]]
#>  [1]  1  4  8  8  7  9 NA NA NA NA NA NA NA NA NA NA NA NA NA NA

#combining the vectors into df
df = data.frame(vectors)
colnames(df) = paste0('col.', 1:ncol(df))
df
#>    col.1 col.2 col.3 col.4 col.5 col.6 col.7 col.8 col.9 col.10
#> 1      6     1     3     7     8     6     5     3     6      9
#> 2      8     4    NA     7    10     8     5     1     8     NA
#> 3      5     8    NA    10     5     9     7    NA     1     NA
#> 4      5     8    NA     4     4     2     8    NA     8     NA
#> 5      9     7    NA    NA     6     6     6    NA     9     NA
#> 6      2     9    NA    NA     5     4     7    NA     4     NA
#> 7      1    NA    NA    NA     1     1     2    NA     8     NA
#> 8      2    NA    NA    NA     9     7     6    NA     5     NA
#> 9      4    NA    NA    NA     4     8    10    NA     8     NA
#> 10     7    NA    NA    NA     3     6    NA    NA     1     NA
#> 11     3    NA    NA    NA     1     6    NA    NA     9     NA
#> 12     8    NA    NA    NA     6     7    NA    NA     8     NA
#> 13    NA    NA    NA    NA     6     8    NA    NA    10     NA
#> 14    NA    NA    NA    NA     2     8    NA    NA    10     NA
#> 15    NA    NA    NA    NA     1     9    NA    NA     5     NA
#> 16    NA    NA    NA    NA     2     3    NA    NA     2     NA
#> 17    NA    NA    NA    NA     1     1    NA    NA    NA     NA
#> 18    NA    NA    NA    NA     6     6    NA    NA    NA     NA
#> 19    NA    NA    NA    NA    NA     9    NA    NA    NA     NA
#> 20    NA    NA    NA    NA    NA     9    NA    NA    NA     NA

reprex package (v0.3.0)

于 2020-07-04 创建

请注意,您可以对 800 个向量执行相同的操作,遍历它们并将它们的大小更改为最长向量的大小,额外的索引将自动填充 NA。

据我了解,您目前拥有:

vector_var1 <- c(1, 1)
vector_var2 <- c("a", "a")
list_vec1 <- list(c("a", "b", "c"), c("a"))
list_vec2 <- list(c(1,2,3), c(1,2,3,4,5))

您可以将其放入具有 列表列的数据框中 :

dat <- data.frame(
  var1 = vector_var1,
  var2 = vector_var2,
  vec1 = I(list_vec1),
  vec2 = I(list_vec2)
)

这给出了这个 JSON:

jsonlite::toJSON(dat, pretty = TRUE)
# [
#   {
#     "var1": 1,
#     "var2": "a",
#     "vec1": ["a", "b", "c"],
#     "vec2": [1, 2, 3]
#   },
#   {
#     "var1": 1,
#     "var2": "a",
#     "vec1": ["a"],
#     "vec2": [1, 2, 3, 4, 5]
#   }
# ]

是你需要的吗?

编辑

根据评论中的讨论,以下是如何使用 purrr::transposerlist::list.zip 获得预期结果:

vector_var1 <- c(1, 1)
vector_var2 <- c("a", "a")
list_vec1 <- list(c("a", "b", "c"), c("a", "b", "c", "d", "e"))
list_vec2 <- list(c(1,2,3), c(1,2,3,4,5))

L1 <- purrr::transpose(list(list_vec1, list_vec2))
L2 <- lapply(L1, function(vecs){
  do.call(rlist::list.zip, c(vecs, list(use.names=FALSE)))
})

dat <- data.frame(var1 = vector_var1, var2 = vector_var1, vec = I(L2))

jsonlite::toJSON(dat, auto_unbox = TRUE)
# [{"var1":1,"var2":1,"vec":[["a",1],["b",2],["c",3]]},{"var1":1,"var2":1,"vec":[["a",1],["b",2],["c",3],["d",4],["e",5]]}]