每列采样一行,数据基本缺失

时间:2016-01-10 22:47:29

标签: r if-statement dataframe data.table missing-data

作为我的数据框的一个例子,我将其称为df1,我有GROUP1有三行数据,GROUP2有两行数据。我有三个变量,X1,X2和X3:

GROUP          X1    X2   X3
GROUP1         A     NA   NA
GROUP1         NA    NA   T
GROUP1         C     T    G   
GROUP2         NA    NA   C
GROUP2         G     NA   T

根据之前的问题和答案(Sample a single row, per column, within a subset of a data frame in R, while following conditions),我的答案已经过了一半,除非我在使用字符方面遇到问题。

我想从GROUP1每列采样一个变量,以创建一个代表GROUP1的新行。我不想从GROUP1中采样一个完整的行,而是需要为每个列单独进行采样。我想为GROUP2做同样的事情。此外,采样不应考虑/包括NA,除非该组变量的所有行都具有NA(例如GROUP2,变量X2,以上)。

例如,在抽样后,我可以得到结果:

GROUP         X1    X2   X3
GROUP1        A     T    T
GROUP2        G     NA   C

只有GROUP2,变量X2,才能在这里产生NA。我实际上有300个分类群,40个组,160000个变量,以及大量的NA。

当我使用时:

library(data.table)

setDT(df1)[,lapply(.SD, function(x)
if(all(is.na(x))) NA_character_ else sample(na.omit(x),1)) , by = GROUP]

我最后发出警告:

Column 2 of result for group 2 is type 'character' but expecting type    
'integer'. Column types must be consistent for each group.

但是,此警告似乎不仅适用于完全由NA组成的组的变量。

如果我用NA_integer_替换NA_character_,则某些列会导致组变量的非NA行的总和,而不是来自行的样本。

2 个答案:

答案 0 :(得分:2)

您可以使用此data.table来电:

setDT(df1)[ , lapply(.SD, 
  function(x) x[!is.na(x)][sample(sum(!is.na(x)), 1)]), by = GROUP]

或者你可以调整原来的

setDT(df1)[,lapply(.SD, function(x)
  if(all(is.na(x))) NA_character_ 
    else as.character(na.omit(x))[sample(length(na.omit(x)), 1)]) , by = GROUP]

或使用基础R的aggregate

aggregate(df1[ , names(df1) != "GROUP"], by=list(df1$GROUP), 
  function(ii) ifelse(length(na.omit(ii)) == 0, 
    NA,
    as.character(na.omit(ii))[sample(length(na.omit(ii)), 1)])) 
    # Note use of as.character in case of factors
#  Group.1 X1   X2 X3
#1  GROUP1  A    T  T
#2  GROUP2  G <NA>  C

正如thelatemail所提到的,您遇到的问题很可能是由于变量为factor s,因为您的代码在X1-X3是字符时有效。上述任何解决方案都应与factors一起使用。

答案 1 :(得分:1)

使用dplyr,您可以执行以下操作:

library(dplyr)

sampleValue <- function(x) {
  ifelse(sum(is.na(x)) == length(x), x[NA], sample(x[!is.na(x)], 1))
}

df <- data.frame(GROUP = c('GROUP1', 'GROUP1', 'GROUP1', 'GROUP2', 'GROUP2'),
                 X1 = c('A', NA, 'C', NA, 'G'),
                 X2  = c(NA, NA, 'T', NA, NA),
                 X3 = c(NA, 'T', 'G', 'C', 'T'),
                 stringsAsFactors = FALSE)
df %>% group_by(GROUP) %>% summarise_each(funs(sampleValue), -GROUP)

如果并非所有值都是NA,则该函数从所提供的值的向量中选择采样值,如果它们都是NA,则返回NA。您可以使用最后的代码行为每个组和每个列调用此函数。

输出如下(注意不同运行的输出变化,因为涉及随机抽样):

Source: local data frame [2 x 4]

   GROUP    X1    X2    X3
   (chr) (chr) (chr) (chr)
1 GROUP1     A     T     T
2 GROUP2     G    NA     C