简体   繁体   English

有条件地使用基于另一列中的值的颜色填充特定列中的单元格

[英]Conditionally fill cells in specific columns with colour based on value in another column

I have the following data frame: 我有以下数据框:

col1 <- rep(c("A","B","C","D"),10)
col2 <- rep(c(1,0),10)
col3 <- rep(c(0,1),10)
col4 <- rep(c(1,0),10)
col5 <- rep(c(0,1),10)

test_df <- data.frame(col1, col2, col3, col4, col5, stringsAsFactors = F)

I would like to color specific row cells across multiple columns based on the values in col1, and also add a vertical line (indicating a limit) between two columns in the table (based on the same value in col1) 我想根据col1中的值为多个列上的特定行单元着色,并在表中的两列之间添加一条垂直线(表示一个限制)(基于col1中的相同值)

For example, if col1 == "A", then i want to color the cells in col2 and col5 grey, in the same row as col1 == A. 例如,如果col1 ==“A”,那么我想为col2和col5灰色的单元格着色,与col1 == A在同一行。

In dummy code: 在虚拟代码中:

if col1 == A: color columns(col2, col5), vert.line between col3 and col4
if col1 == B: color columns(col2, col3, col5), vert.line between col4 and col5
if col1 == C: color columns(col2, col4, col5), vert.line between col3 and col4
if col1 == D: color columns(col2, col5), vert.line between col2 and col3

I would like to specify these rules so they can easily be changed if necessary. 我想指定这些规则,以便在必要时可以轻松更改。

I want to end up with something like this (asterisks indicate cell coloring): 我想最终得到这样的东西(星号表示细胞着色):

col1   col2   col3   col4   col5
A      *1*     0   | 1      *0*
B      *0*    *1*    0    | *1*
C      *1*    *0*  | 1      *0*
D      *0*  |  1     0      *1*
A      *1*     0   | 1      *0*
B      *0*    *1*    0    | *1*
C      *1*    *0*  | 1      *0*
D      *0*  |  1     0      *1*

I am presenting this in a table in a shiny app and markdown document. 我在一个闪亮的应用程序和降价文档的表格中呈现这一点。 Is there any way to do this with f. 有没有办法用f做到这一点。 ex xtable or dplyr? ex xtable还是dplyr?

There is a solution using tableHTML in combination with 2 functions to replicate the logic. 有一个解决方案使用tableHTML结合2个函数来复制逻辑。

First, you need to create css for each column that provides the styling information that should be applied to the table. 首先,您需要为每个列创建css,以提供应该应用于表的样式信息。 I have split it into 2 functions, one for the background, and one for the line between columns. 我把它分成2个函数,一个用于背景,一个用于列之间的行。

library(tableHTML)

The first function changes the colour of cells based on the value in col1 . 第一个函数根据col1的值更改单元格的颜色。 You can change them by providing different colours in the arguments of the function. 您可以通过在函数的参数中提供不同的颜色来更改它们。

get_background_column_css <- function(col1,
                                   a_col = "lightgray",
                                   b_col = "steelblue",
                                   c_col = "lightgreen",
                                   d_col = "indianred",
                                   default = "white") {
  # create css for col2
  background_color_col2 <- ifelse(col1 == "A", a_col, 
                      ifelse(col1 == "B", b_col,
                      ifelse(col1 == "C", c_col,
                      ifelse(col1 == "D", d_col, default
                             ))))
  css_col2 <- setNames(list(list(c("background-color"),
                     list(background_color_col2))), "col2")

  # create css for col3
  background_color_col3 <- ifelse(col1 == "B", b_col,
                                  ifelse(col1 == "C", c_col, default))
  css_col3 <- setNames(list(list(c("background-color"),
                                 list(background_color_col3))), "col3")
  # create css for col4
  background_color_col4 <- rep("", length(col1))
  css_col4 <- setNames(list(list(c("background-color"),
                                 list(background_color_col4))), "col4")
  # create css for col5
  background_color_col5 <- ifelse(col1 == "A", a_col, 
                                  ifelse(col1 == "B", b_col,
                                         ifelse(col1 == "C", c_col,
                                                ifelse(col1 == "D", d_col, default
                                                ))))
  css_col5 <- setNames(list(list(c("background-color"),
                                 list(background_color_col5))), "col5")

  list(css_col2, css_col3, css_col4, css_col5)
}

The second function adds a border between columns. 第二个函数在列之间添加边框。

get_border_column_css <- function(col1) {
  # create css for col2
  border_col2 <- ifelse(col1 == "D", "1px solid black", "0px")
  css_col2 <- setNames(list(list(c("border-right"),
                                 list(border_col2))), "col2")
  # create css for col3
  border_col3 <- ifelse(col1 == "C", "1px solid black", "0px")
  css_col3 <- setNames(list(list(c("border-right"),
                                 list(border_col3))), "col3")
  # create css for col4
  border_col4 <- ifelse(col1 == "B", "1px solid black", "0px")
  css_col4 <- setNames(list(list(c("border-right"),
                                 list(border_col4))), "col4")
  # create css for col5
  border_col5 <- rep("0px", length(col1))
  css_col5 <- setNames(list(list(c("border-right"),
                                 list(border_col5))), "col5")

  list(css_col2, css_col3, css_col4, css_col5)
}

In order to test the function, I only use the first 4 rows (since they have all the combinations of possibilities): 为了测试函数,我只使用前4行(因为它们具有所有可能性的组合):

test_df <- head(test_df, 4)

Next, I create 1 css list for the background-color and 1 css list for the border that can be supplied to add_css_conditional_column() 接下来,我为background-color创建1个css列表,为可以提供给add_css_conditional_column()border创建1个css列表

css_background = get_background_column_css(test_df$col1)
css_border = get_border_column_css(test_df$col1)

Next, I create a tableHTML object. 接下来,我创建一个tableHTML对象。

tableHTML <- tableHTML(test_df,
                       rownames = FALSE,
                       border = 0) 

Next, I add the background css in a loop to each column: 接下来,我将循环中的背景css添加到每个列:

for (i in 1:4) {
  tableHTML <- tableHTML %>%
    add_css_conditional_column(conditional = "colour_rank",
                               colour_rank_css = css_background[[i]],
                               columns = names(test_df)[i + 1])
}

And the border css: 边境css:

for (i in 1:4) {
  tableHTML <- tableHTML %>%
    add_css_conditional_column(conditional = "colour_rank",
                               colour_rank_css = css_border[[i]],
                               columns = names(test_df)[i + 1])
}

This is the result: 这是结果:

tableHTML

产量

Here is a partial (doesn't do the custom line separation between columns) solution. 这是一个部分(不做列之间的自定义行分隔)解决方案。

For the following, I leverage the package formattable . 对于以下内容,我利用了包formattable

The dataframe used is df as defined in your question. 使用的数据框是df如您的问题中所定义。

library(formattable)
library(dplyr)

## Function that create the formula for the coloring of each row
## You could also personalize the color
color_row <- function(r,
                      c,
                      color = 'gray') {

  return(area(row = r, col = c) ~ color_tile(color, color))
}

## Create database that containes info on coloring pattern
df_color <- data_frame(col1 = c('A', 'B', 'C', 'D'),
                       limits = list(c(2,5), c(2,3,5), c(2,4,5), c(2,5)))


## Join it to original data.frame
df_join <- df %>% left_join(df_color) 

## Create list with all the appropriate formulas to color data frame
format_list <- mapply(color_row, r = 1:nrow(df), c = df_join$limits, color = 'gray')

## Pass it to formattable
df_final <- formattable(df,format_list) 

The result looks like this: 结果如下: 在此输入图像描述

This can be easily used in RNotebook and Shiny. 这可以很容易地用在RNotebook和Shiny中。 Following example codes for each (for the code below to work, you need the result of the previous code df_final to be in your environment): 下面是每个示例代码(为了使下面的代码工作,您需要将以前的代码df_final的结果放在您的环境中):

---
title: "R Notebook"
output: html_notebook
---

```{r}
library(dplyr)
library(formattable)
format_table(df_final)
```

Shiny: 闪亮:

library(shiny)
library(formattable)
  # table example
  shinyApp(
    ui = fluidPage(
      fluidRow(
        column(12,
               formattableOutput('table')
        )
      )
    ),

    server = function(input, output) {


      output$table <- renderFormattable(df_final)
    }
  )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM