การลบกลุ่มที่มีคำสั่งแบบมีเงื่อนไขใน r

คำสั่งแบบมีเงื่อนไขคือในกรณีใดๆ หากมีแถวติดต่อกันสองแถวขึ้นไปที่มีค่ามากกว่า 1 ควรลบกลุ่มออก

ตัวอย่างเช่น:

Event<- c(1,1,1,1,2,2,2,2,2,2,3,3,3,3,3)
Value<- c(1,0,0,0,8,7,1,0,0,0,8,0,0,0,0)
A<- data.frame(Event, Value)

Event   Value
  1       1
  1       0
  1       0
  1       0
  2       8
  2       7
  2       1
  2       0
  2       0
  2       0
  3       8
  3       0
  3       0
  3       0
  3       0

ในตัวอย่างนี้ ควรลบกลุ่มของเหตุการณ์ 2 เนื่องจากมีแถวสองแถวติดต่อกันซึ่งมีค่ามากกว่า 1 ดังนั้นจึงควรมีลักษณะดังนี้:

Event   Value
  1       1
  1       0
  1       0
  1       0
  3       8
  3       0
  3       0
  3       0
  3       0

ข้อเสนอแนะใด ๆ ?


person Noel    schedule 25.04.2020    source แหล่งที่มา
comment
ใช่ มากกว่า 1   -  person Noel    schedule 25.04.2020
comment
หากมีกลุ่มมากกว่า 1 แถวติดต่อกัน โดยมีค่า >1 ฉันต้องการลบกลุ่ม   -  person Noel    schedule 25.04.2020
comment
ขออภัย มีกลุ่มมากกว่า 1 แถวติดต่อกัน ตามที่แสดงไว้ในตัวอย่าง   -  person Noel    schedule 25.04.2020
comment
ภายในกลุ่ม เป็นกรณีที่ค่าลดลงตามตัวอย่างนี้เสมอหรือไม่ หรือตัวอย่างเช่น เราอาจอยู่ในกลุ่มเดียวกัน: 3, 0, 1, 5 ตามลำดับนั้น (หมายความว่าไม่ควรลบกลุ่มเนื่องจากตัวเลขที่มากกว่า 1 ไม่ต่อเนื่องกัน)   -  person Aaron Montgomery    schedule 25.04.2020
comment
ไม่จำเป็น. ในตัวอย่างของคุณ (3,0,1,5) คุณพูดถูก ไม่ควรลบออก   -  person Noel    schedule 25.04.2020


คำตอบ (3)


เราสามารถใช้ rle ตามกลุ่มได้

library(dplyr)
A %>%
 group_by(Event) %>%
 filter(!any(with(rle(Value > 1), lengths[values] > 1)))
 #Opposite way using all
 #filter(all(with(rle(Value > 1), lengths[values] < 2)))

#  Event Value
#  <dbl> <dbl>
#1     1     1
#2     1     0
#3     1     0
#4     1     0
#5     3     8
#6     3     0
#7     3     0
#8     3     0
#9     3     0

ตรรกะเดียวกันนี้สามารถใช้ในฐาน R :

subset(A, !ave(Value > 1, Event, FUN = function(x) 
               any(with(rle(x), lengths[values] > 1))))

เช่นเดียวกับ data.table

library(data.table)
setDT(A)[, .SD[!any(with(rle(Value > 1), lengths[values] > 1))], Event]
person Ronak Shah    schedule 25.04.2020

ใช้ dplyr

A %>%
  group_by(Event) %>%
  mutate(consec = if_else(Value > 1, row_number(), 0L),
         remove = if_else(consec > 1,"Y","N")) %>%
  filter(!any(remove == "Y")) %>%
  select(-c("consec","remove"))
person Matt    schedule 25.04.2020

วิธีการ base R:

# split the dataframe by event into separate lists, record whether values are > 1 (T/F)
A_split <- split(A$Value > 1, Event)

# for each item in the list, record the number of consecutive T values;
# make T/F vector "keep" with row names corresponding to A$Event
keep <- sapply(A_split, function(x) sum(x[1:length(x) - 1] * x[2:length(x)])) == 0 

# convert keep to numeric vector of A$Event values
keep <- as.numeric(names(keep == T))

# subset A based on keep vector
A[A$Event %in% keep, ]

person Aaron Montgomery    schedule 25.04.2020