Рецепты

Условное форматирование в R:Shiny

Сегодня сложная тема.

Для начала обрисую проблему. Есть отчет в Экселе, который надо делать каждый час – и рассылать по почте. Сделать в Экселе – оно конечно автоматизировано, и все такое – но рассылать по почте и захламлять всем почту надоело. Сделал отчет в Shiny, захостил у себя на компьютере – дал по списку получателей адрес IP:Port где крутится этот отчет и забыл про него. Решение выглядело именно так.

Но…

Сам отчет конечно, после долгого изучения фреймворков Shiny и ShinyDashboard труда сделать не представляло…
Вот только была некая графическая «вишенка на торте» в Экселе, реализовать которую в Shiny не получалось очень долго.
Нда, интрига не удалась – спойлер в самом названии этого поста. Да, условное форматирование как в Экселе не мог придумать как сделать…

Но в итоге получилось.

Итак, у нас есть отчет. Филиалы – продажи в штуках понедельно. Понятно, что приведенные данные синтетические и упрощенные. Условное форматирование наложено на каждую строчку индивидуально.

Бизнес-задача такого отчета – оценить на длительном периоде понедельную динамику на всем поле филиалов, найти те, у кого в данный момент дела не очень – «надавать по башке». Так как условное форматирование наложено на каждый филиал – то цветовым кодированием задаются относительные значения отгрузок. То есть, быстро взглянув на огромную простыню – можно увидеть красные пятна и понять – «задница порылась именно тут».

Возвращаемся к R.
Загрузим библиотеки и создадим наши данные.

library(shiny)
library(DT)
exampleDF <- data.frame(
name=c('Волгоград', 'Самара', 'Якутск'),
week1=c(23, 28, 36),
week2=c(25, 24, 72),
week3=c(32, 29, 66),
week4=c(31, 24, 48)
)

Дальше пойдет уже R-код, в понятиях фреймворка Shiny. Описывать его целиком – это дело толстенных книжек, поэтому не буду – кому очень надо сам выучит (2 недели с неплохим английским). Хочу сказать, что скопировав этот код, даже ничего не понимая к себе – он будет работать, может быть разберетесь J

Выведем получившийся DataFrame в отчет:

ui <- dataTableOutput("table_ex")
server <- function(input, output) {
output$table_ex <- renderDataTable({datatable(exampleDF)})
}
app<-shinyApp(ui, server)
runApp(app)

Вот результат:

Ну что сказать ? «Чистенько, но бедновато» (С)

То есть, отчет как будто есть, а полезность для нормальной работы его не особо. Именно потому, что нет условного форматирования. Как я бился, как искал, пробовал различные варианты вывода в приложение Shiny датафреймов. Ничего не помогало. Практически весь буржуйский StackOverflow перерыл. Решения в лоб, как всегда находилось для R, на этот раз не получилось. Опять рыл, читал, думал, искал. Чуть не выучил JavaScript даже. Но что-то у меня в мозгах замкнуло и я увидел в пакете/библиотеке JS DT (datatable) возможность выводить html код в ячейку таблицы. Немножко подумал, поэкспериментировал с принципами построения html-таблиц и у меня получилось. Только пришлось красить цвет шрифта а не фона – так получается как то информативнее для меня, особенно на больших таблицах и появляется возможность сделать темный фон всего отчета.
Итак, заменим функцию server:

server <- function(input, output) {
rbPal <- colorRampPalette(c('red','darkorange','darkgreen'))
for (i in 1:(nrow(exampleDF)))
{
val<-as.numeric(exampleDF[i,2:5])
Col<- rbPal(11)[round((val-min(val))/((max(val)-min(val))/10),digits = 0)+1]
exampleDF[i,2]<-paste0('<span style="color:',Col[1],'; display: block; text-align: right;">', exampleDF[i,2], '</span>')
exampleDF[i,3]<-paste0('<span style="color:',Col[2],'; display: block; text-align: right;">', exampleDF[i,3], '</span>')
exampleDF[i,4]<-paste0('<span style="color:',Col[3],'; display: block; text-align: right;">', exampleDF[i,4], '</span>')
exampleDF[i,5]<-paste0('<span style="color:',Col[4],'; display: block; text-align: right;">', exampleDF[i,5], '</span>')
}
output$table_ex <- renderDataTable({datatable(exampleDF,escape=FALSE)})
}

Тут мы в цикле (ужас для R, знаю) – бежим по каждой строчке, берем из нее вектор значений, создаем вектор цветов из заранее созданной палитры rbPal (красный-желтый-зеленый), и потом в ячейку таблицы вместо значения заносим HTML строку <span>, в которой и прописывается и само значение, и его цвет.

Результат вот такой:

Что и требовалось, и всех устраивает.

Условное форматирование в R:Shiny: 2 комментария

Добавить комментарий