根据另一个分组变量

时间:2016-09-15 15:42:40

标签: r dplyr aggregate tapply split-apply-combine

示例:我有一个按性别划分的高度数据集。 我想将高度分为低点和高点,其中切点被定义为每个性别中的平均值 - 2sd。

示例数据集:

set.seed(8)
df = data.frame(sex = c(rep("M",100), rep("F",100)), 
                ht = c(rnorm(100, mean=1.7, sd=.17), rnorm(100, mean=1.6, sd=.16)))

我想在单行矢量化代码中做一些事情,因为我很确定这是可能的,但是,我不知道如何编写它。我想可能有办法使用cut()apply()和/或dplyr来实现这一目标。

3 个答案:

答案 0 :(得分:1)

如何使用基础R中的cut

sapply(c("F", "M"), function(s){
    dfF <- df[df$sex==s,] # filter out per gender
    cut(dfF$ht, breaks = c(0, mean(dfF$ht)-2*sd(dfF$ht), Inf), labels = c("low", "high"))
})
# dfF$ht heights per gender
# mean(dfF$ht)-2*sd(dfF$ht) cut point

答案 1 :(得分:0)

刚刚使用base r发现了以下解决方案:

df$ht_grp <- ave(x = df$ht, df$sex, 
                 FUN = function(x) 
                       cut(x, breaks = c(0, (mean(x, na.rm=T) - 2*sd(x, na.rm=T)), Inf)))

这是有效的,因为我知道0和Inf是合理的界限,但我也可以使用min(x)max(x)作为我的上限和下限。这导致因子变量分为低,高和NA。

我之前的解决方案: 我提出了以下两个步骤,这个过程并不是那么糟糕:

df = merge(df, 
           setNames( aggregate(ht ~ sex, df, FUN = function(x) mean(x)-2*sd(x)), 
                     c("sex", "ht_cutoff")), 
           by = "sex")

df$ht_is_low = ifelse(df$ht <= df$ht_cutoff, 1, 0)

答案 2 :(得分:0)

在下面的代码中,我创建了2个新变量。两者都是通过对sex变量进行分组并过滤ht的不同范围来创建的。

 library(dplyr)
 df_low <- df %>% group_by(sex) %>% filter(ht<(mean(ht)-2*sd(ht)))
 df_high<- df %>% group_by(sex) %>% filter(ht>(mean(ht)+2*sd(ht)))