Определение перекрывающихся случаев при создании групп в R - PullRequest
0 голосов
/ 16 апреля 2020

У меня есть три условия, которые все должны быть выполнены, которые определяют, в какой случай должна быть помещена конкретная запись. Все переменные x, y и z находятся в диапазоне [1,10]. Мой вклад будет нижняя и верхняя границы для каждого условия и для каждого случая. Я понимаю, что если бы у меня было только одно условие, я мог бы сравнивать диапазоны напрямую, т. Е.

case1: [a,b] case2: [c,d] and check a <= d and c <= b

Цель состояла бы в том, чтобы определить случаи на основе условий, а на выходе было бы указано, какие случаи перекрываются друг с другом, чтобы я мог переопределить.

Однако я не уверен, как расширить лог c до пересечения условий и кодировать его в R. TIA

Пример кода: Это Таблица предоставляет условия для оператора case

structure(list(Case = c(1, 2, 3, 4, 5, 6), x_lower = c(9, 1, 
9, 3, 3, 1), x_upper = c(10, 2, 10, 5, 6, 2), y_lower = c(9, 
1, 1, 4, 4, 1), y_upper = c(10, 2, 2, 6, 7, 2), z_lower = c(9, 
1, 1, 3, 3, 1), z_upper = c(10, 2, 2, 4, 5, 2), `Overlapping Case` = c(NA, 
NA, NA, NA, NA, NA)), row.names = c(NA, -6L), class = c("tbl_df", 
"tbl", "data.frame"))

некоторые данные для проверки logi c, Case2 и Case6 всегда будут перекрываться, и я считаю, что Case4 всегда содержится в Case5

library(tidyverse)
set.seed(10)
dat=data.frame(x=sample(1:10,size=1000,replace=TRUE),y=sample(1:10,size=1000,replace=TRUE),
               z=sample(1:10,size=1000,replace=TRUE)) %>% 
 mutate(Case= case_when( between(x,9,10) & between(y,9,10) & between(z,9,10)~ "Case1",
             between(x,1,2) & between(y,1,2) & between(z,1,2)~"Case2",
             between(x,9,10) & between(y,1,2) & between(z,1,2)~"Case3",
             between(x,3,5) & between(y,4,6) & between(z,3,4)~"Case4",
             between(x,3,6) & between(y,4,7) & between(z,3,5)~"Case5",
             between(x,1,2) & between(y,1,2) & between(z,1,2)~"Case6",
             TRUE ~ "Other"))

1 Ответ

0 голосов
/ 17 апреля 2020

Вот один способ (из многих), который вы могли бы go об этом. Комментарии чередуются ниже.

# given structure stored as "df"

#-----------

# Establish the overlap() function. This function takes as input
# two rows from df and outputs a logical indicator of overlap
overlap <- function(a, b){
  a <- unlist(a)   # flatten these into vectors for use in apply() later
  b <- unlist(b)
  all(a["x_lower"] <= b["x_upper"], b["x_lower"] <= a["x_upper"],
      a["y_lower"] <= b["y_upper"], b["y_lower"] <= a["y_upper"],
      a["z_lower"] <= b["z_upper"], b["z_lower"] <= a["z_upper"])
}

# testing the new function
overlap(temp[4, ], temp[5, ])
  ## [1] TRUE
overlap(temp[2, ], temp[5, ])
  ## [1] FALSE
overlap(temp[2, ], temp[6, ])
  ## [1] TRUE

#-----------

# Define the check_other_rows() function, which takes as input
# a number of a row in df and produces as output a comma-separated
# string (possibly empty) of matching rows
check_other_rows <- Vectorize(function(i){
  apply(df, 1, overlap, b = temp[i, ]) %>% 
    which %>%          # record which rows had overlap with row i
    setdiff(i) %>%     # remove trivial value of i from list
    paste(sep = ", ")
  }
)

# testing the new function
check_other_rows(1)
  ## [[1]] 
  ## character(0)
check_other_rows(2)
  ## [1] "6"

#-----------

a <- check_other_rows(1:nrow(df))
# this works because we vectorized check_other_rows(), but we need
# to clean up the structure a bit b/c of the empty entries
a[lengths(a) == 0] <- NA_character_
a <- as.character(a)
a
  ## [1] NA  "6" NA  "5" "4" "2"

# store the result into the desired column of df
df$`Overlapping Case` <- a
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...