2
votes
 library(tidyverse)

Using the sample datasets below (three for 201603, and three for 201602), I'm attempting to use two master datasets to filter several other datasets by using tidyverse tools such as dplyr::semi_join, purrr::map2, and purrr::pmap. I would like the output to be a list of the filtered data. However I've become stuck while trying to use pmap() to accomplish all this in one set of code so I can output one list of all the filtered data.

This example is a bit complicated, so I'll try to break it down. First, I used this code to put the two "201603" datasets that need to be filtered into a list called "List1". I then used purrr::map to change the Id column name so that I can use a semi_join after.

List1<-list(One201603,Two201603)%>%
map(~rename(.x,"Id"="ID"))

Next, I used purrr::map2 to iterate over List1, and a list of MainData201603, which is the master dataset for 201603 that is being used to filter the other two datasets. This outputs a list, and then I change the list element names with purrr::set_names.

Df<-map2(List1,list(MainData201603),semi_join,by="Id")%>%
set_names(c("One201603","Two201603"))

Everything works up to here, but now I have another master dataset called "MainData201602", as well as two other datasets that need to be filtered, "One201602", and "Two201602". I could simply follow the same steps as above, but I don't want to repeat code and I feel there's a more elegant way to do it all in one step using purrr tools such as pmap(). I'm thinking something like the code below, which doesn't work. I tried several other variations of pmap and lists, but couldn't figure it out. Help would be appreciated!

List2<-list(One201602,Two201602)%>%
map(~rename(.x,"Id"="ID"))

 Df<-pmap(list(List1,list(KPI201603)),list(List2,list(KPI201602)),semi_join,by="Id")%>%
map(~set_names(.x,c("One201603","Two201603","One201602","Two201602")))



Id<-c(6666,3333,1111,9999,8888,5555,2222,4444)
Animal<-c("Rabbit", "Moose", "Dog", "Cat", "Squirrel", "Raccoon", "Fish", "Elephant")
MainData201603<-data_frame(Id,Animal)

ID<-c(6666,3333,4545,6767,3322,1111,8888,8876,9990,1234,7775,3445)
Person<-c("Chris","Yuki","Mike","Darren","Katrina","Camilla","Dreanna","Nathan","Aisha","Sra","Pierre","Luigi")
One201603<-data_frame(ID,Person)

ID<-c(6666,8888,4453,1243,1111,5567,4543,8898,4444,7665,7889,5554)
Person<-c("Mr.K","Ms.S","Mr.P","Mr.B","Mrs.N","Mrs.W","Mr.D","Ms.A","Ms.M","Mr.X","Mrs.Z","Ms.T")
Two201603<-data_frame(ID,Person) 

MainData201602<-MainData201603

One201602<-One201603

Two201602<-Two201603
1

1 Answers

0
votes

Here is a possible solution. The idea is to create List1 and List2 with proper names. And then create a list called target, containing List1 and List2, and a list called master, containing list(MainData201603) and list(MainData201602). After that, we can use map2 to apply the map2 function you developed to target and master.

List1 <- list(One201603,Two201603)%>%
  map(~rename(.x,"Id"="ID")) %>%
  set_names(c("One201603","Two201603"))

List2 <- list(One201602,Two201602)%>%
  map(~rename(.x,"Id"="ID")) %>%
  set_names(c("One201602","Two201602"))

target <- list(List1, List2)
master <- list(list(MainData201603), list(MainData201602))

map2(target, master, ~map2(.x, .y, semi_join, by = "Id"))
[[1]]
[[1]]$One201603
# A tibble: 4 x 2
     Id Person 
  <dbl> <chr>  
1  6666 Chris  
2  3333 Yuki   
3  1111 Camilla
4  8888 Dreanna

[[1]]$Two201603
# A tibble: 4 x 2
     Id Person
  <dbl> <chr> 
1  6666 Mr.K  
2  8888 Ms.S  
3  1111 Mrs.N 
4  4444 Ms.M  


[[2]]
[[2]]$One201602
# A tibble: 4 x 2
     Id Person 
  <dbl> <chr>  
1  6666 Chris  
2  3333 Yuki   
3  1111 Camilla
4  8888 Dreanna

[[2]]$Two201602
# A tibble: 4 x 2
     Id Person
  <dbl> <chr> 
1  6666 Mr.K  
2  8888 Ms.S  
3  1111 Mrs.N 
4  4444 Ms.M