Вопрос или проблема
У меня есть data.frame в R, который содержит парные комбинации идентификаторов генетических последовательностей, сгруппированные по названиям кластеров. Список пар был дедублицирован, и нет самосравнений. Я пытаюсь добавить генетическое расстояние для каждой пары, которое доступно в таблице базы данных Microsoft SQL server, где также есть два столбца идентификаторов. У меня есть строго доступ к базе данных только для чтения (я не могу писать/создавать таблицы) и я взаимодействую с ней с помощью пакета {dbplyr}
.
Обычно я просто делал бы left_join()
для добавления столбца расстояний, но я не могу это сделать, потому что моя первая таблица с парными идентификаторами находится в среде R, а таблица расстояний на SQL сервере. Таблица расстояний содержит миллионы записей, поэтому импортировать всё это не вариант.
Я могу предоставить список значений для фильтрации, но предоставление моего списка идентификаторов отдельно для Id1
и Id2
недостаточно специфично, так как каждый идентификатор был сопоставлен с каждым другим идентификатором в базе данных, и мне нужны лишь сравнения внутри кластера для конкретной подгруппы кластеров и идентификаторов.
Что мне, кажется, нужно, так это способ фильтрации расстояний, которые мне нужны, из таблицы расстояний на сервере, используя пересечение моих двух списков идентификаторов, но я не знаю, как это сделать. Любые решения с предпочтением dbplyr
(или SQL, но это должно быть решение с фильтрацией) будут очень полезны.
Примечание: я читал несколько постов относительно фильтрации по двум столбцам, но все ответы предполагают какой-то тип соединения, что я не могу сделать, потому что мои таблицы находятся в двух разных местах и у меня нет прав на запись в базе данных.
Вот игрушечный пример моей таблицы с парами идентификаторов:
# Загрузить необходимые библиотеки:
library(DBI)
library(dbplyr)
library(tidyverse)
# Пример data.frame в R, содержащий пары идентификаторов для фильтрации:
idpairs <- data.frame(id = c(1,2,3,4,5,6,7,8,9,10,11,12),
cluster = c(rep("A", 4),
rep("B", 4),
rep("C", 4))) %>%
group_by(cluster) %>%
expand(Id1 = id, Id2 = id) %>%
filter(Id1 < Id2) %>%
ungroup()
Это дает мне следующую таблицу:
> idpairs
# A tibble: 18 × 3
cluster Id1 Id2
<chr> <dbl> <dbl>
1 A 1 2
2 A 1 3
3 A 1 4
4 A 2 3
5 A 2 4
6 A 3 4
7 B 5 6
8 B 5 7
9 B 5 8
10 B 6 7
11 B 6 8
12 B 7 8
13 C 9 10
14 C 9 11
15 C 9 12
16 C 10 11
17 C 10 12
18 C 11 12
Мое соединение с базой данных Microsoft SQL server называется con
и я создал соединение с таблицей расстояний в этой базе данных с помощью dbplyr::tbl()
, которое называется distances_tbl
. Вот как выглядит distances_tbl
:
# Пример таблицы расстояний (эта на сервере):
distances_tbl <- data.frame(
id = sample(seq(6000:7000), size = 100),
Id1 = sample(seq(1:50), size = 100, replace = TRUE),
Id2 = sample(seq(1:50), size = 100, replace = TRUE),
Distance = sample(seq(0:30), size = 100, replace = TRUE)
)
> distances_tbl %>%
+ head(n = 10)
id Id1 Id2 Distance
1 477 31 34 23
2 261 36 17 14
3 132 47 34 8
4 184 31 36 19
5 24 7 35 19
6 47 27 5 27
7 759 17 38 18
8 670 21 37 19
9 145 12 38 3
10 29 42 14 30
Вы можете видеть в таблице, что много сравнений не подходят мне – либо потому, что они сравнивают идентификаторы, которые вообще не находятся в моем наборе данных, либо один из идентификаторов есть в моих данных, но он парен с другим идентификатором, который не есть в них. Например:
- 1 и 3 актуально (оба идентификатора находятся в моих данных, корректное сравнение, так как оба идентификатора в кластере A)
- 1 и 5 не актуально (оба идентификатора находятся в моих данных, но они в разных кластерах)
- 1 и 37 не актуально (только 1 в моих данных, 37 нет)
Ответ или решение
Для решения вашей задачи по фильтрации и объединению данных из R-окружения с таблицей на SQL сервере, при этом имея только права на чтение, мы можем воспользоваться возможностями пакета dbplyr
. Учитывая, что у вас есть пары идентификаторов в data.frame
и вы хотите извлечь соответствующие расстояния из таблицы на сервере, я предлагаю следующий поэтапный подход.
Шаг 1: Подготовка данных
Для начала убедитесь, что у вас есть data.frame
, из которого мы будем извлекать необходимые пары идентификаторов. Ваш пример уже содержит необходимую информацию:
library(dplyr)
library(dbplyr)
# Пример данных с парами идентификаторов
idpairs <- data.frame(id = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
cluster = c(rep("A", 4),
rep("B", 4),
rep("C", 4))) %>%
group_by(cluster) %>%
expand(Id1 = id, Id2 = id) %>%
filter(Id1 < Id2) %>%
ungroup()
# Вывод результата
print(idpairs)
Шаг 2: Подключение к SQL и создание объекта таблицы
Убедитесь, что у вас установлено соединение с вашей базой данных SQL и что вы правильно подключили таблицу, содержащую расстояния:
# Создание соединения с базой данных
con <- dbConnect(/* параметры подключения */)
# Подключение к таблице расстояний на SQL сервере
distances_tbl <- tbl(con, "название_таблицы_расстояний")
Шаг 3: Фильтрация данных на сервере
Теперь мы используем функционал dbplyr
для фильтрации нужных записей по идентификаторам, которые находятся в вашем data.frame
:
# Преобразование данных из R в SQL
idpairs_sql <- copy_to(con, idpairs, "idpairs_sql", overwrite = TRUE)
# Фильтрация расстояний в соответствии с идентификаторами из idpairs_sql
filtered_distances <- distances_tbl %>%
inner_join(idpairs_sql, by = c("Id1" = "Id1")) %>%
inner_join(idpairs_sql, by = c("Id2" = "Id2")) %>%
select(Id1, Id2, Distance) %>%
collect()
Шаг 4: Анализ результатов
Теперь у вас есть отфильтрованный data.frame
, содержащий дистанции только для указанных пар идентификаторов:
# Вывод отфильтрованных результатов
print(filtered_distances)
Примечания
-
Используйте оператор
inner_join()
для того, чтобы оставить только те пары идентификаторов, которые присутствуют как вidpairs
, так и в таблице расстояний. Это верный подход для минимизации нагрузки на сервер, так как вы работаете только с данными, которые вам нужны. -
Использование функции
collect()
завершает запрос и загружает результаты в ваш локальныйR
, позволяя вам работать с выведенными данными. -
Если ваш набор данных слишком велик, и вы всё ещё получаете массив данных, есть возможность дальнейшего уменьшения объема, добавляя дополнительные фильтры.
Эта стратегия позволяет эффективно управлять данными, убирая из выборки несоответствующие пары идентификаторов, и работая в рамках возможности вашего доступа к базе данных.