Объединение сложных строк data.frame по общему идентификатору - PullRequest
2 голосов
/ 04 августа 2020
example <- structure(list(id = c(1, 1, 2, 2, 3, 3, 4), var1 = c(5, NA, 8, 
9, 10, NA, 3), var2 = c(23, NA, 8, 9, NA, NA, 6), var3 = c(NA, 
NA, NA, NA, NA, NA, NA), var4 = c(5, 5, 6, 6, 7, 7, 8)), row.names = c(NA, 
-7L), class = "data.frame")

У меня есть большой и сложный фрейм данных, в котором одна и та же мера может присутствовать более одного раза, а разные записи для одной и той же меры могут содержать разные данные. Я создал упрощенный пример выше. Что я хотел бы сделать, так это объединить это как можно больше. Я думаю, что мне проще всего объяснить это, если я проконсультируюсь с примером:

print(example)

  id var1 var2 var3 var4
1  1    5   23   NA    5
2  1   NA   NA   NA    5
3  2    8    8   NA    6
4  2    9    9   NA    6
5  3   10   NA   NA    7
6  3   NA   NA   NA    7
7  4    3    6   NA    8
  • Если переменная присутствует в одной из строк с идентификатором, но является NA в другой, то не- Значение NA всегда берется
  • Если значение переменной одинаково для всех экземпляров идентификатора, используйте это значение
  • Если две строки имеют одинаковый идентификатор, но разные значения для одного переменная, тогда они остаются в виде двух разных строк
  • Если переменная NA во всех строках с некоторым идентификатором, тогда этот идентификатор будет иметь NA для этой переменной в окончательном фрейме данных

Таким образом, желаемый результат выглядит так:

  id var1 var2 var3 var4
1  1    5   23   NA    5
2  2    8    8   NA    6
3  2    9    9   NA    6
4  3   10   NA   NA    7
5  4    3    6   NA    8

По StackOverflow есть похожие вопросы, но ни один из них не касается всех этих функций одновременно. Ближайшее, что у меня есть, это:

example %>% 
   group_by(id) %>% 
   summarise_all(funs(list(na.omit(.))))

     id var1      var2      var3      var4     
  <dbl> <list>    <list>    <list>    <list>   
1     1 <dbl [1]> <dbl [1]> <lgl [0]> <dbl [2]>
2     2 <dbl [2]> <dbl [2]> <lgl [0]> <dbl [2]>
3     3 <dbl [1]> <dbl [0]> <lgl [0]> <dbl [2]>
4     4 <dbl [1]> <dbl [1]> <lgl [0]> <dbl [1]>

Что, по сути, делает то, что я хочу, но помещает все в списки, что мешает любой последующей работе с фреймом данных. Вместо получения двух строк для ID 2 я получаю одну строку, которая, например, содержит список с 8 и 9 для var1. Это также происходит с совпадающими переменными: для ID1, var4 вы получаете список, содержащий 5, 5.

1 Ответ

2 голосов
/ 04 августа 2020

Вы можете это сделать across. Для каждого столбца и id вы можете сохранить только unique значения, отличные от NA,

library(dplyr)

example %>% 
  group_by(id) %>% 
  summarise(across(.fns = ~{x <- unique(na.omit(.));x[1:max(1, length(x))]}))
  #With summarise_all you can do
  #summarise_all(~{x <- unique(na.omit(.));x[1:max(1, length(x))]})


#    id  var1  var2 var3   var4
#  <dbl> <dbl> <dbl> <lgl> <dbl>
#1     1     5    23 NA        5
#2     2     8     8 NA        6
#3     2     9     9 NA        6
#4     3    10    NA NA        7
#5     4     3     6 NA        8
...