Как найти все возможные комбинации уникальных пересечений векторов между несколькими (6) векторами разной длины в R

У меня есть набор из 6 векторов разной длины (имена столбцов: tp1-tp6). Выглядит примерно так:

    tp1     tp2     tp3     tp4     tp5     tp6
    K06167  K14521  K17095  K21805  K03238  K18213
    K07376  K17095  K01424  K13116  K03283  K14521
    K03347  K14521  K14319  K00799  K08901  K01756
    K20179  K01693  K01682  K03283  K02716  K03238
    K03527  K02882  K01414  K01693  K08907  K01850
    K08901  K02912  K00940  K14319  K00411  K01768
    K11481  K02868  K04043  K14835  K01414  K15335
    K02716  K14835  K12606  K19371  K00963  K12818
    K03545  K14766  K09550  K04043  K01749  K02975
    K08907  K00602  K15437  K09550  K03116  K03002
    K15470  K10798  K03456  K03687  K09550  K17679
    K16465  K14823  K18059  K03456  K08738  K13116
    K03116  K00940  K03115  K18534  K08907  K14521
    K08738  K16474  K15502  K03495  K03687  K01937
    K08907  K19371  K00026  K13100  K08907  K03002
    .
    .
    .

Я хотел бы создать список, содержащий все соответствующие значения K, соответствующие каждой возможной комбинации 6 векторов. Например, для комбинации tp2 и tp3 я хочу найти все значения, которые у двух векторов являются общими, но не появляются ни в одном из других векторов (tp1, tp4, tp5, tp6). В данном случае это будет K00940. Возможно ли это с векторами разной длины в R?

Аналогичный вопрос был задан в

Поиск всех возможных комбинаций пересечений векторов?

и я попробовал один из кодов, приведенных в ответах. Хотя код дает мне все возможные комбинации и их соответствующие значения в большом списке, он не учитывает то обстоятельство, что мне нужны только уникальные пересечения между разными векторами. Например, комбинация tp2 и tp3 дала мне все возможные значения, общие для двух векторов, но включала значения, которые присутствовали в других векторах, которые также присутствовали в tp2 и tp3. Мне просто нужны уникальные значения, общие только для tp2 и tp3.

veclist <- list(tp1, tp2, tp3, tp4, tp5, tp6) 

combos <- Reduce(c,lapply(1:length(veclist), function(x) combn(1:length(veclist),x,simplify=FALSE)))

CKUP_combos <- lapply(combos, function(x) Reduce(intersect, veclist[x]) )

person Johnson Lin    schedule 25.09.2019    source источник


Ответы (2)


Определите следующую функцию:

getUniqueIntersections <- function(veclist, col1name, col2name){
  #Returns vector of all strings in components col1name and col2name of veclist
  # that are not in any of the other components of veclist.

  inc1 <- veclist[[col1name]]
  inc2 <- veclist[[col2name]]
  inc <- intersect(inc1, inc2) 

  excNames <- setdiff(names(veclist), c(col1name, col2name))
  exc <- unique(do.call(c, veclist[excNames]))

  result <- setdiff(inc, exc)

  return(result)
}

Затем определите veclist как именованный список интересующих векторов, а затем используйте эти имена для создания фрейма данных из пар, которые мы хотим перебрать:

veclist <- list(tp1=tp1, tp2=tp2, tp3=tp3, tp4=tp4, tp5=tp5, tp6=tp6)
dfCombNames <- as.data.frame(combn(names(veclist), 2))
dfCombNames
#   V1  V2  V3  V4  V5  V6  V7  V8  V9 V10 V11 V12 V13 V14 V15
#1 tp1 tp1 tp1 tp1 tp1 tp2 tp2 tp2 tp2 tp3 tp3 tp3 tp4 tp4 tp5
#2 tp2 tp3 tp4 tp5 tp6 tp3 tp4 tp5 tp6 tp4 tp5 tp6 tp5 tp6 tp6

Наконец, создайте список результатов, просматривая каждый столбец в dfCombNames.

  • row1 и row2 каждого столбца в dfCombNames объединяются вместе, чтобы сформировать имена ключей компонентов списка, например «тп2, тп3»
  • getUniqueIntersections применяется к значениям в row1 и row2, которые соответствуют рассматриваемым парам столбцов, чтобы получить уникальные значения пересечения для этой пары.
resultList <- list()
for(col in dfCombNames){
  col1 <- as.character(col[1])
  col2 <- as.character(col[2])
  compName <- paste(as.character(col), collapse=",")
  resultList[[compName]] <- getUniqueIntersections(veclist, col1, col2)
}

resultList должен содержать желаемые значения, например,

> resultList[["tp2,tp3"]]
[1] "K17095" "K00940"

> resultList[["tp1,tp5"]]
[1] "K08901" "K02716" "K08907" "K03116" "K08738"
person Ben Wynne-Morris    schedule 25.09.2019
comment
Привет, все работало вплоть до forloop; когда я ввел код resultList [[compName]] ‹- getUniqueIntersections (df, col1, col2), появилось следующее сообщение об ошибке: Ошибка в UseMethod (pull): нет применимого метода для 'pull', примененного к объекту функции класса - person Johnson Lin; 26.09.2019
comment
Теперь изменили код для обработки векторов разной длины. Пожалуйста, проверьте еще раз с новым кодом. - person Ben Wynne-Morris; 26.09.2019
comment
Привет, Бен, ошибка в combn (names (veclist), 2): n ‹m произошла, когда я запустил код dfCombNames‹ - as.data.frame (combn (names (veclist), 2)) - person Johnson Lin; 27.09.2019
comment
Вы сначала определили veclist ‹- list (tp1, tp2, tp3, tp4, tp5, tp6)? - person Ben Wynne-Morris; 28.09.2019
comment
Привет, Бен, да, я сначала определил veclist, но он все равно обнаружил ошибку. - person Johnson Lin; 29.09.2019
comment
Хорошо, мне только что пришло в голову, что я дал имена veclist ... Пожалуйста, попробуйте veclist ‹- list (tp1 = tp1, tp2 = tp2, tp3 = tp3, tp4 = tp4, tp5 = tp5, tp6 = tp6), тогда он будет надеюсь, все работает на вас. - person Ben Wynne-Morris; 30.09.2019
comment
Привет, я попробовал новый код, и теперь ошибка Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,: arguments подразумевают разное количество строк: 118, 99, 87, 513, когда я запускал resultList [[compName]] ‹- getUniqueIntersections (veclistUP, col1, col2) Как вы думаете, это, вероятно, результат того факта, что у меня есть векторы разной длины? Как мне исправить это ? Спасибо! - person Johnson Lin; 30.09.2019
comment
Код должен обрабатывать векторы разной длины, но убедитесь, что вы используете последнюю версию getUniqueIntersections, а не исходную версию этой функции. - person Ben Wynne-Morris; 30.09.2019
comment
Привет, Бен, я использовал последнюю версию getUniqueIntersections, но по какой-то причине ошибка все еще выскакивает. - person Johnson Lin; 30.09.2019
comment
Я тестировал работу кода на небольших игрушечных примерах, включая векторы разной длины, поэтому должен быть какой-то крайний случай, вызывающий проблему. Что стоит попробовать: (1) Создайте ОЧЕНЬ простого veclist'а и заставьте его работать. Если вы уверены, что это работает для простых случаев, создавайте вещи, добавляя tp1, tp2, .. в свой veclist, чтобы вы могли точно определить, когда он терпит неудачу (2) Попробуйте одну пару перед циклом for, например getUniqueIntersections (veclist, tp1, tp5) (3) Проверяем veclist, чтобы убедиться, что все компоненты списка действительно являются векторами, а не вложенными списками и т.д. - person Ben Wynne-Morris; 01.10.2019

person    schedule
comment
Извините, это не сработало, и я просто вижу NULL в консоли, когда ввожу код. В наборе данных Res просто был список из 6 меньших списков с разной длиной. - person Johnson Lin; 26.09.2019