根据 Group 和 ifelse 条件将 NA 分配给变量

Assign NA to a variable based on Group and ifelse condition

我正在尝试在 RAIN_15 列中分配 NA 值,如果 RAIN_15 中的任何行的值 > 100,则所有对应于 RAIN_15 中的 gr 的观察值] 将替换为 NA。示例数据如下:

   TRGCODE RAIN   DATE    TIME gr RAIN_15
    6155   0.0 2015-06-18 0000 17     0.0
    6155   0.0 2015-06-18 0015 17     0.0
    6155   0.0 2015-06-18 0030 17     0.0
    6155   0.0 2015-06-18 0045 17     0.0
    6155   0.0 2015-06-18 0100 17     0.0
    6155   0.0 2015-06-18 0115 17     0.0
    6155   0.0 2015-06-18 0130 17     0.0
    6155   0.0 2015-06-18 0145 17     0.0
    6155   0.0 2015-06-18 0200 17     0.0
    6155   0.0 2015-06-18 0215 17     0.0
    6155   0.0 2015-06-18 0230 17     0.0
    6155   0.0 2015-06-18 0245 17     0.0
    6155   0.2 2015-06-18 0300 17     0.2
    6155 123.7 2015-06-18 0315 17   123.5
    6155 127.0 2015-06-18 0330 17     3.3
    6155 127.0 2015-06-18 0345 17     0.0
    6155 127.0 2015-06-18 0400 17     0.0
    6155 127.0 2015-06-18 0415 17     0.0
    6155 127.0 2015-06-18 0430 17     0.0
    6155 127.0 2015-06-18 0445 17     0.0
    6155 127.0 2015-06-18 0500 17     0.0
    6155 141.7 2015-06-18 0515 17    14.7
    6155 594.3 2015-06-18 0530 17   452.6
    6155    NA 2015-06-18 0545 17      NA
    6155    NA 2015-06-18 0600 17      NA

数据有数千行,其中 gr 是基于 TIME 的组。这里 RAIN_15 的值 > 100,因此 RAIN_15 中对应于 gr 17 的所有观测值都应替换为 NA。 我试过

df_v1 <- df %>% group_by(TRGCODE, gr) %>% mutate(RAIN_15 = ifelse(any(RAIN_15 > 100), NA, RAIN_15)) 

但它正在用 0 替换 RAIN_15 值。如果我删除 ifelse 中的 any,那么它只是用 NA 替换 RAIN_15 中的值 > 100。

df <- read.table(header = TRUE, text = 'TRGCODE RAIN   DATE    TIME gr RAIN_15
    6155   0.0 2015-06-18 0000 17     0.0
    6155   0.0 2015-06-18 0015 17     0.0
    6155   0.0 2015-06-18 0030 17     0.0
    6155   0.0 2015-06-18 0045 17     0.0
    6155   0.0 2015-06-18 0100 17     0.0
    6155   0.0 2015-06-18 0115 17     0.0
    6155   0.0 2015-06-18 0130 17     0.0
    6155   0.0 2015-06-18 0145 17     0.0
    6155   0.0 2015-06-18 0200 17     0.0
    6155   0.0 2015-06-18 0215 17     0.0
    6155   0.0 2015-06-18 0230 17     0.0
    6155   0.0 2015-06-18 0245 17     0.0
    6155   0.2 2015-06-18 0300 17     0.2
    6155 123.7 2015-06-18 0315 17   123.5
    6155 127.0 2015-06-18 0330 17     3.3
    6155 127.0 2015-06-18 0345 17     0.0
    6155 127.0 2015-06-18 0400 17     0.0
    6155 127.0 2015-06-18 0415 17     0.0
    6155 127.0 2015-06-18 0430 17     0.0
    6155 127.0 2015-06-18 0445 17     0.0
    6155 127.0 2015-06-18 0500 17     0.0
    6155 141.7 2015-06-18 0515 17    14.7
    6155 594.3 2015-06-18 0530 17   452.6
    6155    NA 2015-06-18 0545 17      NA
    6155    NA 2015-06-18 0600 17      NA')

x=aggregate(RAIN_15 ~ gr, data = df, max)

x$RAIN_15=ifelse(x$RAIN_15>100, NA,x$RAIN_15)

df$RAIN_15=merge(df,x, all.x = TRUE, by="gr")[7]

data.table:

library(data.table)
setDT(df_v1)
df_v1[,RAIN_15:=fifelse(rep(any(RAIN_15>100,na.rm=T),.N),NA_real_,RAIN_15),by=gr][]

   TRGCODE  RAIN       DATE TIME gr RAIN_15
 1:    6155   0.0 2015-06-18    0 17      NA
 2:    6155   0.0 2015-06-18   15 17      NA
 3:    6155   0.0 2015-06-18   30 17      NA
 4:    6155   0.0 2015-06-18   45 17      NA
 5:    6155   0.0 2015-06-18  100 17      NA
 6:    6155   0.0 2015-06-18  115 17      NA
 7:    6155   0.0 2015-06-18  130 17      NA
 8:    6155   0.0 2015-06-18  145 17      NA
 9:    6155   0.0 2015-06-18  200 17      NA
10:    6155   0.0 2015-06-18  215 17      NA
11:    6155   0.0 2015-06-18  230 17      NA
12:    6155   0.0 2015-06-18  245 17      NA
13:    6155   0.2 2015-06-18  300 17      NA
14:    6155 123.7 2015-06-18  315 17      NA
15:    6155 127.0 2015-06-18  330 17      NA
16:    6155 127.0 2015-06-18  345 17      NA
17:    6155 127.0 2015-06-18  400 17      NA
18:    6155 127.0 2015-06-18  415 17      NA
19:    6155 127.0 2015-06-18  430 17      NA
20:    6155 127.0 2015-06-18  445 17      NA
21:    6155 127.0 2015-06-18  500 17      NA
22:    6155 141.7 2015-06-18  515 17      NA
23:    6155 594.3 2015-06-18  530 17      NA
24:    6155    NA 2015-06-18  545 17      NA
25:    6155    NA 2015-06-18  600 17      NA
    TRGCODE  RAIN       DATE TIME gr RAIN_15

为了完整起见,这里有两个 data.table 方法:

  1. if() ... else 分组
  2. 通过查找更新连接 table

1。 if() ... else 按组

library(data.table)
setDT(df)[, RAIN_15 := if (any(RAIN_15 > 100)) NA else RAIN_15, by = gr][]
    TRGCODE  RAIN       DATE  TIME    gr RAIN_15
 1:    6155   0.0 2015-06-18     0    17      NA
 2:    6155   0.0 2015-06-18    15    17      NA
 3:    6155   0.0 2015-06-18    30    17      NA
 4:    6155   0.0 2015-06-18    45    17      NA
 5:    6155   0.0 2015-06-18   100    17      NA
...
20:    6155 127.0 2015-06-18   445    17      NA
21:    6155 127.0 2015-06-18   500    17      NA
22:    6155 141.7 2015-06-18   515    17      NA
23:    6155 594.3 2015-06-18   530    17      NA
24:    6155    NA 2015-06-18   545    17      NA
25:    6155    NA 2015-06-18   600    17      NA
26:    6155   0.0 2015-06-18     0    18       0
27:    6155   0.0 2015-06-18    15    18       0
    TRGCODE  RAIN       DATE  TIME    gr RAIN_15

请注意,我使用了经过修改的样本数据集和一个额外的组(第 26、27 行)进行测试。

此方法使用 if() ... else 子句而不是像 .

中那样调用 fifelse() 函数

原因是 any() 已经是一个聚合函数,它总是 returns 一个长度为 的逻辑向量 。另外一点就是RAIN_15的元素应该替换为相同的值NAfifelse() 是一个向量函数,它逐个元素地重复决策,在这种情况下这是一种浪费。

但是,这种方法的缺点是 RAIN_15 列的 所有 元素被替换,即使对于那些根本不需要替换的组也是如此。

2。使用查找更新连接 table

这种方法只会在必要时更新行:

library(data.table)
setDT(df)[df[, which(any(RAIN_15 > 100)), by = gr], on = .(gr), RAIN_15 := NA][]

此处,df 查找 table 连接,其中包含需要通过引用更新的组 ID gr。其他组将保持不变。

查找table

创建
df[, which(any(RAIN_15 > 100)), by = gr]
      gr    V1
1:    17     1

它只包含满足条件的组ID。可以忽略第 V1 列。

数据

如上所述,修改后的示例数据集包括另一组的另外 2 行 testing/demonstration。

library(data.table)
df <- fread("
   TRGCODE RAIN   DATE    TIME gr RAIN_15
    6155   0.0 2015-06-18 0000 17     0.0
    6155   0.0 2015-06-18 0015 17     0.0
    6155   0.0 2015-06-18 0030 17     0.0
    6155   0.0 2015-06-18 0045 17     0.0
    6155   0.0 2015-06-18 0100 17     0.0
    6155   0.0 2015-06-18 0115 17     0.0
    6155   0.0 2015-06-18 0130 17     0.0
    6155   0.0 2015-06-18 0145 17     0.0
    6155   0.0 2015-06-18 0200 17     0.0
    6155   0.0 2015-06-18 0215 17     0.0
    6155   0.0 2015-06-18 0230 17     0.0
    6155   0.0 2015-06-18 0245 17     0.0
    6155   0.2 2015-06-18 0300 17     0.2
    6155 123.7 2015-06-18 0315 17   123.5
    6155 127.0 2015-06-18 0330 17     3.3
    6155 127.0 2015-06-18 0345 17     0.0
    6155 127.0 2015-06-18 0400 17     0.0
    6155 127.0 2015-06-18 0415 17     0.0
    6155 127.0 2015-06-18 0430 17     0.0
    6155 127.0 2015-06-18 0445 17     0.0
    6155 127.0 2015-06-18 0500 17     0.0
    6155 141.7 2015-06-18 0515 17    14.7
    6155 594.3 2015-06-18 0530 17   452.6
    6155    NA 2015-06-18 0545 17      NA
    6155    NA 2015-06-18 0600 17      NA
    6155   0.0 2015-06-18 0000 18     0.0
    6155   0.0 2015-06-18 0015 18     0.0
")