将中间列表输出保存在 dplyr 管道中,并将其映射回管道下方的另一个列表 - R

Save intermediate list output in dplyr pipeline and map it back to another list further down the pipeline - R

我正在 运行使用 dplyr 管道对数据集中的组进行 pcas。我从 group_split 开始,所以我正在处理一个列表。为了 运行 prcomp() 函数,只能包含每个列表的 numeric 列,但我想在最后带回 factor 列用于绘图.我曾尝试在管道中途使用 {. ->> temp} 保存中间输出,但由于它是一个列表,我不知道如何在绘图时为分组列编制索引。

library(tidyverse)
library(ggbiplot)

iris %>%
  group_split(Species, keep = T) %>% #group by species, one pca per species
  {. ->> temp} %>%  # save intermediate output to preserve species column for use in plotting later
  map(~.x %>% select_if(is.numeric) %>% select_if(~var(.) != 0) %>% 
        prcomp(scale. = TRUE))%>% #run pca on numeric columns only
  map(~ggbiplot(.x), label=temp$Species)#plot each pca, labeling points as species names form the temporary object

这可以为 iris 数据集中的每个物种生成一个 pca 图,但由于 temp$species = NULL,这些点未标记。

一种选择是使用 splitimap

library(tidyverse)
library(ggbiplot)
iris %>%
split(.$Species) %>%  # save intermediate output to preserve species column for use in plotting later
map(~.x %>% select_if(is.numeric) %>% select_if(~var(.) != 0) %>% 
        prcomp(scale. = TRUE)) %>% 
imap(~ggbiplot(.x, labels = .y))

如果您使用 map2() 并将 .y 参数作为物种列表传递,您可以获得我认为您想要的结果。请注意,在您的原始代码中,labels 参数位于 ggbiplot() 函数之外,因此被忽略了。

library(tidyverse)
library(ggbiplot)

iris %>%
  group_split(Species, keep = T) %>% 
  {. ->> temp} %>%  
  map(~.x %>% 
        select_if(is.numeric) %>%
        select_if(~var(.) != 0) %>% 
        prcomp(scale. = TRUE)) %>% 
  map2(map(temp, "Species"), ~ggbiplot(.x, labels = .y))

针对您的评论,如果您想添加第三个参数,您可以使用 pmap() 而不是 map2()。在下面的示例中,pmap() 被传递给 ggbiplot() 参数的(嵌套)数据列表。请注意,我已经更改了 new 变量,因此它是一个因素,而不是跨组的常数。

iris %>%
  mutate(new = factor(sample(1:3, 150, replace = TRUE))) %>%
  group_split(Species, keep = T) %>% 
  {. ->> temp} %>%  
  map(~.x %>% 
        select_if(is.numeric) %>%
        select_if(~var(.) != 0) %>% 
        prcomp(scale. = TRUE)) %>% 
  list(map(temp, "Species"), map(temp, "new")) %>%
  pmap(~ ggbiplot(pcobj = ..1, labels = ..2, groups = ..3))