Dplyr和Tidyverse =>条件替换所有变量(遍历数据集)

时间:2018-12-06 12:47:46

标签: r loops replace dplyr tidyverse

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

比方说,我有一个包含6个变量(y1-y6)的数据集,我需要用“ NA”替换最低值之前的所有值,也用“ NA”替换最高值之后的所有值。

因此,此数据 Original dataset

将与以下类似:

new dataset

为使我的问题更清楚,如果变量在地板和天花板的外面,则需要将条目标记为NA。换句话说,在下图的 second 行中, y1 必须替换为NA(因为底数是y2)和 y6 < / strong>也必须替换为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))

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

@ Mark-Peterson的答案很好用,但是不需要编写外部函数。 您只能使用mutate if_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-01创建