Dplyr присоединиться: нет совпадения с любым - PullRequest
0 голосов
/ 23 мая 2018

Редактирует Я немного редактирую этот пост, чтобы обеспечить немного больше контекста на случай, если весь подход был неправильным с самого начала.См. «Контекст» ниже, чтобы попытаться объяснить проблему более абстрактно.

Я видел поток, где обсуждается сопоставление NA в таблицах, и варианты - сопоставить их с другими NA или не сопоставитьих ни к чему: dplyr left_join, соответствующий NA

Однако я действительно ищу противоположное поведение.Есть ли способ, чтобы NA (или какое-либо пропущенное значение для этого случая) соответствовало любому другому значению во время операции соединения?Пример ниже:

library(tidyverse)
# Removed output for brevity

tbl1 <- tibble(subj = 1, run = 1, session=1)

tbl2 <- tibble(subj = c(1, NA, 2), run = c(NA, 1, 2), session=c(NA, NA, 1), outcomedata = c(NA, NA, NA) )

tbl2$outcomedata[2][[1]] <- list(temperature=30)
tbl2$outcomedata[1][[1]] <- list(height=155, weight=80)
tbl2$outcomedata[3][[1]] <- list(temperature=20)

tbl1
#> # A tibble: 1 x 3
#>    subj   run session
#>   <dbl> <dbl>   <dbl>
#> 1  1.00  1.00    1.00
tbl2
#> # A tibble: 3 x 4
#>    subj   run session outcomedata
#>   <dbl> <dbl>   <dbl> <list>     
#> 1  1.00 NA      NA    <list [2]> 
#> 2 NA     1.00   NA    <list [1]> 
#> 3  2.00  2.00    1.00 <list [1]>

left_join(tbl1, tbl2)
#> Joining, by = c("subj", "run", "session")
#> # A tibble: 1 x 4
#>    subj   run session outcomedata
#>   <dbl> <dbl>   <dbl> <list>     
#> 1  1.00  1.00    1.00 <NULL>

Мой желаемый конечный результат заключается в том, что я могу сопоставить первую и вторую строки таблицы tbl2 с одной строкой таблицы tbl1, поскольку эти строки соответствуют всем атрибутам, отличным от NA.Третья строка не должна совпадать ни с чем, так как она отличается от значений, отличных от NA.Таким образом, я пытаюсь получить конечный результат следующим образом:

#> # A tibble: 2 x 4
#>    subj  run   session  outcomedata
#>   <dbl> <dbl>   <dbl>     <list>     
#> 1  1.00  1.00    1.00     <list [2]> 
#> 2  1.00  1.00    1.00     <list [1]> 

Контекст

Позвольте мне предоставить контекст на случай, если я ухожу отсюда и лаю неправильное дерево с объединениями, и есть более легкая альтернатива.У меня есть несколько вложенных файлов json (которые я создаю в R в виде списков), которые содержат различную информацию, которую я хочу отнести к конкретным экземплярам данных.Один json может содержать информацию, которая относится ко всем экземплярам данных для субъекта 1 (т. Е. Первая строка таблицы tbl2), а другая относится ко всем экземплярам данных для прогона 1 (т. Е. Вторая строка таблицы tbl2).

Я хотел бы иметь возможность объединить всю релевантную информацию для каждого созвездия параметров в данных (один из которых находится в Таблице 1, но планируется их все) в отдельных списках.Мой план состоял в том, чтобы попытаться получить все, чтобы соответствовать всем связанным, а затем использовать операцию group_by над всеми параметрами (то есть group_by (subj, run, session)) и объединить списки (мой план состоял в том, чтобы использовать rlist :: list.merge).

Любая помощь будет высоко оценена!

1 Ответ

0 голосов
/ 12 июня 2018

Вот решение tidyverse:

tbl2 %>%
  split(seq(nrow(.))) %>%               # split into one row data frames
  map_dfr(~modify_if(.,is.na,~NULL) %>% # remove na columns
        inner_join(tbl1,.))             # inner join to table1

# # A tibble: 2 x 4
#    subj   run session outcomedata
#       <dbl> <dbl>   <dbl> <list>     
# 1     1     1       1 <list [2]> 
# 2     1     1       1 <list [1]>

Я использую inner_join(tbl1,.) вместо inner_join(tbl1), чтобы сохранить порядок столбцов.

И базовый R перевод:

df_list <- split(tbl2,seq(nrow(tbl2)))
df_list <- lapply(df_list,function(dfi){
  merge(tbl1, dfi[!sapply(dfi,is.na)])
})
do.call(rbind,df_list)
#   subj run session outcomedata
# 1    1   1       1     155, 80
# 2    1   1       1          30

Бонус

2 100% -ный подход к точке с использованием group_by вместо split.один с do, один с nest и map.do является устаревшим FYI, но здесь он предлагает более компактный и читаемый синтаксис:

tbl2 %>%
  group_by(n=seq(n())) %>%
  do(modify_if(.,is.na,~NULL) %>% # remove na columns
            inner_join(tbl1,.)) %>%
  ungroup %>%
  select(-n)

tbl2 %>%
  rowid_to_column("n") %>%
  group_by(n) %>%
  nest(.key="dfi") %>%
  mutate_at("dfi",~map(.,
                       ~ modify_if(.,is.na,~NULL) %>% # remove na columns
                         inner_join(tbl1,.))) %>%
  unnest %>%
  select(-n)
...