【问题标题】:Dplyr and Tidyverse => conditional replace all variables (looping through a dataset)Dplyr 和 Tidyverse => 有条件地替换所有变量(循环数据集)
【发布时间】:2019-05-08 04:11:45
【问题描述】:

这是一个简单的问题,但答案却花费了我更多的时间。我找到的最接近的答案是one。所以,我在这里 - 一如既往 - 寻求帮助!

假设我有一个包含 6 个变量 (y1-y6) 的数据集,我需要将地板之前的所有值替换为“NA”,并将天花板之后的所有值替换为“NA”。

所以,这个数据

会像下面这样:

为了明确我的问题,如果 变量 在地板和天花板之外,我需要将条目标记为 NA。也就是说,在下图的第二行,y1必须换成NA(因为地板是y2)和y6 也必须换成NA,因为上限是y5。

我是 dplyr 用户,如果答案使用 tidyverse 环境,我会很高兴。

一如既往的感谢!

ds <- data.frame(floor = c(1:2),
                 ceiling = c(4,5),
                 y1 = c(1,2),
                 y2 = c(1,2),
                 y3 = c(1,2),
                 y4 = c(1,2),
                 y5 = c(1,2),
                 y6 = rep(c(1,2),3))

【问题讨论】:

  • 如果 在地板/天花板之外或如果 列索引 在地板/天花板?具体来说,如果列y3 的值1 的行底为2,那么该值是否应该标记为NA?相反,如果列y1 的值为3 且行底为2,则该值是否应标记为NA?
  • 好问题!如果 variable 不是/不在地板和天花板之外,我正在尝试将条目标记为NA。换句话说,在第二行中,y1必须替换为NA(因为地板是y2),y6也必须替换为NA,因为天花板是y5。我将编辑问题以使其清楚。 @马克彼得森

标签: r loops replace dplyr tidyverse


【解决方案1】:

您可以首先创建一个函数来确定传递的索引是否在一组边界内,如果是则分配NA,否则分配一个单独的传递值。这里,x 是列索引,val 是您要分配的值,如果不是 NAlow 是下限(下限),high 是上限(上限):

altMask <- function(x, val, low, high){
  sapply(1:length(x), function(idx){
    ifelse(between(x[idx], low[idx], high[idx]), val[idx], NA)
  })
}

然后,您可以将数据转换为长格式(注意添加行索引变量以在转换回宽格式时使用),应用函数,然后转换回来:

ds %>%
  mutate(rowIdx = 1:n()) %>%
  gather(col, value, starts_with("y")) %>%
  mutate(value = altMask(parse_number(col), value, floor, ceiling)) %>%
  spread(col, value) %>%
  arrange(rowIdx) %>%
  select(-rowIdx)

返回:

  floor ceiling y1 y2 y3 y4 y5 y6
1     1       4  1  1  1  1 NA NA
2     2       5 NA  2  2  2  2 NA
3     1       4  1  1  1  1 NA NA
4     2       5 NA  2  2  2  2 NA
5     1       4  1  1  1  1 NA NA
6     2       5 NA  2  2  2  2 NA

【讨论】:

  • 马克,感谢您提供的出色解决方案!我今天将使用它,但我会回到这里了解您在此代码中采取的每一步!你的回答真的很优雅!
【解决方案2】:

@Mark-Peterson 的回答效果很好,但没有必要编写外部函数。 你可以只mutateif_else标准等。 (if_elseifelse 的矢量化形式,因此不再需要 sapply

library(tidyverse)
ds <- data.frame(floor = c(1:2),
                 ceiling = c(4,5),
                 y1 = c(1,2),
                 y2 = c(1,2),
                 y3 = c(1,2),
                 y4 = c(1,2),
                 y5 = c(1,2),
                 y6 = rep(c(1,2),3))

ds %>%
  mutate(rowIdx = 1:n()) %>%
  pivot_longer(cols = starts_with("y"), names_to = "col") %>%
  mutate(col_num = parse_number(col),
         value_after_floor_and_ceiling = if_else(col_num >= floor & col_num <= ceiling, value, NA_real_)) %>%
  select(-col_num, -value, value = value_after_floor_and_ceiling) %>%
  pivot_wider(names_from = "col") %>%
  arrange(rowIdx) %>%
  select(-rowIdx)
#> # A tibble: 6 x 8
#>   floor ceiling    y1    y2    y3    y4    y5    y6
#>   <int>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1       4     1     1     1     1    NA    NA
#> 2     2       5    NA     2     2     2     2    NA
#> 3     1       4     1     1     1     1    NA    NA
#> 4     2       5    NA     2     2     2     2    NA
#> 5     1       4     1     1     1     1    NA    NA
#> 6     2       5    NA     2     2     2     2    NA

reprex package (v0.3.0) 于 2019 年 12 月 1 日创建

【讨论】:

    猜你喜欢
    • 2020-11-17
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 2022-01-09
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多