如果这是重复,我道歉,我真的不知道我正在努力实现的正确术语。
我有一个药物实验室结果的数据框如下:
╔══════╦════════╗ ║ 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 ║ ╚══════╩═══════════╩══════════╩════════════╝
这样做的最佳方式是什么?
答案 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。您可以计算am
中check
和count()
存在的数据点数。然后,您使用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),指示结果是否为异常值,然后将其输入相应的摘要中,而不是直接过滤()。