【问题标题】:R: Pushing entire row to NA based on condition in one column at a timeR:一次根据一列中的条件将整行推送到NA
【发布时间】:2020-09-30 16:14:24
【问题描述】:

假设 df:

A   B   C   D   E   F
1   10  NA  10  NA  10
10  NA  10  1   10  10
10  1   1   NA  NA  NA
10  10  NA  10  10  10
10  NA  10  10  1   10

我想做的是遍历列以检查具有以下条件的每一行的值:

  • A
  • C
  • E
  • F

...随后,循环列中的行与相应条件匹配,整行将被推送到 NA

期望的结果:

A   B   C   D   E   F
NA  NA  NA  NA  NA  NA
10  NA  10  1   10  10
NA  NA  NA  NA  NA  NA
NA  NA  NA  NA  NA  NA
NA  NA  NA  NA  NA  NA

我尝试对其中一列执行此操作:

df[df$A<5, ] <- NA

但是这导致了错误

Error in `[<-.data.frame`(`*tmp*`, df$A < 5, , value = NA) : 
  missing values are not allowed in subscripted assignments of data frames

请指教

【问题讨论】:

  • @Phil 很抱歉打错了字,因为我在编辑过程中不小心通过单击 Enter 发布了问题,我已经修复了错字。但是错误仍然存​​在...

标签: r loops if-statement variable-assignment na


【解决方案1】:

您可以在对不需要的行进行子集化后分配NA

df[with(df,A<5 | C<3 | E<7 | F<2 |
           is.na(A) | is.na(C) | is.na(E) | is.na(F)),] <- NA
df
#   A  B  C  D  E  F
#1 NA NA NA NA NA NA
#2 10 NA 10  1 10 10
#3 NA NA NA NA NA NA
#4 NA NA NA NA NA NA
#5 NA NA NA NA NA NA

方法是为每一行的每个条件创建一个逻辑向量,然后将它们与|(或)结合起来。然后您可以使用该逻辑向量对df 进行子集化,以仅将满足条件的行替换为NA

使用with 使您不必输入df$ 8 次。


根据实际数据中有多少条件,您可以使用Reduce 使其更紧凑,但可能不行:

df[with(df,Reduce(`|`,c(list(A<5, C<3, E<7, F<2),
                        lapply(list(A,C,E,F),is.na)))),] <- NA

【讨论】:

  • 我在dat[-which(!Reduce(`|`, Map(`&lt;`, dat[vars], c(5,3,7,2)))),] &lt;- NA 中有一个类似的Map + Reduce 想法,我认为它与NA 隐含地有效
  • 嗯,我喜欢这个。如果你写了一个答案,我会赞成。 ;)
  • 我不是 100% 确定它适用于所有情况,但我会在有时间的时候返回它。
  • 可能类似于df[-which(Reduce(`&amp;`, Map(`&gt;`,with(df,list(A,C,E,F)),c(5,3,7,2)))),] &lt;- NA
【解决方案2】:

您可以使用一些tidyverse 操作

library(dplyr)

df_example <- data.table::fread("A   B   C   D   E   F
1   10  NA  10  NA  10
10  NA  10  1   10  10
10  1   1   NA  NA  NA
10  10  NA  10  10  10
10  NA  10  10  1   10")

df_example %>%
  mutate(across(everything(), ~ as.numeric(.x))) %>%
  rowwise() %>%
  mutate(exclude = any(c_across(c(A,C,E,F)) %>% is.na() | A < 5 | C < 3 | E < 7 | F < 2)) %>%
  mutate(across(everything(), .fns = ~ ifelse(exclude == TRUE, yes = NA, .x))) %>%
  select(-exclude) %>%
  ungroup()
#> # A tibble: 5 x 6
#>       A     B     C     D     E     F
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1    NA    NA    NA    NA    NA    NA
#> 2    10    NA    10     1    10    10
#> 3    NA    NA    NA    NA    NA    NA
#> 4    NA    NA    NA    NA    NA    NA
#> 5    NA    NA    NA    NA    NA    NA

【讨论】:

    猜你喜欢
    • 2021-06-25
    • 2021-12-28
    • 1970-01-01
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多