根据前一列的值替换多个列中的值

4

我的样本数据看起来像这样(真实数据更大)

library(tidyverse, warn.conflicts = F)
df <- tibble(chr_x = c(0,0,1,1,1,4,4,4,5,5,6,7),
             pos_x = c(1,2,3,4,5,6,7,8,9,0,1,2),
             chr_y = c(1,2,3,3,3,2,1,1,0,0,1,5),
             pos_some = c(1,2,3,4,5,6,7,8,9,0,1,2))

我需要替换某些列中的特定值(比如以 chr 开头的值)为 NA,我是这样做的。

df %>% mutate_at(vars(starts_with("chr")), ~ na_if(., 0))
#> # A tibble: 12 x 4
#>    chr_x pos_x chr_y pos_some
#>    <dbl> <dbl> <dbl>    <dbl>
#>  1    NA     1     1        1
#>  2    NA     2     2        2
#>  3     1     3     3        3
#>  4     1     4     3        4
#>  5     1     5     3        5
#>  6     4     6     2        6
#>  7     4     7     1        7
#>  8     4     8     1        8
#>  9     5     9    NA        9
#> 10     5     0    NA        0
#> 11     6     1     1        1
#> 12     7     2     5        2

下一部分是我卡住的地方。现在我需要将后续列中的值替换为NA,其中在上面的列中值为NA。我该怎么做?生成的数据框应该如下所示。
#> # A tibble: 12 x 4
#>    chr_x pos_x chr_y pos_some
#>    <dbl> <dbl> <dbl>    <dbl>
#>  1    NA     NA     1        1
#>  2    NA     NA     2        2
#>  3     1     3     3        3
#>  4     1     4     3        4
#>  5     1     5     3        5
#>  6     4     6     2        6
#>  7     4     7     1        7
#>  8     4     8     1        8
#>  9     5     9    NA        NA
#> 10     5     0    NA        NA
#> 11     6     1     1        1
#> 12     7     2     5        2

这篇文章是由 reprex 包 (v0.3.0) 在 2020-05-21 创建的。

2个回答

4

使用 dplyrpurrr 的一个选项可能是:

bind_cols(df %>%
           select(1) %>%
           mutate_all(~ na_if(., 0)),
          map_dfc(.x = 2:length(df),
                  ~ df %>% 
                   mutate_at(vars(starts_with("chr")), ~ na_if(., 0)) %>%
                   transmute_at(vars(.x), ~ replace(., !!is.na(select(., .x - 1)), NA))))

   chr_x pos_x chr_y pos_some
   <dbl> <dbl> <dbl>    <dbl>
 1    NA    NA     1        1
 2    NA    NA     2        2
 3     1     3     3        3
 4     1     4     3        4
 5     1     5     3        5
 6     4     6     2        6
 7     4     7     1        7
 8     4     8     1        8
 9     5     9    NA       NA
10     5     0    NA       NA
11     6     1     1        1
12     7     2     5        2

谢谢您提供的解决方案,它确实有效,但似乎有点复杂。 - cropgen

3
我们可以使用基本的R语言。创建一个“chr”列的索引(“i1”),对“chr”列进行子集操作,将值为0对应的值转换为NA(“i2”),并通过乘以i2来更新“i1”和相邻位置的值(“i2”)。
i1 <- which(startsWith(names(df), 'chr'))
i2 <- NA^(df[i1] == 0)
df[i1] <- df[i1] * i2
df[i1 + 1] <- df[i1 + 1] * i2
df
# A tibble: 12 x 4
#   chr_x pos_x chr_y pos_some
#   <dbl> <dbl> <dbl>    <dbl>
# 1    NA    NA     1        1
# 2    NA    NA     2        2
# 3     1     3     3        3
# 4     1     4     3        4
# 5     1     5     3        5
# 6     4     6     2        6
# 7     4     7     1        7
# 8     4     8     1        8
# 9     5     9    NA       NA
#10     5     0    NA       NA
#11     6     1     1        1
#12     7     2     5        2

1
这是一个非常优美的解决方案。 - Shan R
这很不错。我以前没见过这种符号 NA^(df[i1] == 0),你能解释一下吗?它似乎是将匹配的值替换为 NA,其他所有值替换为 1 - cropgen
@cropgen 它基于 NA^0NA^1,分别返回 1 和 NA。逻辑向量 TRUE/FALSE (df[i1] == 0) 在内部被转换为 1/0,因此会出现您注意到的行为。 - akrun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接