Связывание строк в группе в R - PullRequest
0 голосов
/ 08 июня 2018

У меня есть данные, в которых некоторые столбцы определяют группы, а некоторые столбцы (a1-a4 в данных примера ниже) имеют значение только в одном столбце, а NA - в остальных.

structure(list(gp = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "gp1", class = "factor"), id = c(1, 1, 2, 2, 2, 2, 3, 3, 3), name = structure(c(1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), a1 = c(0.4, NA, NA, NA, NA, NA, 0.3, NA, NA), a2 = c(NA, NA, NA, 1, NA, NA, NA, NA, NA), a3 = c(NA, 1.2, NA, NA, NA, NA, NA, NA, NA), a4 = c(NA, NA, 1, NA, NA, NA, NA, NA, 1)), .Names = c("gp", "id", "name", "a1", "a2", "a3", "a4"), row.names = c(NA, -9L), class = "data.frame")

Как язнаю, что только один из столбца a1 действительно имеет значение, и мне не нужны отдельные строки, я хотел бы собрать все значения в группе в одну строку.Я ожидаю что-то вроде ниже.

structure(list(gp = structure(c(1L, 1L, 1L), .Label = "gp1", class = "factor"), id = c(1, 2, 3), name = structure(1:3, .Label = c("A", "B", "C"), class = "factor"), a1 = c(0.4, NA, 0.3), a2 = c(NA, 1, NA), a3 = c(1.2, NA, NA), a4 = c(NA, 1, 1)), .Names = c("gp", "id", "name", "a1", "a2", "a3", "a4"), row.names = c(NA, -3L), class = "data.frame")

Как мне этого добиться?Было бы здорово, если бы в решении использовался тидиверс.

Ответы [ 3 ]

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

Поскольку OP уже упоминал, что может быть только одна строка со значением, следовательно, одна опция может использовать dplyr::first после применения group_by.Я предпочел использовать summarise_at, чтобы получить гибкость, чтобы исключить несколько столбцов, по которым анализ не требуется.

library(dplyr)

df %>% group_by(gp, id, name) %>%
  summarise_at(vars(starts_with("a")), funs(dplyr::first(sort(.)))) %>%
  as.data.frame()

#    gp id name  a1 a2  a3 a4
# 1 gp1  1    A 0.4 NA 1.2 NA
# 2 gp1  2    B  NA  1  NA  1
# 3 gp1  3    C 0.3 NA  NA  1
0 голосов
/ 09 июня 2018
dat%>%
  group_by(gp,id,name)%>%
  summarise_all(funs(lift(coalesce)(.)))

# A tibble: 3 x 7
# Groups:   gp, id [?]
  gp       id name      a1    a2    a3    a4
  <fct> <dbl> <fct>  <dbl> <dbl> <dbl> <dbl>
1 gp1      1. A      0.400   NA   1.20   NA 
2 gp1      2. B     NA        1. NA       1.
3 gp1      3. C      0.300   NA  NA       1.
0 голосов
/ 08 июня 2018

Вы можете попробовать это

library(tidyverse)
df1 %>% 
 group_by(gp, id, name) %>% 
 summarise_all(sum, na.rm = TRUE) %>% 
 summarise_all(na_if, 0)
# A tibble: 3 x 7
# Groups:   gp [?]
#  gp       id name      a1    a2    a3    a4
#  <fct> <dbl> <fct>  <dbl> <dbl> <dbl> <dbl>
#1 gp1      1. A      0.400   NA   1.20   NA 
#2 gp1      2. B     NA        1. NA       1.
#3 gp1      3. C      0.300   NA  NA       1.

Не будет никаких NA с, но 0 с в конечном выводе, отсюда второй вызов summarise_all.Я предполагаю, что в столбцах a1 до a4 нет 0 s.


Вот решение для случая, когда в вашем начальном наборе данных есть 0 s.

sum_NA <- function(x) {
  if(all(is.na(x))) {
    NA
  } else {
    sum(x, na.rm = TRUE)
  }
}

df2 %>% 
 group_by(gp, id, name) %>% 
 summarise_all(sum_NA)
# A tibble: 3 x 7
# Groups:   gp, id [?]
#  gp       id name      a1    a2    a3    a4
#  <fct> <dbl> <fct>  <dbl> <dbl> <dbl> <dbl>
#1 gp1      1. A      0.      NA   1.20   NA 
#2 gp1      2. B     NA        0. NA       1.
#3 gp1      3. C      0.300   NA  NA       1.

данные

df1 <- structure(list(gp = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "gp1", class = "factor"), id = c(1, 1, 2, 2, 2, 2, 3, 3, 3), name = structure(c(1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), a1 = c(0.4, NA, NA, NA, NA, NA, 0.3, NA, NA), a2 = c(NA, NA, NA, 1, NA, NA, NA, NA, NA), a3 = c(NA, 1.2, NA, NA, NA, NA, NA, NA, NA), a4 = c(NA, NA, 1, NA, NA, NA, NA, NA, 1)), .Names = c("gp", "id", "name", "a1", "a2", "a3", "a4"), row.names = c(NA, -9L), class = "data.frame")

df2 <- structure(list(gp = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "gp1", class = "factor"), id = c(1, 1, 2, 2, 2, 2, 3, 3, 3), name = structure(c(1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), a1 = c(0.0, NA, NA, NA, NA, NA, 0.3, NA, NA), a2 = c(NA, NA, NA, 0, NA, NA, NA, NA, NA), a3 = c(NA, 1.2, NA, NA, NA, NA, NA, NA, NA), a4 = c(NA, NA, 1, NA, NA, NA, NA, NA, 1)), .Names = c("gp", "id", "name", "a1", "a2", "a3", "a4"), row.names = c(NA, -9L), class = "data.frame")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...