【发布时间】:2020-06-05 20:44:13
【问题描述】:
应合作者的要求,我正在尝试创建删除异常值的数据集的第二个版本。我有多个组(因素)和多个数值响应变量的数据。我想编写一个函数,(1)使用 1.5*IQR 和 3*IQR 方法按组查找异常值和极值,(2)计算异常值,以及(3)如果异常值的数量大于 2,则替换值对于 EXTREMES 仅使用 NA,但如果异常值的数量小于或等于 2,则将 OUTLIERS 的值替换为 NA。
因为这是一个分组计算,所以我选择使用 dplyr。我希望将此函数应用于我的数据集中的几个响应变量中的每一个。我已经使用这种方法实现了步骤 (1) 和 (2),但在步骤 (3) 中遇到了以下问题。
第 1 步和第 2 步:
require(dplyr)
# Find outliers and extremes for one response variable by group. Mark if number of outliers per group is >2.
# List outliers and extremes.
out_ext_num <- iris %>%
group_by(Species) %>%
mutate(is_outlier = (Sepal.Length < summary(Sepal.Length)[2] - (1.5*IQR(Sepal.Length)) |
(Sepal.Length > ((1.5*IQR(Sepal.Length)) + summary(Sepal.Length)[5]))),
is_extreme = (Sepal.Length < (summary(Sepal.Length)[2] - (3*IQR(Sepal.Length)))) |
(Sepal.Length > ((3*IQR(Sepal.Length)) + summary(Sepal.Length)[5]))) %>%
summarise(out_num2 = sum(is_outlier) > 2, outliers = list(Sepal.Length[is_outlier == T]),
extremes = list(Sepal.Length[is_extreme == T]))
# A tibble: 3 x 4
Species out_num2 outliers extremes
<fct> <lgl> <list> <list>
1 setosa FALSE <dbl [0]> <dbl [0]>
2 versicolor FALSE <dbl [0]> <dbl [0]>
3 virginica FALSE <dbl [1]> <dbl [0]>
我可以将它与我的数据的嵌套版本结合起来,以便组排列: (已编辑)
nested <- iris %>%
select(Species, Sepal.Length) %>%
group_by(Species) %>%
nest() %>%
left_join(out_ext_num)
# A tibble: 3 x 5
# Groups: Species [3]
Species data out_num2 outliers extremes
<fct> <list> <lgl> <list> <list>
1 setosa <tibble [50 x 1]> FALSE <dbl [0]> <dbl [0]>
2 versicolor <tibble [50 x 1]> FALSE <dbl [0]> <dbl [0]>
3 virginica <tibble [50 x 1]> FALSE <dbl [1]> <dbl [0]>
现在,对于每个组,如果out_num2 是FALSE,我想将data tibble(包含向量Sepal.Length)中的值与outliers 列表中的值相匹配。如果它们匹配,我想用NA 替换小标题中的那个值。如果out_num2 是TRUE,我想将data tibble 中的值与extremes 列表中的值匹配,并将tibble 中的相应值替换为NA。现在,我什至无法将列表中的值与小标题、句号匹配,更不用说有条件地匹配了。我曾尝试在mutate() 和map() 中使用%in%,但感觉我在小标题中错误地引用了Sepal.Length 向量:
require(purrr)
nested %>%
mutate(Sepal.Length.o = map(data, ~ ifelse(Sepal.Length[.x %in% nested$outliers], NA, Sepal.Length)))
我查看了来自不同站点的列表引用和几篇关于匹配值的帖子,但这种 dplyr 格式并不适用。有没有其他或更好的方法来做到这一点?
在弄清楚如何匹配之后,我打算使用嵌套的ifelse 语句来有条件地用NA 替换异常值或极值,可能类似于这样:
nested %>%
mutate(Sepal.Length.o = ifelse(out_num2 == T,
ifelse(match_tibble_with_extremes, NA, Sepal.Length),
ifelse(match_tibble_with_outliers, NA, Sepal.Length)))
但我不确定这是否会如我所愿。任何帮助,尤其是匹配步骤,将不胜感激。
【问题讨论】:
-
什么是
out_num -
应该是
out_ext_num。我已经在帖子中对其进行了编辑。谢谢。 -
在您的示例中,所有行都将
out_num2设为 FALSE -
iris 数据集就是这种情况,但对于我自己的数据,我可能会得到一些 TRUE,具体取决于数据集。
-
你可以试试
nested %>% rowwise %>% mutate(data = map2(data, if(out_num2) list(extremes) else list(outliers), ~ replace(.x, .x %in% .y, NA)))