purrr: How to intersect one list with several nested lists

六眼飞鱼酱① 提交于 2019-12-11 18:12:06

问题


I have a data.frame containing parties in government. These parties are nested in a list column grouped by period (= each year).

I want to compare the overlap between each government and previous governments.

library(tidyverse)

df <- tibble::tribble(
  ~period, ~party, ~seats,
        1,    "A",      2,
        1,    "B",      3,
        1,    "C",      3,
        2,    "A",      2,
        2,    "C",      3,
        3,    "C",      4,
        3,    "E",      1,
        3,    "F",      3
  )


df1 <- df %>% 
  group_by(period) %>% 
  nest() %>% 
  mutate(gov=map(data, "party") %>% map(.,list)) %>% 
  mutate(prev.govs=map(data, "party") %>% 
           map(., list) %>%
           accumulate(.,union))

To make the comparison I created a list which includes nested lists for each previous government (prev.govs). Each nested list shoudl be compared (intersect) with the list containing the present government (gov). Here's where I got stuck.

I tried to use map2 of the purrr package and compare the list containing the parties of the present gov with the (nested) lists containing parties of previous governments (prev.govs). Unfortunately, here I get stuck.

Failed approaches:

df2 <- df1%>% 
  mutate(rep=map2(.x=gov, .y=prev.govs, .f=intersect))

df2 <- df1%>% 
  mutate(rep=map(gov, ~map2(., prev.govs, intersect)))

df2 <- df1%>% 
  mutate(rep=modify_depth(prev.govs, 2, ~map2(.,gov, intersect)))
#> Error in mutate_impl(.data, dots): Evaluation error: Mapped vectors must have consistent lengths:
#> * `.x` has length 2
#> * `.y` has length 3.

What I am trying to get is for each period a list with nested lists for each previous government. Each nested list contains the parties which overlap with the present government. A simplified case on two list hopefully makes this sufficiently clear:

new <- list(c("A" ,"C", "E", "F"))
old <- list(c("A", "B", "C"), c("A", "C"), c("D", "E", "F"))

map2(new, old, intersect)
#> [[1]]
#> [1] "A" "C"
#> 
#> [[2]]
#> [1] "A" "C"
#> 
#> [[3]]
#> [1] "E" "F"

回答1:


I think the below syntax is more clear and also more convenient for debugging because you can throw a breakpoint inside the first map2 code block and check the shape of the data.

df1$comparison <- map2(df1$gov, df1$prev.govs, function(curGov, prevGov) {
  map2(curGov, prevGov, intersect)
})

but if you want to stick to mutate, you can do the following. However, I think it's very confusing and it's better maybe just use the full named function.

df1 <- df1 %>% mutate(comparison = map2(gov, prev.govs, ~map2(.x, .y, intersect)))

# or better use named parameters

df1 <- df1 %>%
  mutate(
    comparison = map2(
      gov, 
      prev.govs,
      function(curGov, prevGov) {
        map2(curGov, prevGov, intersect)
      }
    )
  )


来源:https://stackoverflow.com/questions/54582821/purrr-how-to-intersect-one-list-with-several-nested-lists

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!