Почему в ifelse функции с операторами AND неверные результаты - PullRequest
0 голосов
/ 06 июня 2019

У меня есть следующий набор данных:

df1 <- data.frame(number = c(1,1,0,0,0,0,0,1,1))

В этом наборе данных я хочу создать второй столбец, который показывает, есть ли в определенной строке первого столбца случай, когда первый и второй лагиравны 0, а первый отвод равен 1. Если это так, то число 1 помещается во второй столбец, где произошло изменение от 0 до 1 (если не случай, то равно 44. В результате впри этом все строки во втором столбце должны быть равны 44, кроме восьмого.

Вот мой код. В комментариях ниже я выложу фотографию необходимого результата.

df1$t<-ifelse(df1[,1]==1 & lag(df1[,1]==0,1,default = 44) & lag(df1[,1]==0,2,default = 44)
                              & lead(df1[,1]==1,1,default = 44)
                              ,1,44)

1 Ответ

0 голосов
/ 06 июня 2019

Хотя ФП попросил объяснить, почему его код не возвращает ожидаемый результат (на который указывает комментарий Грегора ), я хотел бы предложить альтернативный подход.

Если я правильно понимаю, ОП хочет найти все подпоследовательности в df1$number, которые состоят из двух нулей, за которыми следуют два, то есть c(0, 0, 1, 1). Затем строка, содержащая первую последовательность в подпоследовательности, должна быть помечена 1, тогда как все остальные строки должны получить 44 в качестве значения по умолчанию.

Начиная с версии v1.12.0 (на CRAN 13 января 2019 г.) с data.table, функция shift() распознает отрицательные параметры задержки / опережения. Таким образом, столбец может быть сдвинут на несколько значений в одном пакете. Номера строк, которые удовлетворяют вышеуказанному условию, идентифицируются последующей операцией соединения. Наконец, df1 обновляется выборочно, используя следующие номера строк:

# use enhanced sample dataset, rows 10 to 21 added
df1 <- data.frame(number = c(1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1))

library(data.table)
setDT(df1)[, t := 44] # coerce to data.table, pre-populate result column
# shift and join
idx <- df1[, shift(number, 2:-1)][.(0, 0, 1, 1), on = paste0("V", 1:4), which = TRUE]
df1[idx, t := 1] # selective update
df1
    number  t
 1:      1 44
 2:      1 44
 3:      0 44
 4:      0 44
 5:      0 44
 6:      0 44
 7:      0 44
 8:      1  1
 9:      1 44
10:      0 44
11:      1 44
12:      0 44
13:      1 44
14:      1 44
15:      0 44
16:      0 44
17:      1 44
18:      0 44
19:      0 44
20:      1  1
21:      1 44
    number  t

Это работает по существу как подход OP, сдвигая и сравнивая с ожидаемыми значениями. Однако подход OP требует кодирования четырех сравнений и трех операций сдвига, в то время как здесь сдвиг выполняется за один шаг, а сравнение всех столбцов одновременно выполняется операцией соединения на втором этапе.

Дополнительные пояснения

Сдвиг

df1[, shift(number, 2:-1)]

возвращает

    V1 V2 V3 V4
 1: NA NA  1  1
 2: NA  1  1  0
 3:  1  1  0  0
 4:  1  0  0  0
 5:  0  0  0  0
 6:  0  0  0  0
 7:  0  0  0  1
 8:  0  0  1  1
 9:  0  1  1  0
10:  1  1  0  1
11:  1  0  1  0
12:  0  1  0  1
13:  1  0  1  1
14:  0  1  1  0
15:  1  1  0  0
16:  1  0  0  1
17:  0  0  1  0
18:  0  1  0  0
19:  1  0  0  1
20:  0  0  1  1
21:  0  1  1 NA
    V1 V2 V3 V4

В последующей операции соединения

df1[, shift(number, 2:-1)][.(0, 0, 1, 1), on = paste0("V", 1:4), which = TRUE]

which = TRUE запрашивает возврат только индексов совпадающих строк, которые

[1]  8 20
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...