thanks for the puzzle, I have some doubts about deleting the nearest previous "y matching " row for negative x, as I'm not sure if it should matter the x value of that candidate for deletion.. but my implementation at least 'works' when judged by the test data, and your expectation of rows it deletes.
Note that I could have done a simple for loop over each negative x that I wanted to find matches for, but I got cute and used the slider package which I was recently introduced to.
library(tidyverse)
library(slider)
<- structure(list(
x = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1),
y = c(84, 28, 0, 112, 28, 112, 112, 28, 28, 112, 28, 28,
112, 28, 112, 112, 28, 28, 112, 112, 28, 28, 112, 112, 28, 112,
28, 28, 112, 28, 112, 28, 112, 112, 28)
), class = "data.frame", row.names = c(NA, -35L))
# step 1, harden up the rownumbers
d2 <- d %>% mutate(rownum = row_number())
# step 2, extract the negative x's
neg_x <- d2 %>% filter(x<0)
# step 3, want search for the nearest row above with matching y
# first lookup for each -ex the dataframe containing all rows before it that match its y value
searches_to_perform <- slide(.x = neg_x,
.f = ~ filter(slice(d2,1:.[["rownum"]]),y==.[["y"]]),
)
#step 4, the 2nd to last entry if it exists is what we want to mark for deletion
# do we need an additional rule though, to insist that x == 1 for example ? in the test data x isnt not 1 , does this matter ?
found_em <- map(searches_to_perform,~(tail(.,2)) %>% slice(1))
#step 5 , make a list of rows to delete
rows_to_del <- c(bind_rows(found_em) %>% pull(rownum),pull(neg_x,rownum))
d2$rows_to_del <- d2$rownum %in% rows_to_del
# do the delete
d3 <- filter(d2, rows_to_del==FALSE) %>% select(x,y)