Створення нового стовпця умовно на основі попередніх n рядків


9

У мене встановлений кадр даних наступним чином:

 df <- data.frame("id" = c(111,111,111,222,222,222,222,333,333,333,333), 
                  "Location" = c("A","B","A","A","C","B","A","B","A","A","A"), 
                  "Encounter" = c(1,2,3,1,2,3,4,1,2,3,4))

      id Location Encounter
1  111        A         1
2  111        B         2
3  111        A         3
4  222        A         1
5  222        C         2
6  222        B         3
7  222        A         4
8  333        B         1
9  333        A         2
10 333        B         3
11 333        A         4

Я в основному намагаюся створити бінарний прапор, за яким місце розташування є в попередньому Зустрічі для кожної групи id. Так би виглядало так:

    id Location Encounter Flag
1  111        A         1    0
2  111        B         2    0
3  111        A         3    1
4  222        A         1    0
5  222        C         2    0
6  222        B         3    0
7  222        A         4    1
8  333        B         1    0
9  333        A         2    0
10 333        B         3    1
11 333        A         4    1

Я намагався розібратися, як зробити оператор if:

library(dplyr)

df$Flag <- case_when((df$id - lag(df$id)) == 0 ~ 
                case_when(df$Location == lag(df$Location, 1) | 
                          df$Location == lag(df$Location, 2) | 
                          df$Location == lag(df$Location, 3) ~ 1, T ~ 0), T ~ 0)

    id Location Flag
1  111        A    0
2  111        B    0
3  111        A    1
4  222        A    0
5  222        C    0
6  222        B    0
7  222        A    1
8  333        B    0
9  333        A    1
10 333        B    1
11 333        A    1

Але це питання, коли рядку 9 неправильно присвоюється 1, а в фактичних даних є випадки з 15+ зустрічами, тому це стає досить громіздким. Я сподівався знайти спосіб зробити щось подібне

lag(df$Location, 1:df$Encounter)

Але я знаю, lag()потрібне ціле число для k, щоб певна команда не працювала.


Ласкаво просимо до переповнення стека! Просто тому, що ви попросили зрозуміти, що стосується ТАК, ви можете прочитати, що робити, коли хтось відповість на ваше запитання . Окрім цього, не погано зайнятися екскурсією та прочитати « Як задати питання» (ваше запитання чудове, але воно дасть вам знак). Сподіваюсь, бачите вас тут, частіше. Ура.
M--

Відповіді:


6

Варіант с duplicated

library(dplyr)
df %>% 
  group_by(id) %>% 
  mutate(Flag = +(duplicated(Location)))
# A tibble: 11 x 4
# Groups:   id [3]
#      id Location Encounter  Flag
#   <dbl> <fct>        <dbl> <int>
# 1   111 A                1     0
# 2   111 B                2     0
# 3   111 A                3     1
# 4   222 A                1     0
# 5   222 C                2     0
# 6   222 B                3     0
# 7   222 A                4     1
# 8   333 B                1     0
# 9   333 A                2     0
#10   333 A                3     1
#11   333 A                4     1

4

У базі R ми можемо використовувати aveзгруповані по idта Locationперевернути всі значення з другого ряду групи до 1.

df$Flag <- as.integer(with(df, ave(Encounter, id, Location, FUN = seq_along) > 1))
df

#    id Location Encounter Flag
#1  111        A         1    0
#2  111        B         2    0
#3  111        A         3    1
#4  222        A         1    0
#5  222        C         2    0
#6  222        B         3    0
#7  222        A         4    1
#8  333        B         1    0
#9  333        A         2    0
#10 333        A         3    1
#11 333        A         4    1

Використовуючи dplyr, це було б

library(dplyr)

df %>%  group_by(id, Location) %>%  mutate(Flag = as.integer(row_number() > 1))

4

Використання data.table:

library(data.table)

dt[, flag:=1]
dt[, flag:=cumsum(flag), by=.(id,Location)]
dt[, flag:=ifelse(flag>1,1,0)]

Дані:

dt <- data.table("id" = c(111,111,111,222,222,222,222,333,333,333,333), 
                 "Location" = c("A","B","A","A","C","B","A","B","A","A","A"),
                 "Encounter" = c(1,2,3,1,2,3,4,1,2,3,4))

4

Більш загальним data.tableрішенням буде використання .Nабо rowid:

library(data.table)

setDT(dt)[, Flag := +(rowid(id, Location)>1)][]

або

setDT(df)[, Flag := +(seq_len(.N)>1), .(id, Location)][]
#>      id Location  Encounter Flag
#> 1:  111        A         1    0
#> 2:  111        B         2    0
#> 3:  111        A         3    1
#> 4:  222        A         1    0
#> 5:  222        C         2    0
#> 6:  222        B         3    0
#> 7:  222        A         4    1
#> 8:  333        B         1    0
#> 9:  333        A         2    0
#> 10: 333        A         3    1
#> 11: 333        A         4    1

0

Ви також можете скористатися цим:

library(data.table)
setDT(df)[,flag:=ifelse(1:.N>1,1,0),by=.(id,Location)] 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.