这是一个简单的问题,但是答案使我花了更多的时间。我找到的最接近的答案是这个one。所以,我像往常一样在这里寻求帮助!
比方说,我有一个包含6个变量(y1-y6)的数据集,我需要用“ NA”替换最低值之前的所有值,也用“ NA”替换最高值之后的所有值。
将与以下类似:
为使我的问题更清楚,如果变量在地板和天花板的外面,则需要将条目标记为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))
答案 0 :(得分:1)
您可以首先创建一个函数,该函数确定传递的索引是否在一组边界之内,如果是NA
,则为x
,否则,则为一个单独的传递值。这里,val
是列索引,NA
是要分配的值(如果不是low
,high
是下界(底限),{{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_else
是ifelse
的向量化形式,因此不再需要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创建