解析一列json并与另一列绑定以制作数据框

问题描述

我有采用以下格式的数据:

queue.finish();

have <- structure(list(V1 = c(4L,28L,2L),V2 = c("[{\"group\":1,\"topic\":\"A\"},{\"group\":1,\"topic\":\"B\"},{\"group\":2,\"topic\":\"C\"},\"topic\":\"T\"},\"topic\":\"U\"},{\"group\":3,\"topic\":\"V\"},\"topic\":\"D\"},\"topic\":\"R\"},{\"group\":4,\"topic\":\"Q\"},\"topic\":\"S\"},\"topic\":\"W\"},{\"group\":6,\"topic\":\"O\"},\"topic\":\"P\"},\"topic\":\"E\"},\"topic\":\"F\"},\"topic\":\"G\"},\"topic\":\"H\"},\"topic\":\"I\"},\"topic\":\"J\"},\"topic\":\"K\"},\"topic\":\"L\"},\"topic\":\"M\"},\"topic\":\"N\"}]","[]","[{\"group\":2,\"topic\":\"M\"}]") ),row.names = c(NA,3L),class = "data.frame") 内容是每行的嵌套分组,如 V2

我想获得一个宽数据框,其中每一行的组+主题的每个组合都有一个指示符 (1/0)(请参阅 [{"group":1,"topic":"A"},{"group":1,"topic":"B"}...])。像这样:

also_have

第一步是解析json。

我可以使用 # A tibble: 3 x 4 id topic_id_1 topic_id_2 topic_id_3 topic_id_4 ... <dbl> <dbl> <dbl> <dbl> 1 4 1 1 0 2 28 0 0 0 3 2 0 0 0 取消嵌套到列表中,但我不确定如何将 purrr::map(have$V2,jsonlite::fromJSON) 列(我们可能会重命名V1)绑定到列表的每个元素结果列表(请注意,列表元素二是空的,因为 id 是空的)。下面是第一个元素的片段添加V1==28 (id)

V1

或者,我认为 [[1]] group topic id 1 1 A 4 2 1 B 4 3 2 C 4 4 2 T 4 ... 会让我更接近我最终需要的东西,但在这里我也不确定如何添加purrr::map_df(have$V2,jsonlite::fromJSON) (id)。>

V1

停止。

我想如果我能用 df <- purrr::map_df(have$V2,jsonlite::fromJSON) df What I get: group topic 1 1 A 2 1 B 3 2 C 4 2 T ... What I want (notice `V1==28` does not appear): group topic id 1 1 A 4 2 1 B 4 3 2 C 4 4 2 T 4 5 2 U 4 6 3 V 4 7 3 D 4 8 3 R 4 9 4 A 4 10 4 Q 4 11 4 S 4 12 4 W 4 13 6 O 4 14 6 P 4 15 6 E 4 16 6 F 4 17 6 G 4 18 6 H 4 19 6 I 4 20 6 J 4 21 6 K 4 22 6 L 4 23 6 M 4 24 6 N 4 25 2 C 2 26 3 D 2 27 6 O 2 28 6 P 2 29 6 E 2 30 6 G 2 31 6 M 2 得到上面的数据框,我就能得到剩下的方法。最终目标是将这些信息与 id 结合起来,然后进行广泛的调整。

also_have

更新:

应用@akrun 的解决方案:

# join
also_have <- expand_grid(c(1:6),c(LETTERS)) %>%
  mutate(topic_id = 1:n()) %>%
  magrittr::set_colnames(c("group","topic","topic_id")) %>%
  select(topic_id,group,topic)

# pivot wide

# A tibble: 3 x 4
     id topic_id_1 topic_id_2 topic_id_3 topic_id_4 ...
  <dbl>      <dbl>      <dbl>      <dbl>
1     4          1          1          0
2    28          0          0          0
3     2          0          0          0

解决方法

我们可以传递一个命名向量,然后在 .id 中使用 map_dfr

 purrr::map_dfr(setNames(have$V2,have$V1),jsonlite::fromJSON,.id = 'id')

-输出

id group topic
1   4     1     A
2   4     1     B
3   4     2     C
4   4     2     T
5   4     2     U
6   4     3     V
7   4     3     D
8   4     3     R
9   4     4     A
10  4     4     Q
11  4     4     S
12  4     4     W
...

或者这可以在使用 dplyr

后在 rowwise 框架本身内完成
library(tidyr)
have %>%
    rowwise %>%
    transmute(ID = V1,V2 = list(fromJSON(V2))) %>% 
    ungroup %>%
    unnest(c(V2),keep_empty = TRUE) %>% 
    select(-V2)
# A tibble: 32 x 3
      ID group topic
   <int> <int> <chr>
 1     4     1 A    
 2     4     1 B    
 3     4     2 C    
 4     4     2 T    
 5     4     2 U    
 6     4     3 V    
 7     4     3 D    
 8     4     3 R    
 9     4     4 A    
10     4     4 Q    
# … with 22 more rows

第二步做一个join

out <-  have %>%
     rowwise %>%
     transmute(ID = V1,V2 = list(fromJSON(V2))) %>% 
     ungroup %>%
     unnest(c(V2),keep_empty = TRUE) %>% 
     select(-V2) %>% right_join(also_have)
out
Joining,by = c("group","topic")
# A tibble: 163 x 4
      ID group topic topic_id
   <int> <int> <chr>    <int>
 1     4     1 A            1
 2     4     1 B            2
 3     4     2 C           29
 4     4     2 T           46
 5     4     2 U           47
 6     4     3 V           74
 7     4     3 D           56
 8     4     3 R           70
 9     4     4 A           79
10     4     4 Q           95
# … with 153 more rows