Как создать вектор из общих элементов в векторах R

У меня есть несколько векторов символов генов, содержащих названия видов, в которых они обнаружены, и я сделал график UpSetR, чтобы показать количество видов, общих для разных генов. Теперь я хотел бы сделать обратное: нанести на график количество общих генов по видам, но я не знаю, как это сделать.

Пример того, что у меня есть:

gene1 <- c("Panda", "Dog", "Chicken")
gene2 <- c("Human", "Panda", "Dog")
gene3 <- c("Human", "Panda", "Chicken")  
...#About 20+ genes with 100+ species each

Пример того, что я хотел бы получить в результате:

Panda <- c("gene1", "gene2", "gene3")
Dog <- c("gene1", "gene2")
Human <- c("gene2", "gene3")
Chicken <- c("gene1", "gene3")
...  

Я знаю, что это концептуально просто, но логистически сложнее. Кто-нибудь может дать мне подсказку?

Спасибо!

5 ответов

Решение

Ты можешь использовать unstack от базы R:

unstack(stack(mget(ls(pattern="gene"))),ind~values)
$Chicken
[1] "gene1" "gene3"

$Dog
[1] "gene1" "gene2"

$Human
[1] "gene2" "gene3"

$Panda
[1] "gene1" "gene2" "gene3"

Вы можете в конечном итоге перечислить это в окружающую среду, list2env функция

Сломать:

 l = mget(ls(pattern="gene"))#get all the genes in a list
 m = unstack(stack(l),ind~values)# Stack them, then unstack with the required formula
 m
$Chicken
[1] "gene1" "gene3"

$Dog
[1] "gene1" "gene2"

$Human
[1] "gene2" "gene3"

$Panda
[1] "gene1" "gene2" "gene3"

 list2env(m,.GlobalEnv)
 Dog
 [1] "gene1" "gene2"

Прежде всего я думаю, что для большинства целей лучше хранить gene векторы в списке, как в

genes <- list(gene1 = gene1, gene2 = gene2, gene3 = gene3)

Тогда один базовый подход R будет

genes.v <- unlist(genes)
names(genes.v) <- rep(names(genes), times = lengths(genes))
species <- lapply(unique(genes.v), function(g) names(genes.v)[g == genes.v])
names(species) <- unique(genes.v)
species
# $Panda
# [1] "gene1" "gene2" "gene3"
#
# $Dog
# [1] "gene1" "gene2"
#
# $Chicken
# [1] "gene1" "gene3"
#
# $Human
# [1] "gene2" "gene3"

genes.v является названным вектором всех видов с генами, являющимися их названиями. Тем не менее, когда виды имеют то же самое, например, gene1то эти имена gene11 а также gene12, Это то, что я исправляю во второй строке. Затем в третьей строке я перехожу по всем видам и создаю результирующий список, за исключением того, что в четвертой строке я добавляю названия видов.

Поместите данные в список, для начала. Это облегчает работу.

genes <- list(
    gene1 = c("Panda", "Dog", "Chicken"),
    gene2 = c("Human", "Panda", "Dog"),
    gene3 = c("Human", "Panda", "Chicken")
)

Тогда мы можем получить названия видов оттуда.

species <- unique(unlist(genes))

С этими данными

> species
[1] "Panda"   "Dog"     "Chicken" "Human" 

Для каждого из них мы хотим проверить, содержится ли имя в гене. Это работа для Map (или его двоюродный брат lapply, но мне нравится Map):

get_genes_for_species <- function(s) {
    contained <- unlist(Map(function(gene) s %in% gene, genes))
    names(genes)[contained]
}
genes_per_species <- Map(get_genes_for_species, species)

Теперь у вас есть список списков, один список для каждого вида, содержащий гены, найденные в этом виде.

> genes_per_species
$Panda
[1] "gene1" "gene2" "gene3"

$Dog
[1] "gene1" "gene2"

$Chicken
[1] "gene1" "gene3"

$Human
[1] "gene2" "gene3"

Вы можете попробовать это.

gene  <-unique(c(gene1,gene2,gene3))
TF    <-data.frame(Species = gene)

TF$gene1 <- gene%in%gene1
TF$gene2 <- gene%in%gene2
TF$gene3 <- gene%in%gene3

> TF
  Species gene1 gene2 gene3
1   Panda  TRUE  TRUE  TRUE
2     Dog  TRUE  TRUE FALSE
3 Chicken  TRUE FALSE  TRUE
4   Human FALSE  TRUE  TRUE

Вот вариант, который охватывает тиверсайд и помещает результат в аккуратный фрейм данных.

Хитрость заключается в том, чтобы объединить результаты с str_c а также summarise,

   tibble(gene1 = gene1, 
          gene2 = gene2, 
          gene3 = gene3) %>% 
   gather(gene_name, gene_type) %>% 
   group_by(gene_type) %>% 
   summarise(genes = str_c(gene_name, collapse = ", "))

# A tibble: 4 x 2
  gene_type genes              
  <chr>     <chr>              
1 Chicken   gene1, gene3       
2 Dog       gene1, gene2       
3 Human     gene2, gene3       
4 Panda     gene1, gene2, gene3

Я согласен с Юлиусом (выше), что лучший способ хранить генные векторы - это список. Именованный список будет еще лучше, так как:

my_gene_list <- set_names(list(gene1, gene2, gene3), str_c("gene", 1:3) ) 

Это аккуратно дало бы тот же результат...

 my_gene_list %>% as_tibble() %>% 
   gather(gene_name, gene_type) %>% 
   group_by(gene_type) %>% 
   summarise(genes = str_c(gene_name, collapse = ", "))

# A tibble: 4 x 2
  gene_type genes              
  <chr>     <chr>              
1 Chicken   gene1, gene3       
2 Dog       gene1, gene2       
3 Human     gene2, gene3       
4 Panda     gene1, gene2, gene3
Другие вопросы по тегам