【问题标题】:Apply between function over a matrix by using lower bound and upper bound vectors通过使用下界和上界向量在矩阵上应用函数
【发布时间】:2018-12-07 16:57:41
【问题描述】:

我有一个由数值组成的数据框。我计算了每列的标准差和平均值,并创建了Upper_BoundLower_Bound 向量,如下所示:

std_devs = apply(exp_vars[,sapply(exp_vars,is.numeric)], 2, sd)
means = apply(exp_vars[,sapply(exp_vars,is.numeric)], 2, mean)
Upper_Bound = means + 3*std_devs
Lower_Bound = means - 3*std_devs

现在我想检测至少有一个值不在相关上限和下限之间的行。例如,列 j 中的值必须等于或大于 Lower_Bound[j] 且等于或小于 Upper_Bound[j],如果行 i 中至少有一个值违反此条件,我想保存该行的索引(I也有行名,保存行名也可以。)我想要获得的是一个索引向量(或行名),它显示了所有违反规则的行。我尝试了以下方法:

outliers = apply(my_data ,1, between(x,Lower_Bound, Upper_Bound,incbounds = TRUE))

但我想期望在连续自动遍历每个值并将它们与相关边界进行比较时,这太过分了。这是我第二次失败的绝望尝试:

outliers = apply(exp_vars_numeric,1, apply(x,2,between(x,Lower_Bound, Upper_Bound, incbounds = TRUE)))

我知道我可以使用 for 循环来做到这一点,但我希望有一个更有效的解决方案。任何建议都非常感谢。

提前致谢。

【问题讨论】:

    标签: r apply


    【解决方案1】:

    考虑通过在ave() 的帮助下添加下限和上限列来将所有内容保存在一个数据框中,以实现sdmean 的内联聚合。然后运行条件ifelse() 来标记这些行。

    num_cols <- sapply(exp_vars,is.numeric)
    num_names <- colnames(exp_vars)[num_cols]
    
    means <- sapply(exp_vars[,num_cols], function(x) ave(x, FUN=mean))
    std_devs <- sapply(exp_vars[,num_cols], function(x) ave(x, FUN=sd))
    
    exp_vars[,paste0(num_names, "_lower")] <- means - 3*std_devs
    exp_vars[,paste0(num_names, "_upper")] <- means + 3*std_devs
    
    # CONDITIONALLY ASSIGN FLAG COLS
    exp_vars[,paste0(num_names, "_flag")] <- ifelse(exp_vars[,num_names] >= exp_vars[,paste0(num_names, "_lower")] &
                                                    exp_vars[,num_names] <= exp_vars[,paste0(num_names, "_upper")], 1, 0)    
    # ADD ALL FLAG COLS HORIZONTALLY
    exp_vars$index <- ifelse(rowSums(exp_vars[,paste0(num_names, "_flag")]) > 0, row.names(exp_vars), NA)
    
    exp_vars[is.na(exp_vars$index), ]
    

    【讨论】:

    • 您好,感谢您的回复。除了一个小细节外,这很好用。我想找到至少有一个 0 标志的列,但是这段代码会找到至少有一个 1 标志的列。因此我像这样更改了最后两行:num_cols_num = sum(num_cols) exp_vars$index &lt;- ifelse(rowSums(exp_vars[,paste0(num_names, "_flag")]) &lt; num_cols_num, row.names(exp_vars), NA) outliers_index = na.omit(exp_vars$index)
    • 听起来不错!很高兴您能够根据最终需求调整解决方案。
    【解决方案2】:

    建议包含一个小例子来说明您的数据是什么样的,以便我们更容易回答您的问题:) 我根据您的描述生成了 data.frames,看来以下内容可以解决您的问题:

    df <- data.frame(a=c(1:10),b=c(5:14))
    ncols <- ncol(df)
    bounds <- data.frame(lower=seq(.5,5,.5),upper=seq(6.5,11,.5))
    one_plus_fall_outside <-   sapply(1:nrow(df),
             function(i) 
               sum(between(df[i,],bounds$lower[i],bounds$upper[i]))/ncols<1
             )  
    which(one_plus_fall_outside)
    

    您可以通过同时查看所有列来检查这是否有效:

    cbind(df,bounds,one_plus_fall_outside)
    

    【讨论】:

    • 感谢您的回复,此代码运行良好,但它不完全是我问题的答案。它为每一行分配不同的上限和下限,而它应该为每一列分配一个不同的上限和下限。例如,''column a'' 应该有一个 lower_bound 和一个 upper_bound,并且 ''column a'' 中的每个值都应该与这些界限进行比较。你不需要修改代码,我使用了@parfait 的建议,效果很好。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2021-06-08
    • 1970-01-01
    • 2015-04-23
    • 2018-05-31
    相关资源
    最近更新 更多