使用r中的条件语句将NA分配给行

问题描述 投票:1回答:2

我正在尝试使用以下条件语句将NA分配给每个事件的前两行:如果每个事件的第一天的值都为“变量” = 0,请检查前一天。如果前一天(上一个事件的最后一天)的“变量”> 0,则将NA分配给事件的前两行,第一天的“变量” = 0。如果前一天的“变量” = 0,则不执行任何操作。

这里是一个例子:

day <- c(1:16)
event<- c(1,1,2,3,4,4,4,5,5,5,6,6,6,7,7,7)
variable<- c(0,0,5,0,0,0,10,0,1,1,0,0,0,0,0,0)
A<- data.frame(day, event, variable)
     day  event  variable
1     1     1        0
2     2     1        0
3     3     2        5
4     4     3        0
5     5     4        0
6     6     4        0
7     7     4       10
8     8     5        0
9     9     5        1
10   10     5        1
11   11     6        0
12   12     6        0
13   13     6        0
14   14     7        0
15   15     7        0
16   16     7        0

以及它的外观如何

     day  event  variable
1     1     1        0
2     2     1        0
3     3     2        5
4     4     3       NA
5     5     4        0
6     6     4        0
7     7     4       10
8     8     5       NA
9     9     5       NA
10   10     5        1
11   11     6       NA
12   12     6       NA
13   13     6        0
14   14     7        0
15   15     7        0
16   16     7        0

注意:是否必须为事件1分配NA我尝试在if条件下执行此操作,但效果不佳。任何的想法?并预先感谢!

r if-statement dplyr conditional-statements na
2个回答
2
投票

编辑:来自OP的新示例数据

library(data.table)
event2<- c(1,2,2,3,4,4,4,4,4,5,5) 
variable2<- c(140, 0, 69, 569, 28, 0,0,0,100,0,0) 
desire_output<- c(140, NA, NA, 569, 28, 0,0,0,100, NA,NA) 
A2<- data.frame(event2, variable2, desire_output) 

setDT(A2)

A2[,first_days_event:=fifelse(.I==min(.I),1,fifelse(.I==min(.I)+1,2,NA_integer_)),by=.(event2)]

A2[,result:={v <- variable2
for (i in 2:.N) {
  if (is.na(first_days_event[i])) {
    v[i] <- variable2[i]
  } else if (first_days_event[i]==1 & variable2[i]==0){
    if (variable2[i-1]>0) {
      v[i] <- NA_integer_
      if (first_days_event[i+1]==2) {
        v[i+1] <- NA_integer_
      }
    }
  }
}
v}]
A2
#>     event2 variable2 desire_output first_days_event result
#>  1:      1       140           140                1    140
#>  2:      2         0            NA                1     NA
#>  3:      2        69            NA                2     NA
#>  4:      3       569           569                1    569
#>  5:      4        28            28                1     28
#>  6:      4         0             0                2      0
#>  7:      4         0             0               NA      0
#>  8:      4         0             0               NA      0
#>  9:      4       100           100               NA    100
#> 10:      5         0            NA                1     NA
#> 11:      5         0            NA                2     NA

我将使用此简单的loop解决方案。只需创建一个标志来指示每个事件的前两个日子。

library(data.table)

day <- c(1:16)
event<- c(1,1,2,3,4,4,4,5,5,5,6,6,6,7,7,7)
variable<- c(0,0,5,0,0,0,10,0,1,1,0,0,0,0,0,0)
A<- data.frame(day, event, variable)

setDT(A)


A[,first_days_event:=fifelse(.I==min(.I),1,fifelse(.I==min(.I)+1,2,NA_integer_)),by=.(event)]

A[,result:={v <- numeric(.N)
  for (i in 2:.N) {
    if (is.na(first_days_event[i])) {
      v[i] <- variable[i]
    } else if (first_days_event[i]==1){
      if (variable[i-1]>0) {
        v[i] <- NA_integer_
        if (first_days_event[i+1]==2) {
          v[i+1] <- NA_integer_
        }
      } else {
        v[i] <- variable[i]
      }
    }
  }
v}]

A
#>     day event variable first_days_event result
#>  1:   1     1        0                1      0
#>  2:   2     1        0                2      0
#>  3:   3     2        5                1      5
#>  4:   4     3        0                1     NA
#>  5:   5     4        0                1      0
#>  6:   6     4        0                2      0
#>  7:   7     4       10               NA     10
#>  8:   8     5        0                1     NA
#>  9:   9     5        1                2     NA
#> 10:  10     5        1               NA      1
#> 11:  11     6        0                1     NA
#> 12:  12     6        0                2     NA
#> 13:  13     6        0               NA      0
#> 14:  14     7        0                1      0
#> 15:  15     7        0                2      0
#> 16:  16     7        0               NA      0

1
投票

这是一种潜在的tidyverse方法。

您可以将组的最后一个值存储在临时列last_var中,然后使用lag移至以下组的第一行进行比较。

请注意,lag中的默认值将确定variable 1中的event是0还是NA

最后的mutate将评估该行是否在组的前2行之内,并检查last_var以确定是否应将其设置为NA或不设置。

编辑

:对于ifelse,还需要检查事件的第一天variable是否为0。
library(tidyverse)

A %>%
  group_by(event) %>%
  mutate(last_var = ifelse(row_number() == n(), last(variable), 0)) %>%
  ungroup %>%
  mutate(last_var = lag(last_var, default = 0)) %>%
  group_by(event) %>%
  mutate(variable = ifelse(row_number() <= 2 & first(last_var) > 0 & first(variable) == 0, NA, variable)) %>%
  select(-last_var)

输出

# A tibble: 16 x 3
# Groups:   event [7]
     day event variable
   <int> <dbl>    <dbl>
 1     1     1        0
 2     2     1        0
 3     3     2        5
 4     4     3       NA
 5     5     4        0
 6     6     4        0
 7     7     4       10
 8     8     5       NA
 9     9     5       NA
10    10     5        1
11    11     6       NA
12    12     6       NA
13    13     6        0
14    14     7        0
15    15     7        0
16    16     7        0

[在注释中包含第二个数据框:

输出

# A tibble: 11 x 3
# Groups:   event [5]
   event variable desire_output
   <dbl>    <dbl>         <dbl>
 1     1      140           140
 2     2       NA            NA
 3     2       NA            NA
 4     3      569           569
 5     4       28            28
 6     4        0             0
 7     4        0             0
 8     4        0             0
 9     4      100           100
10     5       NA            NA
11     5       NA            NA
© www.soinside.com 2019 - 2024. All rights reserved.