处理列表中的列表到R中的数据框

时间:2020-05-26 20:41:02

标签: r list dataframe

我是新手,在处理列表并将其转换为数据框时遇到一些问题

我有一个列表“ ddt”

str(ddt)
 List of 4
 $ id           : chr "18136"
 $ comments.data:List of 3
  ..$ :List of 3
  .. ..$ timestamp: chr "2020-05-25T16:17:32+0000"
  .. ..$ text     : chr "Mocaaa"
  .. ..$ id       : chr "18096"
  ..$ :List of 3
  .. ..$ timestamp: chr "2020-05-25T16:00:00+0000"
  .. ..$ text     : chr "Capucchino"
  .. ..$ id       : chr "17846"
  ..$ :List of 3
  .. ..$ timestamp: chr "2020-05-25T14:42:53+0000"
  .. ..$ text     : chr "Mocachino"
  .. ..$ id       : chr "18037"

 $ id           : chr "17920"
 $ comments.data:List of 1
  ..$ :List of 3
  .. ..$ timestamp: chr "2020-05-24T15:31:30+0000"
  .. ..$ text     : chr "Hello"
  .. ..$ id       : chr "18054"

我需要这个结果

     id                  timestamp         text     id2
1 18136   2020-05-25T16:17:32+0000       Mocaaa   18096
2 18136   2020-05-25T16:00:00+0000   Capucchino   17846
3 18136   2020-05-25T14:42:53+0000    Mocachino   18037
4 17920   2020-05-24T15:31:30+0000        Hello   18054

2 个答案:

答案 0 :(得分:1)

我认为使用data.table可以很好地做到这一点。

set.seed(42)
df <- replicate(2, list(id = sample(1e5, 1), comments = replicate(3, list(tm = as.character(Sys.time() + sample(10, 1)), text = sample(LETTERS, 1), id = sample(1e5, 1)), simplify = FALSE)), simplify = FALSE)
str(df)
# List of 2
#  $ :List of 2
#   ..$ id      : int 91481
#   ..$ comments:List of 3
#   .. ..$ :List of 3
#   .. .. ..$ tm  : chr "2020-05-26 14:44:08"
#   .. .. ..$ text: chr "H"
#   .. .. ..$ id  : int 83045
#   .. ..$ :List of 3
#   .. .. ..$ tm  : chr "2020-05-26 14:44:05"
#   .. .. ..$ text: chr "N"
#   .. .. ..$ id  : int 73659
#   .. ..$ :List of 3
#   .. .. ..$ tm  : chr "2020-05-26 14:44:00"
#   .. .. ..$ text: chr "R"
#   .. .. ..$ id  : int 70507
#  $ :List of 2
#   ..$ id      : int 45775
#   ..$ comments:List of 3
#   .. ..$ :List of 3
#   .. .. ..$ tm  : chr "2020-05-26 14:44:06"
#   .. .. ..$ text: chr "Y"
#   .. .. ..$ id  : int 25543
#   .. ..$ :List of 3
#   .. .. ..$ tm  : chr "2020-05-26 14:44:03"
#   .. .. ..$ text: chr "Y"
#   .. .. ..$ id  : int 97823
#   .. ..$ :List of 3
#   .. .. ..$ tm  : chr "2020-05-26 14:44:00"
#   .. .. ..$ text: chr "M"
#   .. .. ..$ id  : int 56034

我们必须面对的一件事是,您在顶层以及每个列表的内部都有id

library(data.table)
library(magrittr) # for %>%, demonstrative only, can be done without
data.table::rbindlist(df) %>%
  .[, comments := lapply(comments, as.data.table) ] %>%
  # we have a duplicate name 'id', rename in the inner ones
  .[, comments := lapply(comments, setnames, "id", "innerid") ] %>%
  .[, unlist(comments, recursive = FALSE), by = seq_len(nrow(.)) ]
#    seq_len                  tm text innerid
# 1:       1 2020-05-26 14:49:21    H   83045
# 2:       2 2020-05-26 14:49:18    N   73659
# 3:       3 2020-05-26 14:49:13    R   70507
# 4:       4 2020-05-26 14:49:19    Y   25543
# 5:       5 2020-05-26 14:49:16    Y   97823
# 6:       6 2020-05-26 14:49:13    M   56034

我怀疑by=seq_len(nrow(.))不能很好地扩展到更大的数据。由于Rdatatable/data.table#3672仍处于打开状态,因此可以选择仅用unlist替换最后一行(包括seq_len%>% tidyr::unnest(comments))。我怀疑data.tabletidyr的组合有时会引起争议,我建议这种无党派的方法会利用两者的优势。

答案 1 :(得分:1)

该结构看起来就像一个Java脚本对象。

您可以这样做:

library(jsonlite)
library(tidyr)

unnest(unnest(fromJSON(toJSON(df))))

# A tibble: 6 x 4
     id tm                  text    id1
  <int> <chr>               <chr> <int>
1 92345 2020-05-26 14:53:53 X      6730
2 92345 2020-05-26 14:53:56 Q     92812
3 92345 2020-05-26 14:53:56 D     25304
4  9847 2020-05-26 14:53:56 E     82734
5  9847 2020-05-26 14:54:01 I     75079
6  9847 2020-05-26 14:54:02 H     89373