按组

时间:2015-09-29 15:10:00

标签: r statistics dplyr

如果这是重复,我道歉,我真的不知道我正在努力实现的正确术语。

我有一个药物实验室结果的数据框如下:

╔══════╦════════╗
║ drug ║ result ║
╠══════╬════════╣
║ A    ║     10 ║
║ B    ║    150 ║
║ B    ║     50 ║
║ A    ║     14 ║
║ C    ║      3 ║
║ C    ║      7 ║
╚══════╩════════╝

对于每种药物,我使用dplyr使用以下方法删除异常值(平均值> 4 SD):

cleaned <- data %>% group_by(drug) %>% filter(abs(result-mean(result))/sd(result) < 4)

但是现在我想知道我每种药物移除了多少异常值,所以基本上我想生成一个如下所示的数据帧:

╔══════╦═══════════╦══════════╦════════════╗
║ drug ║ total (N) ║ outliers ║ % outliers ║
╠══════╬═══════════╬══════════╬════════════╣
║ A    ║       100 ║        7 ║ 0.07       ║
║ B    ║       200 ║       45 ║ 0.225      ║
║ C    ║       300 ║       99 ║ 0.33       ║
╚══════╩═══════════╩══════════╩════════════╝

这样做的最佳方式是什么?

2 个答案:

答案 0 :(得分:4)

由于没有样本数据,我决定使用mtcars数据集进行演示。如果我按照你的方法,以下将是一种方式。在这里,您想要找出您过滤掉的数据部分;您使用setdiff()来收集数据。由于am是此演示中的组变量,因此请使用count()并查找每个组存在多少异常值(即am为0或1)。您进一步尝试使用select和unlist获取所需的向量。然后,您使用summarise()并计算am存在的数据点数,并使用mutate()添加新列。

library(dplyr)
library(tidyr)

mtcars %>%
group_by(am) %>%
filter(abs(disp-mean(disp))/sd(disp) < 1) %>%
setdiff(mtcars, .) %>%
count(am) %>%
select(2) %>%
unlist-> out

#out
#n1 n2 
#8  2 

summarize(group_by(mtcars, am), total = n()) %>%
mutate(outliers = out, percent = outliers / total)

#     am total outliers   percent
#  (dbl) (int)    (int)     (dbl)
#1     0    19        8 0.4210526
#2     1    13        2 0.1538462

采取devmacrile的建议,我做了以下事情。首先,使用组变量对数据进行分组。然后,您要设置标志列。在这里,我使用mutate()创建了列。列中有TRUE和FALSE。您可以计算amcheckcount()存在的数据点数。然后,您使用spread()包中的tidyr重新整理结果。现在计算am中0组和1组的总数据点。您再次使用am对数据进行分组,最后在transmute()中处理百分比计算和列重命名。我希望这个样本能帮到你。

mtcars %>%
group_by(am) %>%
mutate(check = abs(disp-mean(disp))/sd(disp) < 1)  %>%
count(am, check) %>%
spread(check, n) %>%
mutate(total = `FALSE` + `TRUE`) %>%
group_by(am) %>%
transmute(total, outliers = `FALSE`, percentage = `FALSE` / total)

#     am total outliers percentage
#  (dbl) (int)    (int)      (dbl)
#1     0    19        8  0.4210526
#2     1    13        2  0.1538462

答案 1 :(得分:2)

我将创建一个标志字段(即1或0),指示结果是否为异常值,然后将其输入相应的摘要中,而不是直接过滤()。