rowMean 如果行通过测试

标签 r subset

我正在处理一个数据集,其中源名称由变量前面的 2 个字母缩写指定。所以来自源 AA 的所有变量都以 AA_var1 开头,源 bb 有 bb_variable_name_2 。实际上有很多来源和很多变量名称,但我只留下 2 个作为最小示例。

我想为源数量(即该行上的数据不是 NA 的唯一前缀的数量)大于 1 的任何行创建一个均值变量。如果只有一个源,我想要那个总变量为 NA。

因此,例如,我的数据如下所示:

> head(df)
  AA_var1 AA_var2   myid   bb_meow bb_A_v1
1      NA      NA 123456        10      12
2      NA      10 194200        12      NA
3      12      10 132200        NA      NA
4      12      NA 132201        NA      12
5      NA      NA 132202        NA      NA
6      12      13 132203        14      NA

我想要以下内容:
> head(df)
  AA_var1 AA_var2   myid   bb_meow bb_A_v1  rowMeanIfDiverseData
1      NA      NA 123456        10      12                    NA #has only bb
2      NA      10 194200        12      NA                    11 #has AA and bb
3      12      10 132200        NA      NA                    NA #has only AA
4      12      NA 132201        NA      12                    12 #has AA and bb
5      NA      NA 132202        NA      NA                    NA #has neither
6      12      13 132203        14      NA                    13 #has AA and bb

通常,我只是将 rowMeans() 用于这种事情。但是仅选择变量名称遵循约定/在行级别/的行的附加子集让我在项目级别和我习惯的一般应用级别语句之间感到困惑。

我可以在数据帧级别获得前缀:
mynames <- names(df[!names(df) %in% c("myid")])
tmp <- str_extract(mynames, perl("[A-Za-z]{2}(?=_)"))
uniq <- unique(tmp[!is.na(tmp)])

所以,
> uniq
[1] "AA" "bb"

所以,我可以把它变成一个可以应用于 df 的函数,如下所示:
multiSource <- function(x){
    nm = names(x[!names(x) %in% badnames])           # exclude c("myid")
    tmp <- str_extract(nm, perl("[A-Za-z]{2}(?=_)")) # get prefixes
    uniq <- unique(tmp[!is.na(tmp)])                 # ensure unique and not NA
    if (length(uniq) > 1){
        return(T)
    } else {
        return(F)
    }
 }

但这显然令人困惑,并且仍然处于数据集级别,即:
> lapply(df,multiSource)
$AA_var1
[1] FALSE

$AA_var2
[1] FALSE

$bb_meow
[1] FALSE

$bb_A_v1
[1] FALSE

和...
> apply(df,MARGIN=1,FUN=multiSource)

为所有人提供 TRUE。

否则我想说...
df$rowMean <- rowMeans(df, na.rm=T)

# so, in this case
rowMeansIfTest <- function(X,test) {
   # is this row muliSource True?
   # if yes, return(rowMeans(X))
   # else return(NA)
}

df$rowMeanIfDiverseData <- rowMeansIfTest(df, test=multiSource)

但是我不清楚如何在没有某种 for 循环的情况下做到这一点。

最佳答案

这里的策略是将数据框按列拆分为变量组,并为每一行标识是否存在非 NA 值。然后我们检查 rowsums 以确保至少有两个变量具有非 NA 值的行,如果是,则使用 cbind 添加这些值的平均值。

这将推广到任意数量的列,只要它们以 AA_varXXX 格式命名,并且只要不是该格式的唯一列是 myid 。如果情况并非如此,则很容易修复,但这些是对现在编写的代码的限制。

df.dat <- df[!names(df) == "myid"]
diverse.rows <- rowSums(
  sapply(
    split.default(df.dat, gsub("^([A-Z]{2})_var.*", "\\1", names(df.dat))), 
    function(x) apply(x, 1, function(y) any(!is.na(y)))
) ) > 1
cbind(df, div.mean=ifelse(diverse.rows, rowMeans(df.dat, na.rm=T), NA))

产生:
  AA_var1 AA_var2   myid BB_var3 BB_var4 div.mean
1      NA      NA 123456      10      12       NA
2      NA      10 194200      12      NA       11
3      12      10 132200      NA      NA       NA
4      12      NA 132201      NA      12       12
5      NA      NA 132202      NA      NA       NA
6      12      13 132203      14      NA       13

关于rowMean 如果行通过测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22180935/

相关文章:

python - 根据 Python 中另外两个数组的值创建数组的子集

python - 如何将应用函数链接到 pandas 数据框的子集

javascript - 生成集合的所有可能的分组/子集组合,用完每个项目

r - 如何使用带有 knitr 的 ggplot2 删除 _printed_ 输出警告

R xts 和 data.table

r - 将变量转换为 ggplot 的因子时遇到问题

r - 基于当前行值和前面的行平均数据帧

arrays - 使用索引向量对数组进行子集化

python - pandas:快速计算具有某些值的列的总和

r - 如何编写一个函数来创建用于 ggplot2 的自定义误差线?