如果这是重复,我深表歉意,我真的不知道我想要实现的目标的正确术语。
我有一个药物实验室结果的数据框,如下所示:
╔══════╦════════╗ ║ drug ║ result ║ ╠══════╬════════╣ ║ A ║ 10 ║ ║ B ║ 150 ║ ║ B ║ 50 ║ ║ A ║ 14 ║ ║ C ║ 3 ║ ║ C ║ 7 ║ ╚══════╩════════╝
For each drug, I'm using dplyr to remove outliers (>4 SD's from the mean) using the following:
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 ║ ╚══════╩═══════════╩══════════╩════════════╝
执行此操作的最佳方法是什么?
最佳答案
由于没有样本数据,我决定使用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
和 count()
中的 check
计算存在多少个数据点。然后,您使用 tidyr
包中的 spread()
reshape 结果。现在计算 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
关于R 按组对数据帧进行汇总统计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32847613/