R计算后合并回列表

R merge back List after computation

我遇到了一个简单的问题,但找不到简单的解决方案。 (这个问题可能是duplicate但是我找不到!)

我需要的是在计算后merge将一个列表恢复到原来的列表。

我需要 merge 因为我正在做的计算太复杂了,无法直接 apply 到列表中。因此,我必须单独进行并以某种方式将其放回原始数据集。 (因为这个问题我这里不能直接用mutate)。

因为我无法重现我的数据,所以我将使用mtcars来演示我的问题。

我有一个原始列表,我正在对其进行计算(哪个并不重要),例如:

library(dplyr) 
library(purr) 

我的原始数据集是一个列表

dt = mtcars %>% 
  group_by(gear) %>% 
  split(.$gear)

然后,在这个列表上,我做了一个计算,例如:

dt %>% 
  map(~summarise(., cluster = mean(disp)))

最后我得到了 list

我的数据的(真实)结构最终看起来像这样

$`3`
   gear cluster
1     3   326.3

$`4`
    gear cluster
 1     4   123

等等。我需要的只是将这个列表 merge back 到原始列表。 我怎样才能做到这一点 ?

我需要的(想要的输出)是最终得到(这里很难重现)我的原始 listmerged 计算值.

类似于

$`3`

     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb cluster 
1   21.4     6 258.0   110  3.08 3.215 19.44     1     0     3     1  XXX
2   18.7     8 360.0   175  3.15 3.440 17.02     0     0     3     2  XXX
3   18.1     6 225.0   105  2.76 3.460 20.22     1     0     3     1  XXX
4   14.3     8 360.0   245  3.21 3.570 15.84     0     0     3     4  XXX

所有列表依此类推 (df)

我再次强调,我的原始数据集是一个列表,而不是 data.frame。我需要的是合并 lists,而不是 data.frame

我想到了

dt = mtcars %>% # my data is a list
  group_by(gear) %>% 
  split(.$gear)

fmerge = function(x) x %>% lapply(dt, ., by = 'gear')

dt %>% 
  map(~summarise(., cluster = mean(disp))) %>% 
  lapply(fmerge) 

dt %>% 
  map(~summarise(., cluster = mean(disp))) %>% 
  join_all(dt, ., by = 'gear')

但效果不佳。

有线索吗?

我们可以使用 bind_rows 来绑定 list 元素,然后执行 right_joinleft_join

mtcars %>% 
   group_by(gear) %>% 
   split(.$gear) %>% 
   map(~summarise(., cluster = mean(disp))) %>%
   bind_rows() %>%
   right_join(., mtcars, by = "gear")

然而,这可以在没有 split/map/bind_rows/right_join 的情况下完成,只需在我们 group_by 'gear'

之后用 mutate 创建 'cluster'
mtcars %>% 
     group_by(gear) %>%
     mutate(cluster = mean(disp))

但是,我们假设这个简化的过程可能不适用于 OP 的原始数据集。

更新

根据OP的评论,我们可以使用map2list

的相应元素做left_join
dt %>%
    map(~summarise(., cluster = mean(disp))) %>% 
    map2(dt, ., left_join, by = "gear")

或者如果我们需要单个 data.frame,则使用 map2df

dt %>%
    map(~summarise(., cluster = mean(disp))) %>% 
    map2_df(dt, ., left_join, by = "gear")

我会利用 tidyr 包(然后是 unnest())中的 nest() 来做一些有趣的事情,如下所示:

library(tidyr)
library(dplyr)
library(purrr)

mtcars %>% 
  nest(-gear) %>% 
  mutate(cluster = map_dbl(data, ~ mean(.$disp))) %>% 
  unnest(data)
#> # A tibble: 32 × 12
#>     gear  cluster   mpg   cyl  disp    hp  drat    wt  qsec    vs    am
#>    <dbl>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1      4 123.0167  21.0     6 160.0   110  3.90 2.620 16.46     0     1
#> 2      4 123.0167  21.0     6 160.0   110  3.90 2.875 17.02     0     1
#> 3      4 123.0167  22.8     4 108.0    93  3.85 2.320 18.61     1     1
#> 4      4 123.0167  24.4     4 146.7    62  3.69 3.190 20.00     1     0
#> 5      4 123.0167  22.8     4 140.8    95  3.92 3.150 22.90     1     0
#> 6      4 123.0167  19.2     6 167.6   123  3.92 3.440 18.30     1     0
#> 7      4 123.0167  17.8     6 167.6   123  3.92 3.440 18.90     1     0
#> 8      4 123.0167  32.4     4  78.7    66  4.08 2.200 19.47     1     1
#> 9      4 123.0167  30.4     4  75.7    52  4.93 1.615 18.52     1     1
#> 10     4 123.0167  33.9     4  71.1    65  4.22 1.835 19.90     1     1
#> # ... with 22 more rows, and 1 more variables: carb <dbl>

如果您 运行 此管道的前两行,然后是三行,您将看到有一列数据集与数据中的组相对应。这使您可以做一些非常复杂的事情,而无需将数据拆分成单独的列表。

例如,以下 运行 对每个齿轮的数据进行回归分析(同样,尝试 运行 前 2 条、然后 3 条等管道线以了解如何它正在工作),然后绘制结果:

library(broom)
library(ggplot2)

mtcars %>% 
  nest(-gear) %>% 
  mutate(fits = map(data, ~ lm(mpg ~ hp, .)),
         predicted = map(fits, augment)) %>% 
  unnest(predicted) %>% 
  ggplot(aes(mpg, .fitted)) +
    geom_point() +
    facet_grid(. ~ gear)

可能的解决方案,但由于 loop

而变慢

将计算存储在“列表”中

computation = dt %>% map(~summarise(., cluster = mean(disp)))

然后遍历 list

for(i in 1:length(dt)){
  dt[[i]] = merge(dt[[i]], computation[[i]], by = 'gear')
}

获得

$`3`
   gear  mpg cyl  disp  hp drat    wt  qsec vs am carb cluster
1     3 21.4   6 258.0 110 3.08 3.215 19.44  1  0    1   326.3
2     3 18.7   8 360.0 175 3.15 3.440 17.02  0  0    2   326.3
3     3 18.1   6 225.0 105 2.76 3.460 20.22  1  0    1   326.3

等等。