Назначение NA для строк с условным оператором в r - PullRequest
1 голос
/ 25 апреля 2020

Я пытаюсь назначить NA первым двум строкам каждого события следующим условным выражением: если первый день каждого события имеет значение «variable» = 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 должно быть назначенным с АН, я пытался сделать это с условиями, но не работает хорошо. Есть идеи? и заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 25 апреля 2020

РЕДАКТИРОВАТЬ: Новые примеры данных из 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 голос
/ 25 апреля 2020

Вот потенциальный tidyverse подход.

Вы можете сохранить последнее значение группы во временном столбце last_var и использовать lag, чтобы перейти к первой строке следующей группы для сравнение.

Обратите внимание, что значение по умолчанию в lag будет определять, будет ли variable в event 1 равным 0 или NA.

Окончательный mutate будет оценивать строку, если в первых двух строках группы и отметьте 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
...