每列采样一行,大量缺失数据
Sample a single row, per column, with substantial 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
根据之前的问题和答案 (),我的答案已经完成一半,但我在使用字符时遇到问题。
我想从 GROUP1 的每列中抽样一个变量,以创建一个代表 GROUP1 的新行。我不想从 GROUP1 中抽取一个完整的行,而是需要对每一列单独进行抽样。我想为 GROUP2 做同样的事情。此外,采样不应 consider/include 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_character_ 替换为 NA_integer_,一些列会生成组变量的非 NA 行的总和,而不是跨行的样本。
使用 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,则 returns 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
您可以使用此 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
.
作为我的数据框的示例,我将其称为 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
根据之前的问题和答案 (
我想从 GROUP1 的每列中抽样一个变量,以创建一个代表 GROUP1 的新行。我不想从 GROUP1 中抽取一个完整的行,而是需要对每一列单独进行抽样。我想为 GROUP2 做同样的事情。此外,采样不应 consider/include 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_character_ 替换为 NA_integer_,一些列会生成组变量的非 NA 行的总和,而不是跨行的样本。
使用 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,则 returns 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
您可以使用此 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
.