Итерировать по фрейму данных по элементам списка - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь объединить два фрейма данных на основе подмножества общих идентификаторов. Позвольте мне продемонстрировать:

library(tidyverse)
set.seed(42)

df = list(id = c(1,2,3,4,1,2,2,2,1,1),
       group = c("A","A","A","A","B","B","B","B","C","C"),
       val = c(round(rnorm(10,6,6),0))
       ) %>% 
        tbl_df()

df_na = list(id = c(1,1,1,2,3,3,4,5,5,5),
       group = c(rep(NA,10)),
       val = c(rep(NA,10))
       ) %>% 
        tbl_df()

df содержит данные и id с, в то время как df_na содержит только id с и NA с. Я хотел бы создать объединенный фрейм данных, который содержит всю информацию df и добавить NA с group и id, то есть для каждого group в df найти, какие id с присутствуют как в df, так и в df_na и слиянии.

Если бы я делал это вручную, то есть группу для группы, я бы использовал что-то вроде этого:

A_dist = df %>% filter(group=="A") %>%
  distinct(id) %>%
  pull() 

df_A_comb = df_na %>% 
  filter(id %in% A_dist) %>%
  bind_rows(filter(df, group=="A"))

# A tibble: 11 x 3
      id group   val
   <dbl> <chr> <dbl>
 1     1 NA       NA
 2     1 NA       NA
 3     1 NA       NA
 4     2 NA       NA
 5     3 NA       NA
 6     3 NA       NA
 7     4 NA       NA
 8     1 A        14
 9     2 A         3
10     3 A         8
11     4 A        10

Но обвиоулси Я бы предпочел автоматизировать это. Как новый фанат tidyverse, я пытаюсь понять, что такое purrr::map. Я могу создать вектор из id с для каждого group.

df_dist = df %>% 
        split(.$group) %>% 
        map(distinct, id) %>% 
        map("id")

> df_dist
$A
[1] 1 2 3 4

$B
[1] 1 2

$C
[1] 1

Но перевод моего dplyr подхода более сложен и выдает сообщение об ошибке ранее.

###this approach doesn't work...
df_comb = df_na %>% 
        map(filter, id %in% df_dist)# %>% 
        ...

Error in UseMethod("filter_") : no applicable method for 'filter_' applied to an object of class "c('double', 'numeric')"

Любая помощь будет сильно оценена!

1 Ответ

0 голосов
/ 24 января 2020

Тидиверс великолепен, но иногда вы можете не заметить мощь простого индексирования и действительно полезные базовые инструменты R семейства apply. Эта единственная функция lapply даст вам список, содержащий все нужные вам кадры данных в указанном формате:

lapply(unique(df$group), function(x){
  rbind(df_na[df_na$id %in% df$id[df$group == x],], df[df$group == x,])})

Результат:

#> [[1]]
#> # A tibble: 11 x 3
#>       id group   val
#>    <dbl> <chr> <dbl>
#>  1     1 <NA>     NA
#>  2     1 <NA>     NA
#>  3     1 <NA>     NA
#>  4     2 <NA>     NA
#>  5     3 <NA>     NA
#>  6     3 <NA>     NA
#>  7     4 <NA>     NA
#>  8     1 A        14
#>  9     2 A         3
#> 10     3 A         8
#> 11     4 A        10
#> 
#> [[2]]
#> # A tibble: 8 x 3
#>      id group   val
#>   <dbl> <chr> <dbl>
#> 1     1 <NA>     NA
#> 2     1 <NA>     NA
#> 3     1 <NA>     NA
#> 4     2 <NA>     NA
#> 5     1 B         8
#> 6     2 B         5
#> 7     2 B        15
#> 8     2 B         5
#> 
#> [[3]]
#> # A tibble: 5 x 3
#>      id group   val
#>   <dbl> <chr> <dbl>
#> 1     1 <NA>     NA
#> 2     1 <NA>     NA
#> 3     1 <NA>     NA
#> 4     1 C        18
#> 5     1 C         6

Если вы хотите присоединить их к сохраните результат (скажем, как x) и сделайте следующее:

do.call(rbind, x)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...