Объединить две строки с одинаковым идентификатором в 0,1,2 из наличия / отсутствия - PullRequest
0 голосов
/ 14 мая 2019

Я пытаюсь записать исходную таблицу с SNP ID в строках и Sample ID в столбцах.

Пока мне удалось преобразовать данные в присутствие / отсутствие только с 0 и 1.

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

Оригинальная таблица выглядит следующим образом

snpID   Cal_X1  Cal_X2  Cal_X3  Cal_X4  Cal_X5  Cal_X6  Cal_X7  Cal_X8
A_001   0   1   1   1   0   0   1   0
A_001   0   0   1   0   1   0   1   1
A_002   1   1   0   1   1   1   0   0
A_002   0   1   1   0   1   0   1   1
A_003   1   0   0   1   0   1   1   0
A_003   1   1   0   1   1   0   0   1
A_004   0   0   1   0   0   1   0   0
A_004   1   0   0   1   0   1   1   0

Я бы хотел записать оценки в 0/0 = NA, 0/1 = 0, 1/1 = 2, 1/0 = 1, чтобы продукт выглядел примерно так.

snpID   Cal_X1  Cal_X2  Cal_X3  Cal_X4  Cal_X5  Cal_X6  Cal_X7  Cal_X8
A_001   NA         1       2       1       0       NA      2      0
A_002   1          2       0       1       2       1       0      0
A_003   2          0       NA      2       0       1       1      0
A_004   0          NA      1       0       NA      2       0      NA

Это всего лишь пример. Мой snpID составляет ~ 96000, а общий столбец ID составляет ~ 500.

Буду очень признателен за помощь в написании этого кода.

Ответы [ 2 ]

1 голос
/ 14 мая 2019

Вот несколько примеров на основе dplyr, каждый из которых работает в одном канале и получает одинаковый вывод.Основным первым шагом является группировка по вашему идентификатору, затем сверните все столбцы с помощью /.Затем вы можете использовать mutate_at для выбора всех столбцов, которые начинаются с Cal_ - это может быть полезно, если у вас есть другие столбцы, кроме идентификатора, с которым вы не хотите выполнить эту операцию.

Первый метод - это case_when:

library(dplyr)

dat %>%
  group_by(snpID) %>%
  summarise_all(paste, collapse = "/") %>%
  mutate_at(vars(starts_with("Cal_")), ~case_when(
    . == "0/1" ~ 0,
    . == "1/1" ~ 2,
    . == "1/0" ~ 1,
    TRUE ~ NA_real_
  ))
#> # A tibble: 4 x 9
#>   snpID Cal_X1 Cal_X2 Cal_X3 Cal_X4 Cal_X5 Cal_X6 Cal_X7 Cal_X8
#>   <chr>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
#> 1 A_001     NA      1      2      1      0     NA      2      0
#> 2 A_002      1      2      0      1      2      1      0      0
#> 3 A_003      2      0     NA      2      0      1      1      0
#> 4 A_004      0     NA      1      0     NA      2      0     NA

Однако (по моему мнению) case_when немного сложно читать, и это не демонстрирует его реальную силу, котораявыполнение if / else для проверки нескольких переменных.Лучше всего подходит для проверок по одной переменной за раз: dplyr::recode:

dat %>%
  group_by(snpID) %>%
  summarise_all(paste, collapse = "/") %>%
  mutate_at(vars(starts_with("Cal_")), 
            ~recode(., 
                    "0/1" = 0,
                    "1/1" = 2,
                    "1/0" = 1,
                    "0/0" = NA_real_))
# same output as above

Или, для большей гибкости и удобочитаемости, создайте небольшой объект поиска.Таким образом, вы можете повторно использовать логику перекодирования и легко ее изменить.recode принимает набор именованных аргументов;используя tidyeval, вы можете передать именованный вектор и удалить его с помощью !!! (аналогичный пример есть в recode документах):

lookup <- c("0/1" = 0, "1/1" = 2, "1/0" = 1, "0/0" = NA_real_)

dat %>%
  group_by(snpID) %>%
  summarise_all(paste, collapse = "/") %>%
  mutate_at(vars(starts_with("Cal_")), recode, !!!lookup)
# same output
0 голосов
/ 14 мая 2019

Вы можете использовать aggregate для объединения значений для каждого snpID, а затем заменить значения в соответствии с вашими потребностями с помощью case_when из dplyr.

(out <- aggregate(.~ snpID, dat, toString))
#  snpID Cal_X1 Cal_X2 Cal_X3 Cal_X4 Cal_X5 Cal_X6 Cal_X7 Cal_X8
#1 A_001   0, 0   1, 0   1, 1   1, 0   0, 1   0, 0   1, 1   0, 1
#2 A_002   1, 0   1, 1   0, 1   1, 0   1, 1   1, 0   0, 1   0, 1
#3 A_003   1, 1   0, 1   0, 0   1, 1   0, 1   1, 0   1, 0   0, 1
#4 A_004   0, 1   0, 0   1, 0   0, 1   0, 0   1, 1   0, 1   0, 0

Теперь перекодировать столбцы

library(dplyr)
out[-1] <- case_when(out[-1] == "0, 0" ~ NA_integer_,
                     out[-1] == "0, 1" ~ 0L,
                     out[-1] == "1, 0" ~ 1L,
                     TRUE ~ 2L)

Результат

out
#  snpID Cal_X1 Cal_X2 Cal_X3 Cal_X4 Cal_X5 Cal_X6 Cal_X7 Cal_X8
#1 A_001     NA      1      2      1      0     NA      2      0
#2 A_002      1      2      0      1      2      1      0      0
#3 A_003      2      0     NA      2      0      1      1      0
#4 A_004      0     NA      1      0     NA      2      0     NA

данные

dat <- structure(list(snpID = c("A_001", "A_001", "A_002", "A_002", 
"A_003", "A_003", "A_004", "A_004"), Cal_X1 = c(0L, 0L, 1L, 0L, 
1L, 1L, 0L, 1L), Cal_X2 = c(1L, 0L, 1L, 1L, 0L, 1L, 0L, 0L), 
    Cal_X3 = c(1L, 1L, 0L, 1L, 0L, 0L, 1L, 0L), Cal_X4 = c(1L, 
    0L, 1L, 0L, 1L, 1L, 0L, 1L), Cal_X5 = c(0L, 1L, 1L, 1L, 0L, 
    1L, 0L, 0L), Cal_X6 = c(0L, 0L, 1L, 0L, 1L, 0L, 1L, 1L), 
    Cal_X7 = c(1L, 1L, 0L, 1L, 1L, 0L, 0L, 1L), Cal_X8 = c(0L, 
    1L, 0L, 1L, 0L, 1L, 0L, 0L)), .Names = c("snpID", "Cal_X1", 
"Cal_X2", "Cal_X3", "Cal_X4", "Cal_X5", "Cal_X6", "Cal_X7", "Cal_X8"
), class = "data.frame", row.names = c(NA, -8L))
...