展平长数据集,如果至少有一个非缺失值,则插入一个指标

时间:2019-07-02 18:17:02

标签: r dplyr data.table tidyr

我有一个相对较大的数据集(约100,000行),每个人都有多个行。个体由“ id”标识。我的目标是将数据转换为数据框或data.table,每个人只有一行。 对于每一列,即。 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 个答案:

答案 0 :(得分:2)

我认为这就是您想要的:

一种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

一种data.table解决方案:

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

或者,使用@markus提供的更为简洁的data.table解决方案(谢谢),您也可以使用!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

答案 1 :(得分:2)

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

答案 2 :(得分:0)

尝试:

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)

简而言之:

  • 转换为长格式
  • 创建指标变量
  • 总结idkey
  • 转换为宽格式