Tạo một cột mới có điều kiện dựa trên n hàng trước


9

Tôi có một khung dữ liệu được thiết lập như sau:

 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

Về cơ bản, tôi đang cố gắng tạo một cờ nhị phân, một vị trí nằm trong Cuộc gặp gỡ trước đó cho mỗi nhóm id. Vì vậy, nó sẽ trông như:

    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

Tôi đã cố gắng tìm ra cách để thực hiện một câu lệnh if như:

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

Nhưng điều này có vấn đề trong đó Row 9 đang được gán 1 không chính xác và có những trường hợp có hơn 15 lần gặp trong dữ liệu thực tế nên điều này trở nên khá cồng kềnh. Tôi đã hy vọng tìm ra cách để làm một cái gì đó như

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

Nhưng tôi biết lag()cần một số nguyên cho k, vì vậy lệnh cụ thể sẽ không hoạt động.


Chào mừng bạn đến với Stack Overflow! Chỉ vì bạn đã hỏi về những hiểu biết về thói quen SO, bạn có thể muốn đọc điều này về những việc cần làm khi ai đó trả lời câu hỏi của bạn . Bên cạnh đó, việc tham quan và đọc Cách hỏi (câu hỏi của bạn rất hay, nhưng nó sẽ cho bạn một huy hiệu) không phải là ý kiến ​​tồi . Hy vọng sẽ nhìn thấy bạn xung quanh đây, thường xuyên hơn. Chúc mừng.
M--

Câu trả lời:


6

Một tùy chọn với 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

Trong cơ sở R, chúng ta có thể sử dụng aveđược phân nhóm theo idLocationvà biến tất cả các giá trị từ hàng thứ hai của nhóm 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

Sử dụng dplyr, đó sẽ là

library(dplyr)

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

4

Sử dụng data.table:

library(data.table)

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

Dữ liệu:

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

Một data.tablegiải pháp chung hơn sẽ được sử dụng .Nhoặc rowid:

library(data.table)

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

hoặc là

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

Bạn cũng có thể sử dụng điều này:

library(data.table)
setDT(df)[,flag:=ifelse(1:.N>1,1,0),by=.(id,Location)] 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.