【问题标题】:Turning data frame observations into list of lists将数据框观察结果转换为列表列表
【发布时间】:2018-03-14 00:55:55
【问题描述】:

我在 R 中有一个包含三列的数据框。

  1. lhs
  2. rhs
  3. 定罪
example <- data.frame(lhs=c('phones', 'phones', 'phones',
                            'shoes', 'shoes', 'shoes'),
                      rhs=c('chargers', 'headphones', 'shoes',
                            'shirts', 'pants', 'socks'),
                      conviction=c(1.376, 1.259, 1.087,
                                   1.295, 1.083, 0.978))

看看输出。

我想要做的是把它变成一个数据框,在 lhs 中每个项目有一列,列表列表作为第二列,格式为 [[rhs, confidence],[rhs,conviction]]

类似这样的:

所有这一切的最终目标是拥有一个嵌套的 JSON 文件。

最终的 JSON 应如下所示:

感谢您的帮助。

【问题讨论】:

  • library(tidyr); example %&gt;% nest(-lhs) 就足够了吗?也许更有用的是,生成的 JSON 应该是什么样子?
  • 谢谢阿利斯泰尔。我进行了编辑以包含理想的 JSON。现在正在考虑建议。

标签: json r dataframe


【解决方案1】:

您可以使用tidyversenest 部分数据框。这仍然会给您留下一个嵌套的 tibble 列。要将此列转换为列表,您可以像这样使用maplapply

library(tidyverse)
ans <- example %>%
          nest(-lhs) %>%
          mutate(data = map(data, ~lapply(1:nrow(.x), function(i) .x[i,]))) %>%
          rename(rhs = data)

rhs 列如下所示

ans$rhs
# [[1]]
# [[1]][[1]]
# # A tibble: 1 x 2
       # rhs conviction
    # <fctr>      <dbl>
# 1 chargers      1.376

# [[1]][[2]]
# # A tibble: 1 x 2
         # rhs conviction
      # <fctr>      <dbl>
# 1 headphones      1.259

# [[1]][[3]]
# # A tibble: 1 x 2
     # rhs conviction
  # <fctr>      <dbl>
# 1  shoes      1.087


# [[2]]
# [[2]][[1]]
# # A tibble: 1 x 2
     # rhs conviction
  # <fctr>      <dbl>
# 1 shirts      1.295

# [[2]][[2]]
# # A tibble: 1 x 2
     # rhs conviction
  # <fctr>      <dbl>
# 1  pants      1.083

# [[2]][[3]]
# # A tibble: 1 x 2
     # rhs conviction
  # <fctr>      <dbl>
# 1  socks      0.978

EDIT 返回特定格式的输出

我意识到您仍然会得到带有上述答案的小标题列表,要转换为向量列表,请使用以下(unlist 添加)

mutate(data = map(data, ~lapply(1:nrow(.x), function(i) unlist(.x[i,]))))

【讨论】:

  • purrr::maplapply 做同样的事情,所以同时使用会让人困惑。此外,在 R 中,总是有比迭代索引更直接的路径。
  • @alistaire 我总是对如何处理嵌套映射语句的范围感到困惑。例如,map(data, ~map(1:nrow(.x), ~function(i) unlist(.x[.x?,])))。如何同时引用外部映射.x 和内部映射.x?这是我使用内圈的唯一原因。感谢您的任何见解
  • @alistaire 由于我正在尝试遍历 data.frame/tibble,有没有更好的方法来遍历数据? (我喜欢iterators::iter,但它不能与map 一起使用)。感谢您的任何想法
  • 如果您使用split,则无需遍历行:example %&gt;% nest(-lhs, .key = 'rhs') %&gt;% mutate(rhs = map(rhs, ~split(.x, seq(nrow(.x)))))。更一般地说,如果您正在迭代迭代,您应该首先考虑是否有必要(它是否可矢量化?)。如果是这样,请考虑modify_depth。在语法方面,您可以使用 map(map, ~.x) 或在 purrr 中使用常规函数表示法来区分变量,而不是 ~ 样式。
  • @alistaire,谢谢。 1:split 是更好的选择。 2:没有意识到我可以使用常规函数表示法。也谢谢你。
【解决方案2】:

要获得必要的 JSON 结构,您确实需要一个列表,因为 data.frame 无法为您提供所需的嵌套结构。使用一点 dplyr,您可以将 summarise 每组分组数据放入一个 data.frame,使用 rhs 作为 conviction 的每个值的名称。将结果列表的名称设置为 rhs 的值并转换为 JSON,您将得到

library(dplyr)

example <- data.frame(lhs=c('phones', 'phones', 'phones', 'shoes', 'shoes', 'shoes'),
                      rhs=c('chargers', 'headphones', 'shoes', 'shirts', 'pants', 'socks'),
                      conviction=c(1.376, 1.259, 1.087, 1.295, 1.083, 0.978))

example %>% 
    group_by(lhs) %>% 
    summarise(rest = list(as.data.frame(t(setNames(conviction, rhs))))) %>% 
    { setNames(.$rest, .$lhs) } %>% 
    jsonlite::toJSON(pretty = TRUE)
#> {
#>   "phones": [
#>     {
#>       "chargers": 1.376,
#>       "headphones": 1.259,
#>       "shoes": 1.087
#>     }
#>   ],
#>   "shoes": [
#>     {
#>       "shirts": 1.295,
#>       "pants": 1.083,
#>       "socks": 0.978
#>     }
#>   ]
#> }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-02
    • 2022-11-11
    • 1970-01-01
    • 2020-04-17
    相关资源
    最近更新 更多