У меня есть фрейм данных, который выглядит так:
header1 header2 header3 header4 ...
rowname1 1 2 3 4
rowname2 4 3 2 1
rowname3 2 4 1 3
rowname4 1 4 3 2
...
Я хотел бы сделать цветовой градиент в зависимости от значений для каждой строки. Обычно я хотел бы, чтобы максимальное значение каждой строки было окрашено в зеленый цвет, минимальное значение каждой строки окрашено в красный цвет, а другие ячейки постепенно окрашивались в зависимости от их значения (второе худшее было бы оранжевым, второе лучшее было бы желтым и т. д. ...).
Пример того, что я хотел бы получить:
Не могли бы вы помочь мне в решении этого вопроса?
и, возможно, еще несколько альтернативных вариантов здесь
Вот возможность с DT
.
dat <- data.frame(
V1 = rpois(6,5),
V2 = rpois(6,5),
V3 = rpois(6,5),
V4 = rpois(6,5),
V5 = rpois(6,5),
V6 = rpois(6,5)
)
library(DT)
js <- c(
"function(row, data, num, index){",
" data.shift();", # remove row name
" var min = Math.min.apply(null, data);",
" var max = Math.max.apply(null, data);",
" for(var i=0; i<data.length; i++){",
" var f = (data[i] - min)/(max-min);",
" var h = 120*f;",
" var color = 'hsl(' + h + ', 100%, 50%)';",
" $('td:eq('+(i+1)+')', row).css('background-color', color);",
" }",
"}"
)
datatable(dat, options = list(rowCallback = JS(js)))
Чтобы добавить черные границы, выполните
datatable(dat, options = list(rowCallback = JS(js))) %>%
formatStyle(1:(ncol(dat)-1), `border-right` = "solid 1px")
Приведенное выше решение предполагает, что вы отображаете имена строк в таблице. Если вы не хотите отображать имена строк, выполните следующие действия:
js <- c(
"function(row, data, num, index){",
" var min = Math.min.apply(null, data);",
" var max = Math.max.apply(null, data);",
" for(var i=0; i<data.length; i++){",
" var f = (data[i] - min)/(max-min);",
" var h = 120*f;",
" var color = 'hsl(' + h + ', 100%, 50%)';",
" $('td:eq('+i+')', row).css('background-color', color);",
" }",
"}"
)
datatable(dat, rownames = FALSE, options = list(rowCallback = JS(js)))
По просьбе ОП в чате, вот вариант. Вместо генерации цвета, пропорционального значению ячейки, он генерирует цвет, пропорциональный рангу значения ячейки.
js <- c(
"function(row, data, num, index){",
" data.shift();", # remove row name
" var data_uniq = data.filter(function(item, index) {",
" if (data.indexOf(item) == index){",
" return item;",
" }}).sort(function(a,b){return a-b});",
" var n = data_uniq.length;",
" var ranks = data.slice().map(function(v){ return data_uniq.indexOf(v) });",
" for(var i=0; i<data.length; i++){",
" var f = ranks[i]/(n-1);",
" var h = 120*f;",
" var color = 'hsl(' + h + ', 100%, 50%)';",
" $('td:eq('+(i+1)+')', row).css('background-color', color);",
" }",
"}"
)
dat <- as.data.frame(matrix(round(rnorm(24),2), ncol=8))
datatable(dat, options = list(rowCallback = JS(js)))
Я обнаружил, что цвета стали более отчетливыми, заменив var h = 120*f;
на
var h = 60*(1 + Math.tan(2*f-1)/Math.tan(1));
Спасибо за Ваш ответ. Я попробовал это с моим фреймом данных, и он создает таблицу данных, как у вас ... но без цвета. У вас есть идеи, почему?
@ValentinDubois В вашем фрейме данных есть только числовые значения? И есть ли пропущенные значения?
Только числовые значения и никаких пропущенных значений, или я так думаю. Обновлено: на самом деле кажется, что значения по какой-то причине не являются числовыми, и мы решим эту проблему.
Итак, теперь у меня есть цвета, но кажется, что цвета применяются ко всему набору значений, а не только к каждой строке.
Хорошо, я думаю, что это не работает из-за нечисловых имен строк. Я не уверен, что понимаю код «js», но я думаю, что он требует числового аргумента для «строки», верно?
@ValentinDubois Аааа, да, извините. Аргумент data
соответствует одной строке. Действительно, имя строки является первым компонентом, и в этом проблема. Позвольте мне попытаться исправить это.
@ValentinDubois Я обновил js
. Не могли бы вы попробовать, пожалуйста? Теперь код должен принимать имена строк символов (data.shift()
удаляет первый компонент, то есть имя строки).
Большое спасибо, на этот раз все работает отлично! Извините, что злоупотребляю вашими знаниями, но не могли бы вы также добавить черные рамки для каждой ячейки, чтобы мы могли различать их? (особенно зеленые клетки, которые трудно отличить друг от друга). Спасибо большое за вашу помощь в любом случае!
Давайте продолжить обсуждение в чате.
Вы можете использовать пакет
kableExtra
. Здесь — отличное руководство.