【问题标题】:R Dplyr: How to replace items in a vector matching items in a list, conditionallyR Dplyr:如何有条件地替换向量中的项目匹配列表中的项目
【发布时间】: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_num2FALSE,我想将data tibble(包含向量Sepal.Length)中的值与outliers 列表中的值相匹配。如果它们匹配,我想用NA 替换小标题中的那个值。如果out_num2TRUE,我想将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 %&gt;% rowwise %&gt;% mutate(data = map2(data, if(out_num2) list(extremes) else list(outliers), ~ replace(.x, .x %in% .y, NA)))

标签: r dplyr match


【解决方案1】:

这是一种选择

library(dplyr)
library(purrr)
nested %>% 
   rowwise %>% 
   mutate(data = map2(data, if(out_num2) list(extremes) else list(outliers),  ~ replace(.x, .x %in% .y, NA)))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-12
    • 2011-10-04
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 2019-12-02
    • 2021-12-22
    • 2019-02-03
    相关资源
    最近更新 更多