Выровнять длинный набор данных, вставив индикатор, если хотя бы одно не пропущенное значение - PullRequest
1 голос
/ 02 июля 2019

У меня есть относительно большой (~ 100 000 рядов) набор данных с несколькими строками для каждого человека.Лица идентифицируются по «id».Моя цель - преобразовать в фрейм данных или таблицу данных с одной строкой на человека.Для каждого столбца, т.е.wt: sat, каждая строка будет содержать индикатор, показывающий, был ли хотя бы один не пропущенный экземпляр каждой переменной для данного индивидуума.

Например, с учетом приведенных ниже данных:

 dat <- structure(list(id = c(386L, 386L, 2794L, 2794L, 2794L, 2794L, 
2732L, 2732L), wt = c(56.7, 56.7, NA, NA, NA, NA, 36.3, 36.3), 
    pain = c(NA, NA, 8L, 8L, NA, NA, NA, NA), sbp = c(120L, NA, 
    125L, 125L, NA, NA, 120L, 120L), dbp = c(60L, NA, 81L, 81L, 
    NA, NA, 67L, 67L), hr = c(84L, NA, 100L, 100L, NA, NA, 120L, 
    120L), rr = c(16L, NA, 18L, 18L, NA, NA, 24L, 24L), sat = c(93L, 
    NA, NA, NA, NA, NA, 99L, 99L)), row.names = c(NA, -8L), class = "data.frame")

Я хотел бы произвести:

enter image description here

Ответы [ 3 ]

2 голосов
/ 02 июля 2019

Я думаю, это то, что вы ищете:

A tidyverse решение:

dat %>%
  replace(is.na(.), 0) %>%
  group_by(id) %>%
  summarise_all(~as.numeric(any(. > 0)))

# A tibble: 3 x 8
     id    wt  pain   sbp   dbp    hr    rr   sat
  <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1   386     1     0     1     1     1     1     1
2  2732     1     0     1     1     1     1     1
3  2794     0     1     1     1     1     1     0

A data.table решение:

dat2 <- dat
setDT(dat2)
dat2[is.na(dat2)] <- 0
dat2[, lapply(.SD, function(x) as.numeric(any(x > 0))), id]

Илиболее краткое data.table решение от @markus (спасибо), и вы можете использовать !is.na(.) вместо . > 0 и для других решений (и вам не нужно заменять NA на 0):

cols <- names(dat)[-1];
setDT(dat)[, lapply(.SD, function(x) as.integer(any(!is.na(x)))), .SDcol = cols, by = id]

     id wt pain sbp dbp hr rr sat
1:  386  1    0   1   1  1  1   1
2: 2794  0    1   1   1  1  1   0
3: 2732  1    0   1   1  1  1   1
2 голосов
/ 02 июля 2019

Опция в base R

aggregate(.~ id, replace(dat, is.na(dat), 0), FUN =
      function(x) as.integer(any(x > 0)), na.action = NULL)
#    id wt pain sbp dbp hr rr sat
#1  386  1    0   1   1  1  1   1
#2 2732  1    0   1   1  1  1   1
#3 2794  0    1   1   1  1  1   0

Или с rowsum из base R

+(rowsum(+(dat[-1]  > 0 & !is.na(dat[-1])), dat$id) != 0)
#     wt pain sbp dbp hr rr sat
#386   1    0   1   1  1  1   1
#2732  1    0   1   1  1  1   1
#2794  0    1   1   1  1  1   0
0 голосов
/ 02 июля 2019

Попробуйте:

library(tidyr)
library(dplyr)
dat %>% 
  gather(key, value, -id) %>% 
  mutate(value2 = if_else(is.na(value), 1, 0)) %>% 
  group_by(id, key) %>% 
  summarise(value2 = max(value2)) %>% 
  spread(key, value2)

Короче говоря:

  • конвертировать в длинный формат
  • создать переменную индикатора
  • суммировать по id и key
  • преобразовать в широкоформатный формат
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...