создание тепловой карты, в которой данные содержат значения NaN

Я пытаюсь создать тепловую карту с помощью пакета heatmap.2. В моих данных много значений NaN, и я хотел бы сделать следующее. Каждый раз, когда есть значение NaN, просто сделайте ячейку окрашенной в светло-серый (или какой-либо другой нейтральный цвет, может быть, белый), а все остальные значения (которые являются выражением log2) имеют стандартную зеленую/желтую/красную окраску. схема. Вот мой код, который я использовал:

heatmap.2(as.matrix(foo2[rowSums (abs(foo2)) != 0,]),
          col = redgreen,
          margins = c(12, 22),
          trace = "none", 
          xlab = "Comparison",
          lhei = c(2, 8),
          scale = c("none"),
          symbreaks = min(foo2 = 0, na.rm = TRUE),
          na.color = "blue",
          cexRow = 0.5,
          cexCol = .7,
          main = "DE geness",
          Colv = F)

Это хорошо работает, когда нет значений NaN, но когда данные имеют NaN, я получаю сообщение об ошибке:

Error in hclustfun(distfun(x)) : 
  NA/NaN/Inf in foreign function call (arg 11)

По сути, я хотел бы, чтобы он игнорировал NaN в данных. Я не знаю, как с этим справиться. любая помощь будет принята с благодарностью.


person user1352084    schedule 31.12.2013    source источник
comment
Просто преобразуйте NA в число, выходящее за пределы диапазона других, и укажите разрывы и палитру, которые соответствуют вашим потребностям.   -  person IRTFM    schedule 31.12.2013
comment
Учитывая приведенный ниже ответ о невоспроизводимости, сначала убедитесь, что ваш NaN действительно NaN, а не строки или какой-то другой мусор. Затем убедитесь, что каждая функция, которую вы вызвали внутри вызова heatmap.2, возвращает ожидаемый класс данных. Например, symbreaks=min(foo2 = 0, na.rm=TRUE) — это странный способ проверить, есть ли какие-либо значения 0 в foo2.   -  person Carl Witthoft    schedule 31.12.2013
comment
@BondedDust, преобразование NA в значения (даже в матрице dist) повлияет на кластеризацию.   -  person Zhilong Jia    schedule 18.04.2015


Ответы (5)


TL;DR: проблема, скорее всего, связана с делегированной функцией distfun, а не с самой функцией heatmap2. Функция dist по умолчанию пытается вычислить расстояние между вашими точками данных, и если вычисление расстояния возвращает NA, функция кластеризации не может с этим справиться.


Большая версия:

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

Основная проблема заключается в следующем: Heatmap2 по умолчанию передает hclust и hclustfun и dist как параметры distfun. В сообщении об ошибке четко указано, что hclustfun (которое в данном случае по умолчанию равно hclust) не любит NAs.

Следующий бит информации таков: хотя матрица данных включает NAs, результаты dist (которые передаются в hclust) могут быть свободны от NA, как в случае с ответом @kdauria. Смотри ниже:

> library(gplots)
> mat = matrix( rnorm(25), 5, 5)
> mat[c(1,6,8,11,15,20,22,24)] = NaN
> 
> heatmap.2( mat,
+            col = colorpanel(100,"red","yellow","green"),
+            margins = c(12, 22),
+            trace = "none", 
+            xlab = "Comparison",
+            lhei = c(2, 8),
+            scale = c("none"),
+            symbreaks = min(mat, na.rm=TRUE),
+            na.color="blue",
+            cexRow = 0.5, cexCol = 0.7,
+            main = "DE genes", 
+            dendrogram = "row", 
+            Colv = FALSE )
> ?dist
> mat
           [,1]       [,2]        [,3]        [,4]       [,5]
[1,]        NaN        NaN         NaN -1.10103187 -1.4396185
[2,] -0.8821449  1.4891180  0.41956063 -0.06442867        NaN
[3,] -2.5912928        NaN -0.56603029 -0.55177559 -2.0313602
[4,]  0.8348197  0.2199583  0.06318663  1.59697764        NaN
[5,] -0.2632078 -1.2193110         NaN         NaN  0.8618543
> dist(mat)
         1        2        3        4
2 2.317915                           
3 1.276559 2.623637                  
4 6.032933 3.050821 5.283828         
5 5.146250 4.392798 5.871684 2.862324

Матрица со случайными значениями не воспроизводит проблему, потому что она позволяет избежать этой проблемы. Это подводит меня к вопросу: что нужно, чтобы получить NA от dist?


В моих данных были некоторые чрезмерно большие значения, которые я считал причиной, однако мне удалось воспроизвести проблему, только добавив ряд NA:

> mat = matrix(rnorm(49), 7, 7)
> mat[c(3,17,28, 41)] = mat[c(3,17,28, 41)] * 100000
> mat
              [,1]        [,2]          [,3]          [,4]        [,5]          [,6]       [,7]
[1,] -6.175928e-01  1.68691561 -1.233250e+00 -7.355322e-01 -0.37392178  3.559804e-01  1.7536137
[2,]  6.680429e-01  0.90590237 -1.375424e+00  5.842512e-01 -0.09376548 -3.556098e-01 -1.2926535
[3,] -3.739372e+04 -1.74534887 -2.241643e+05 -2.209226e-01 -0.86769435 -4.590908e-01  1.6306854
[4,] -1.283405e+00  0.20698245  3.635557e-01  3.673208e-01 -0.12339047  1.119922e+00  0.4301094
[5,] -5.430687e-02 -0.75219479  2.609126e+00 -1.340564e-01  0.54016622  2.885021e-01  0.9237946
[6,] -8.395116e-01  0.03675002  2.455545e+00  4.432025e-02 -0.86194910  1.302758e+05  0.6062505
[7,]  1.817036e-01 -1.46137388 -1.853179e+00 -2.177306e+03  2.36763806 -2.273134e+00  1.2440088
> dist(mat)
             1            2            3            4            5            6
2 3.726858e+00                                                                 
3 2.272605e+05 2.272606e+05                                                    
4 2.966078e+00 3.537475e+00 2.272620e+05                                       
5 4.787577e+00 5.039154e+00 2.272644e+05 3.016614e+00                          
6 1.302754e+05 1.302762e+05 2.619559e+05 1.302747e+05 1.302755e+05             
7 2.176576e+03 2.177895e+03 2.272705e+05 2.177679e+03 2.177179e+03 1.302963e+05
> mat = rbind(mat[1:4, ], rep(NA,7), mat[5:6, ])
> mat
              [,1]        [,2]          [,3]        [,4]        [,5]          [,6]       [,7]
[1,] -6.175928e-01  1.68691561 -1.233250e+00 -0.73553223 -0.37392178  3.559804e-01  1.7536137
[2,]  6.680429e-01  0.90590237 -1.375424e+00  0.58425125 -0.09376548 -3.556098e-01 -1.2926535
[3,] -3.739372e+04 -1.74534887 -2.241643e+05 -0.22092261 -0.86769435 -4.590908e-01  1.6306854
[4,] -1.283405e+00  0.20698245  3.635557e-01  0.36732078 -0.12339047  1.119922e+00  0.4301094
[5,]            NA          NA            NA          NA          NA            NA         NA
[6,] -5.430687e-02 -0.75219479  2.609126e+00 -0.13405635  0.54016622  2.885021e-01  0.9237946
[7,] -8.395116e-01  0.03675002  2.455545e+00  0.04432025 -0.86194910  1.302758e+05  0.6062505
> dist(mat)
             1            2            3            4            5            6
2 3.726858e+00                                                                 
3 2.272605e+05 2.272606e+05                                                    
4 2.966078e+00 3.537475e+00 2.272620e+05                                       
5           NA           NA           NA           NA                          
6 4.787577e+00 5.039154e+00 2.272644e+05 3.016614e+00           NA             
7 1.302754e+05 1.302762e+05 2.619559e+05 1.302747e+05           NA 1.302755e+05
> heatmap.2( mat,
+            col = colorpanel(100,"red","yellow","green"),
+            margins = c(12, 22),
+            trace = "none", 
+            xlab = "Comparison",
+            lhei = c(2, 8),
+            scale = c("none"),
+            symbreaks = min(mat, na.rm=TRUE),
+            na.color="blue",
+            cexRow = 0.5, cexCol = 0.7,
+            main = "DE genes", 
+            dendrogram = "row", 
+            Colv = FALSE )
Error in hclustfun(distfun(x)) : 
  NA/NaN/Inf in foreign function call (arg 11)

Однако ситуация, по-видимому, не специфична для случая, когда имеется строка, полностью состоящая из NA. Например:

> mat
              [,1]        [,2]          [,3]       [,4]       [,5]          [,6]       [,7]
[1,]           NaN         NaN           NaN        NaN         NA -7.531027e-01  0.2238252
[2,]  3.210084e-01 -1.55702840  2.777516e-01  0.2176875  1.3310334 -9.621561e-01        NaN
[3,]  1.159837e+05  0.04480172 -1.649482e+04        NaN  2.4748122  8.446133e-01 -0.4240776
[4,] -8.584051e-01         NaN           NaN  1.0557713 -1.0855826 -5.638023e-02 -0.3789979
[5,]            NA          NA -2.539003e-01 -0.4552776  0.3856384            NA         NA
[6,]           NaN  1.31986556           NaN -1.0393147 -1.9197183 -1.434064e+00  0.6334569
[7,]           NaN -0.42180912           NaN -0.8023476 -0.8264077  4.471358e+04  0.5046408
> dist(mat)
             1            2            3            4            5            6
2 5.531033e-01                                                                 
3 3.225471e+00 1.386143e+05                                                    
4 1.723619e+00 3.913983e+00 1.534332e+05                                       
5           NA 1.949799e+00 3.085851e+04 3.945524e+00                          
6 1.486699e+00 6.010961e+00 6.905415e+00 3.743585e+00 4.449179e+00             
7 8.365286e+04 5.915178e+04 5.914939e+04 5.915058e+04 2.358664e+00 5.290752e+04
person posdef    schedule 05.03.2015

Так что я вообще не эксперт в кодировании, но я учился делать тепловые карты на R, и у меня постоянно появлялось одно и то же сообщение об ошибке для моих данных NA. Оказывается, причина, по которой я получил сообщение об ошибке, заключалась в том, что в первом столбце моих данных были термины NA, и R это совсем не понравилось. Поэтому я добавил дополнительный столбец и заполнил его единицами, и это сработало! Я надеюсь, что, возможно, кому-то это будет полезно!

Кахина

person Kahina    schedule 07.12.2017
comment
Вы должны добавить больше деталей к своему ответу. Сколько 1 например. - person Simon; 07.12.2017
comment
Решение @Simon Kahina подразумевает добавление в матрицу одного столбца с одинаковыми значениями. Следовательно, столько 1, сколько строк в матрице. Это решение позволяет вычислить евклидово расстояние между всеми векторами-строками, но добавляет к результирующему рисунку столбец, для которого нет интерпретации. - person 0range; 10.05.2018

Просто предложение для практического решения в дополнение к очень поучительному ответу posdef:

Поскольку distfun используется только для определения структуры дендрограммы, вы можете просто заменить NA в матрице dist значениями, которые немного превышают максимальные значения, не относящиеся к NA.

Для этого нам нужна новая функция расстояния (та, которая оборачивает обычную функцию dist и просто заменяет NA):

dist_no_na <- function(mat) {
    edist <- dist(mat)
    edist[which(is.na(edist))] <- max(edist, na.rm=TRUE) * 1.1 
    return(edist)
}

и используйте эту функцию в вызове Heatmap.2:

heatmap.2(mat, ..., dendrogram="row", Colv="NA", na.color="black", distfun=dist_no_na)

Свойства

Это, конечно, не идеальное решение. Он присваивает числовые значения расстояния парам векторов, для которых нет базы, на которой можно вычислить (евклидово?) расстояние. Тем не менее, у него есть некоторые желательные свойства.

  1. Функция Heatmap.2 работает :-)

  2. Например, строки, которые содержат только NA, сначала отделяются от основной ветки (что хорошо отражает проблему).

  3. Я не совсем уверен, какой эффект имеет замена значений NA, вызванных другими свойствами матрицы. posdef указал, что могут быть такие значения NA. В примере posdef есть две строки, для которых в одном и том же столбце нет пары записей, отличных от NA, т.е. невозможно определить евклидово расстояние. Именно в этом случае, вероятно, все-таки будет уместно отразить это как особо большое расстояние, превышающее все те, которые можно вычислить численно.

Я бы не стал выбирать значение замены, намного превышающее максимальное значение, не относящееся к NA. (Выбранное значение в приведенном выше коде на 10% больше.) Это увеличило бы расстояние от точки разделения строк всех NA до следующих точек разделения (соответствующая часть дендрограммы) и может сделать соответствующие часть дендрограммы трудно увидеть.

person 0range    schedule 10.05.2018

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

Мои данные варьируются от 0 до 114 в матрице данных с большим количеством значений NA, поэтому я сначала заменил все значения NA на -1 (ниже диапазона моего набора данных)

x <- mymatrix %>% replace(is.na(.), -1)

затем я устанавливаю перерывы, используя Heatmap.2(). Если вы хотите, чтобы ваши значения NA были, скажем, «черными», а остальные значения использовали цветовую палитру с диапазоном цветов, установите разрывы с помощью seq(). Поскольку мои данные находятся в диапазоне от 0 до 114, я устанавливаю последовательность от 0 до 114 с шагом 1. Затем с помощью тепловой карты. 2 () я устанавливаю разрывы как -1, а затем мою последовательность (так что разрывы будут выглядеть так ( -1,0,1,2,3..и т.д.) Я устанавливаю цвета "черными" для значений -1 (NA) и использую 114 цветов из сине-красной палитры для остальных значений.

seq <- seq(from = 0, to = 114, by = 1)
heatmap.2(x, col = c("black", bluered(114)), 
      trace = "none", density.info = "none", breaks=c(-1,seq))

Я надеюсь, что это полезно!

person Jana Obajdin    schedule 03.04.2020

Я не могу воспроизвести проблему. Код ниже работает просто отлично. Все значения NaN окрашены в синий цвет.

library(gplots)
mat = matrix( rnorm(25), 5, 5)
mat[c(1,6,8,11,15,20,22,24)] = NaN

heatmap.2( mat,
           col = colorpanel(100,"red","yellow","green"),
           margins = c(12, 22),
           trace = "none", 
           xlab = "Comparison",
           lhei = c(2, 8),
           scale = c("none"),
           symbreaks = min(mat, na.rm=TRUE),
           na.color="blue",
           cexRow = 0.5, cexCol = 0.7,
           main = "DE genes", 
           dendrogram = "row", 
           Colv = FALSE )

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

person kdauria    schedule 31.12.2013
comment
Это кажется немного ошибочным для использования в качестве цветовой палитры, поскольку синий — это просто расширение выбранной вами палитры... Конечно, черный или белый были бы лучшим выбором? - person will; 05.03.2015
comment
Этот пример не отражает случай, который, скорее всего, возникнет у OP, поскольку он не воспроизводит ситуацию, когда dist(mat) включает NAs. Смотрите мой ответ ниже - person posdef; 05.03.2015