Диаграмма Венна из списка кластеров и сопутствующих факторов

У меня есть входной файл со списком ~ 50000 кластеров и наличием ряда факторов в каждом из них (всего ~ 10 миллионов записей), см. меньший пример ниже:

set.seed(1)
x = paste("cluster-",sample(c(1:100),500,replace=TRUE),sep="")
y = c(
  paste("factor-",sample(c(letters[1:3]),300, replace=TRUE),sep=""),
  paste("factor-",sample(c(letters[1]),100, replace=TRUE),sep=""),
  paste("factor-",sample(c(letters[2]),50, replace=TRUE),sep=""),
  paste("factor-",sample(c(letters[3]),50, replace=TRUE),sep="")
)
data = data.frame(cluster=x,factor=y)

С небольшой помощью другого вопроса я получил круговую диаграмму для совместного возникновения таких факторов, как это:

counts = with(data, table(tapply(factor, cluster, function(x) paste(as.character(sort(unique(x))), collapse='+'))))
pie(counts[counts>1])

Но теперь я хотел бы иметь диаграмму Венна для совпадения факторов. В идеале также таким образом, чтобы можно было принять пороговое значение минимального количества для каждого фактора. Например, диаграмма Венна для различных факторов, так что каждый из них должен присутствовать n>10 в каждом кластере, чтобы его можно было принять во внимание.

Я пытался найти способ подсчета таблиц с помощью агрегата, но не смог заставить его работать.


person 719016    schedule 14.11.2011    source источник
comment
Вы смотрели какой-либо из пакетов R для диаграмм Венна? См. недавний пример Г. Джея. Кернс, использующий библиотеку venneuler, или эта краткая статья в Journal of Stat Software с использованием библиотеки venn (Мердок, 2004 г. ). Если речь идет исключительно о программировании на R, его следует перенести на SO.   -  person Andy W    schedule 14.11.2011
comment
Авилелла, на этот вопрос может не быть ответов, потому что он немного не по теме. Вы могли бы добиться большего успеха на SO, у которого есть активное сообщество пользователей R. Но, пожалуйста, не делайте перекрестных сообщений: просто отметьте вопрос для внимания модератора, если вы хотите, чтобы он был перенесен.   -  person whuber    schedule 15.11.2011
comment
Я пометил это, но пока не вижу, чтобы он был перемещен в SO...   -  person 719016    schedule 16.11.2011
comment
Хммм... Флаг не поднят. Я пришел сюда только потому, что вспомнил об этом. Во всяком случае, здесь мы идем. Я уверен, что вы получите хорошие ответы на SO.   -  person whuber    schedule 16.11.2011
comment
@avilella -- Соответствуют ли приведенные ниже решения всем требованиям? Если вы имеете в виду другой пакет диаграмм Венна и не можете привести данные в соответствующую форму, сообщите мне об этом. Спасибо.   -  person Josh O'Brien    schedule 19.11.2011
comment
Последние 200 элементов y не зависят от начального числа, поэтому не будет ли излишним использовать sample() для их создания? Вместо этого вы могли бы использовать rep, или они должны были быть случайными?   -  person Iterator    schedule 20.11.2011


Ответы (1)


Я предоставил два решения, используя два разных пакета с возможностями диаграммы Венна. Как вы и ожидали, оба включают начальный шаг с использованием функции aggregate().

Я предпочитаю результаты пакета venneuler. Положения меток по умолчанию не идеальны, но вы можете настроить их, взглянув на связанный метод plot (возможно, используя locator() для выбора координат).

Решение 1-е:

Одна из возможностей — использовать venneuler() в пакете venneuler для рисования диаграммы Венна.

library(venneuler)

## Modify the "factor" column, by renaming it and converting
## it to a character vector.
levels(data$factor) <- c("a", "b", "c")
data$factor <- as.character(data$factor)

## FUN is an anonymous function that determines which letters are present
## 2 or more times in the cluster and then pastes them together into 
## strings of a form that venneuler() expects.
##
inter <- aggregate(factor ~ cluster, data=data,
                   FUN = function(X) {
                       tab <- table(X)
                       names <- names(tab[tab>=2])
                       paste(sort(names), collapse="&")
                   })            
## Count how many clusters contain each combination of letters
counts <- table(inter$factor)
counts <- counts[names(counts)!=""]  # To remove groups with <2 of any letter
#  a   a&b a&b&c   a&c     b   b&c     c 
# 19    13    12    14    13     9    12 

## Convert to proportions for venneuler()
ps <- counts/sum(counts)

## Calculate the Venn diagram
vd <- venneuler(c(a=ps[["a"]], b = ps[["b"]], c = ps[["c"]],
                  "a&b" = ps[["a&b"]],
                  "a&c" = ps[["a&c"]],
                  "b&c" = ps[["b&c"]],
                  "a&b&c" = ps[["a&b&c"]]))
## Plot it!
plot(vd)

Несколько замечаний о выборе, который я сделал при написании этого кода:

  • Я изменил названия факторов с "factor-a" на "a". Вы, очевидно, можете изменить это обратно.

  • Я только требовал, чтобы каждый фактор присутствовал> = 2 раза (вместо> 10) для подсчета в каждом кластере. (Это должно было продемонстрировать код с этим небольшим подмножеством ваших данных.)

  • Если вы посмотрите на промежуточный объект counts, вы увидите, что он содержит исходный безымянный элемент. Этот элемент представляет собой количество кластеров, содержащих менее 2 любых букв. Вы можете лучше меня решить, хотите ли вы включить их в расчет последующего объекта ps («пропорции»).

введите здесь описание изображения

Решение второе:

Другая возможность состоит в том, чтобы использовать vennCounts() и vennDiagram() в пакете Bioconductor limma. Чтобы загрузить пакет, следуйте приведенным здесь инструкциям. В отличие от решения venneuler выше, перекрытие в результирующая диаграмма не пропорциональна фактической степени пересечения. Вместо этого он снабжает диаграмму фактическими частотами. (Обратите внимание, что это решение не требует редактирования столбца data$factor.)

library(limma)

out <- aggregate(factor ~ cluster, data=data, FUN=table)
out <- cbind(out[1], data.frame(out[2][[1]]))

counts <- vennCounts(out[, -1] >= 2)
vennDiagram(counts, names = c("Factor A", "Factor B", "Factor C"),
            cex = 1, counts.col = "red")

введите здесь описание изображения

person Josh O'Brien    schedule 17.11.2011