将具有不同长度的嵌套列表嵌入数据框中

By simon at 2018-02-28 • 0人收藏 • 23人看过

我使用R和包mongolite从MongoDB获取数据。这个 导致由大量嵌套列表组成的数据不能简化 通过使用unlist,rbindlist或dplyr(at。)中的bind_rows将其转换为数据框 至少我没有设法做到这一点)。 经过大量的试验和错误之后,我找到了一种使用该软件包的方法 用功能融化并使用dplyr和ti重塑dyr让它进入 我想要它的形式。然而,融化需要很长时间(最多15分钟) 每个清单,我有6吨下摆)。 你有什么想法,我怎么能使这个更快? (当然另一种可能 解决方案是查询MongoDB的相关性这样就不会导致结果 在列表中,但更像是我的目标数据框)。 以下代码创建一个虚拟具有相似属性的数据集,目标 数据集的形式和我的解决方案。 虚拟数据:

dummy_data <- list(
  list(actions = list(list(action_type = "link_clicks", value = 30), 
                      list(action_type = "post_likes", value = 3)), 
       date = '2015-08-04'), 
  list(actions = list(list(action_type = "link_clicks", value = 10), 
                      list(action_type = "post_likes", value = 2),
                      list(action_type = "page_engagement", value = 5)), 
       date = '2015-08-02')
  )
塔尔格et形式:
final_data = data.frame(c(30, 10), c(3, 2), c(NA, 5), c('2015-08-04', '2015-08-02'))
names(final_data) = c('actions: link_clicks', 'actions: post_likes', 'actions: page_engagement', 'date')
final_data
临时解决方案
Solution <- reshape2::melt(dummy_data)
Solution <- Solution %>% 
  select(L1, L2, L3, L4, value) %>%
  mutate(L4 = ifelse(is.na(L4), L2, L4)) %>% 
  spread(key = L4, value = value) %>%
  mutate(L2 = ifelse(!is.na(action_type), paste0(L2, ": ", action_type), L2),
         value = ifelse(!is.na(value), value, date)) %>%
  select(L1, L2, value) %>%
  spread(key = L2, value = value) %>% 
  select(-L1)
如果你对mongolite查询有任何建议,这里是最简单的kind的 我使用的查询:
M_DB <- mongolite::mongo(collection = "name", url = "url")
M_DB_List <- M_DB$iterate()$batch(size = 100000) 
非常感谢 编辑:更复杂的数据结构,因为这更接近我的问题
 dummy_data_complex <- list(
  list(actions = list(list(action_type = "link_clicks", value = 30), 
                      list(action_type = "post_likes", value = 3)), 
       date = '2015-08-04',
       currency = 'EUR'), 
  list(actions = list(list(action_type = "link_clicks", value = 10), 
                      list(action_type = "post_likes", value = 2),
                      list(action_type = "page_engagement", value = 5)), 
       date = '2015-08-02',
       demographics = list(gender = "female", 
                           list(actions = list(action_type = "link_clicks", value = 10)))
  ))

3 个回复 | 最后更新于 2018-02-28
2018-02-28   #1

这是一个tidyverse的选项

library(tidyverse)
dummy_data %>% 
     map_df(~ .x %>%
                 as_tibble(.) %>%
                 mutate(actions = map(actions, as_tibble)) %>%
                          unnest)   %>%
     group_by(date, action_type) %>%
     mutate(n = row_number()) %>%
     spread(action_type, value) %>%
     select(-n)
# A tibble: 2 x 4
# Groups: date [2]
#   date       link_clicks page_engagement post_likes
#* <chr>            <dbl>           <dbl>      <dbl>
#1 2015-08-02        10.0            5.00       2.00
#2 2015-08-04        30.0           NA          3.00

2018-02-28   #2

这是一个tidyverse的选项

library(tidyverse)
dummy_data %>% 
     map_df(~ .x %>%
                 as_tibble(.) %>%
                 mutate(actions = map(actions, as_tibble)) %>%
                          unnest)   %>%
     group_by(date, action_type) %>%
     mutate(n = row_number()) %>%
     spread(action_type, value) %>%
     select(-n)
# A tibble: 2 x 4
# Groups: date [2]
#   date       link_clicks page_engagement post_likes
#* <chr>            <dbl>           <dbl>      <dbl>
#1 2015-08-02        10.0            5.00       2.00
#2 2015-08-04        30.0           NA          3.00

2018-02-28   #3

我能够为我的问题找到一个快速解决方案。这是通过使用解决 作为SymbolixAU建议的另一个查询。 而不是使用g iterate()我用find()然后得到一个数据帧 里面有嵌套列表。 从这个时候起,我很容易就能够o使用tidyr :: unnest()获取我的目标 谢谢你的帮助。

登录后方可回帖

Loading...