Как получить уникальные пары на основе общих значений в двух группирующих переменных?

Я использовал ответ Флориана на этот вопрос, чтобы получить уникальные пары отдельно для одной общей (группирующей) переменной. Можно ли распространить это на случай, когда есть две группирующие переменные, и пары должны быть уникальными на основе любой группирующей переменной?

Например, если входные данные

df  = data.frame(scaffold = c("A", "A", "B", "B", "B", "C", "C", "D","A"), 
       geneID = c("162", "276", "64", "276", "281", "64", "162", "162","64"),
       Grouping2 = c("x1", "x2", "x3", "x1", "x2", "x3", "x1", "x2", "x3"),
       stringsAsFactors = F)

и мои группы — geneID и Grouping2, как мне создать все наборы уникальных пар для scaffold? В этом игрушечном примере A и B пары как на 276, так и на x1, но должна быть создана только одна пара A-B?

Измените, чтобы добавить реальный пример: В моем наборе данных 25 530 человек. Хотя некоторые люди живут одни, более половины живут в семьях (Household), состоящих как минимум из двух человек. Люди также работают/ходят в школу (Work). Каждый человек — это один ряд. Мне нужно найти все уникальные пары людей, имеющие одинаковый Household номер или одинаковое Work имя.

Например, если люди A, B и C живут в 123 Any Street, то пары на основе домохозяйств — это A-B, A-C и B-C. Если B и C оба работают в XYZ Tailoring, где также работают D, E и F, то пары на основе компаний: B-D, B-E, B-F, C-D, CE, C-F, DE, D-F и E-F. Не существует пары BC, основанной на XYZ Tailoring, поскольку она уже учтена в комбинации 123 Any Street.

Данные игрушки:

temp <- data.frame(Person = c("A", "B", "C", "D", "E", "F"),
               Household = c("123 Any Street", "123 Any Street", "123 Any Street", "4 Second Street", "5 Third Street",
                         "6 Last Street"),
               Work = c("One Company", "XYZ Tailoring", "XYZ Tailoring", "XYZ Tailoring", "XYZ Tailoring",
                        "XYZ Tailoring"))

И это моя проблема. Чтобы получить целый набор уникальных пар, поделившись Household или Work.

Редактировать 2: желаемый результат. Кадр данных с двумя переменными (или что-то, что я могу превратить в фрейм данных с двумя переменными, например, матрицу). Вызвав переменные from и to, вы получите 12 уникальных пар. Порядок их не имеет значения.

to    from
A     B
A     C
B     C
B     D
B     E
B     F
C     D
C     E
C     F
D     E
D     F
E     F     

B и C связаны как переменной Household, так и переменной Work. У меня может быть только одна пара B и C, не важно, пары они из Household или пары из Work. Пара C и B не может возникнуть, так как она является зеркальным отражением B и C и, следовательно, является дубликатом.

Я думаю, вам будет легче помочь, если вы включите ожидаемый результат. Возможно, я что-то упускаю, но мне сложно понять, как должен выглядеть результат. Спасибо.

L Tyrone 30.07.2024 07:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вариант tidyverse:

library(dplyr)
library(tidyr)
library(purrr)

df <- data.frame(scaffold = c("A", "A", "B", "B", "B", "C", "C", "D","A"), 
                 geneID = c("162", "276", "64", "276", "281", "64", "162", "162","64"),
                 Grouping2 = c("x1", "x2", "x3", "x1", "x2", "x3", "x1", "x2", "x3"),
                 stringsAsFactors = FALSE)

# summarise() scaffolds as lists, filter() non-matched scaffold values,
# map() unique pairs using combn(), unnest() pairs to individual rows,
# unnest_wider() to individual columns
result <- df |>
  summarise(scaffolds = list(unique(scaffold)), .by = c(geneID, Grouping2)) |>
  filter(lengths(scaffolds) > 1) |>
  mutate(pairs = map(scaffolds, ~ combn(.x, 2, simplify = FALSE))) |>
  unnest(pairs) |>
  unnest_wider(pairs, names_sep = "_")
  
data.frame(result)
#   geneID Grouping2 scaffolds pairs_1 pairs_2
# 1    162        x1      A, C       A       C
# 2     64        x3   B, C, A       B       C
# 3     64        x3   B, C, A       B       A
# 4     64        x3   B, C, A       C       A

На основе обновленного набора данных и желаемого результата вы можете использовать pivot_longer(), чтобы получить перестановки группирующих переменных, суммировать, как и раньше, использовать separate() для разделения пар и присвоения имен столбцов, а затем возвращать только distinct() строк:

temp <- data.frame(Person = c("A", "B", "C", "D", "E", "F"),
                   Household = c("123 Any Street", "123 Any Street", "123 Any Street", "4 Second Street", "5 Third Street",
                                 "6 Last Street"),
                   Work = c("One Company", "XYZ Tailoring", "XYZ Tailoring", "XYZ Tailoring", "XYZ Tailoring",
                            "XYZ Tailoring"))

result <- temp |>
  pivot_longer(-Person) |>
  summarise(tmp = list(unique(Person)), .by = c(name, value)) |>
  filter(lengths(tmp) > 1) |>
  mutate(pairs = map(tmp, ~ combn(.x, 2, simplify = FALSE))) |>
  unnest(pairs) |>
  mutate(pairs = map_chr(pairs, ~ paste(sort(.x), collapse = "-"))) |>
  separate(pairs, into = c("to", "from"), sep = "-") |>
  select("to", "from") |>
  distinct()

result
# # A tibble: 12 × 2
#    to    from 
#    <chr> <chr>
#  1 A     B    
#  2 A     C    
#  3 B     C    
#  4 B     D    
#  5 B     E    
#  6 B     F    
#  7 C     D    
#  8 C     E    
#  9 C     F    
# 10 D     E    
# 11 D     F    
# 12 E     F  

И разбить каждую половину пары на две переменные, например. Scaffold1, Scaffold2 вместо того, чтобы иметь пару в одной переменной (пары)? Например. Scaffold1 = A, B, A, A и Scaffold2 = C, C, B, C

Michelle 30.07.2024 04:47

@Michelle — обновлено с помощью unnest_wider() для разделения столбца пар. Надеюсь это поможет.

L Tyrone 30.07.2024 05:09

Я использовал этот метод для своих данных, а затем понял, что он не работает для моих данных. Здесь я не хочу, чтобы Grouping2 была вложена в GeneID, а чтобы ссылки были основаны на OR. Пример с игрушкой, возможно, слишком игрушечный. Обновлю свой вопрос.

Michelle 30.07.2024 05:47

Это выглядит великолепно, спасибо! Более 774 000 уникальных пар.

Michelle 30.07.2024 13:51

Другие вопросы по теме