0

I have a table with several binary variables. Is it possible to make a table such that all cells with 1s would be black. Like this

this

kath
  • 7,624
  • 17
  • 32
  • 1
    Welcome to SO. This is a very appropriate use of a picture (it conveys the output needs well!). If you are familiar with `ggplot2`, the `geom_tile` and `geom_text` functions can do this. If you provide some data (Read https://stackoverflow.com/tags/r/info and links it provides for how to do that) SO contributors may be able to show you how for your specific case. – hrbrmstr Nov 20 '18 at 11:51

2 Answers2

1

Using gridExtra to create a gtable.

library(grid)
library(gridExtra)

set.seed(1)

sample.data <- matrix(data=sample(0:1, 5*5, r=TRUE), nrow=5, ncol=5)
colnames(sample.data) <- LETTERS[1:5]
rownames(sample.data) <- letters[1:5]


# for cut() to work data has to be of class matrix or table.
# data.frame will cause error    
fcol <- as.character(cut(
          sample.data, c(0, 0.5, 1), include.lowest=TRUE, 
          labels=c("black", "white")))

bcol <- as.character(cut(
          sample.data, c(0, 0.5, 1), include.lowest=TRUE, 
          labels=c("white", "black")))

# building a theme.
# core specifies the features of the main field,
# rowhead the row titles, and colhead the column titles.
# fg_params specifies the features of the foreground, namely the text,
# bg_params specifies the features of the background, like the fill
# and border colors.
t1 <- ttheme_minimal(base_size=20, 
        core=list(
          fg_params=list(col=fcol),
          bg_params=list(fill=bcol, col="black", lwd=2)
        ),
        rowhead=list(
          fg_params=list(fontface=1)
        ),
        colhead=list(
          fg_params=list(fontface=1, rot=90)
        )
      )

grid.newpage()
grid.table(sample.data, theme=t1)

enter image description here

AkselA
  • 8,153
  • 2
  • 21
  • 34
  • 1
    This OP is obviously a new contributor and pretty obviously new to R, perhaps provide some (_any_?) context to what you're doing above for them? Your "solution" doesn't even plot it for them (and they likely do not know to use `grid.newpage()` on their own). – hrbrmstr Nov 20 '18 at 12:07
  • 1
    @hrbrmstr: Working on it ;) – AkselA Nov 20 '18 at 12:09
  • Thank you for your suggestion. Error in cut.default(Data1, c(0, 0.5, 1), include.lowest = TRUE, labels = c("black", : x should be numeric, but all my columns numeric I chekced by classes – Maria Zeltser Nov 20 '18 at 18:44
  • @MariaZeltser: Could you share `Data1` with us? Do `dput(Data1)` and copy-paste the result into your question. – AkselA Nov 20 '18 at 18:56
1

We'll use the data from the image (though this is likely not your use-case). This will simulate it:

library(tidyverse)

set.seed(2018-11-20)

# expand.grid just creates a data frame out of all the combinations
# of the provided vectors.

# tbl_df just turns the output into a data frame that (oversimplifying)
# prints better

# set_names is just setting column names

# the mutate line is where we generate the 0/1s

expand.grid(
  sprintf("Address%s", 1:9),
  sprintf("Transaction%s", 1:16),
  stringsAsFactors = FALSE
) %>%
  tbl_df() %>%
  set_names(c("address", "transaction")) %>%
  mutate(value = sample(0:1, n(), replace=TRUE)) -> xdf

xdf
## # A tibble: 144 x 3
##    address  transaction  value
##    <chr>    <chr>        <int>
##  1 Address1 Transaction1     0
##  2 Address2 Transaction1     1
##  3 Address3 Transaction1     1
##  4 Address4 Transaction1     0
##  5 Address5 Transaction1     1
##  6 Address6 Transaction1     1
##  7 Address7 Transaction1     0
##  8 Address8 Transaction1     0
##  9 Address9 Transaction1     1
## 10 Address1 Transaction2     0
## # ... with 134 more rows

If your data is "wide" vs "long" (like the above) take a look at the tidyr::gather function.

Now, it's just a wee bit more data wrangling and some basic ggplot2. First, we'll use your logic and define cell fill and text color for each cell. And, since we want the X axis plotted in the reverse direction we also order it so that ggplot2 will honor that need.

mutate(
  xdf,
  fill = ifelse(value == 1, "black", "white"),
  color = ifelse(value == 1, "white", "black"),
  address = factor(address, levels = sort(unique(address), decreasing = TRUE))
) -> xdf

Now, we use a tile layer and put a text layer on top of it. We used "real" color names in the mutate call above so we can take advantage of a ggplot2 "hack" by surrounding the mapped column aesthetic with I() which tells ggplot2 to use the value as-is and also don't bother giving us a legend (we can generate a legend if you want but that wasn't in the sparse question).

Then, we remove some whitespace between labels and the plot, stick the Y labels on top and rotate them (though this is not a good practice since making folks twist their head to read your plot is not cool).

ggplot(xdf, aes(x = transaction, y = address)) +
  geom_tile(
    aes(fill = I(fill)),
    color = "#2b2b2b", size=0.125,
  ) +
  geom_text(
    aes(label = value, color = I(color))
  ) +
  scale_x_discrete(expand=c(0,0), position = "top") +
  scale_y_discrete(expand=c(0,0)) +
  labs(x = NULL, y = NULL) +
  hrbrthemes::theme_ipsum_rc(grid="XY") +
  theme(axis.text.x = element_text(angle=90, vjust=0.5, hjust=1))

enter image description here

hrbrmstr
  • 77,368
  • 11
  • 139
  • 205
  • thank you very much for you suggestion! I have the table already in talbe view. I am not an expert in R, so a little bit hard to understnad how to change your code – Maria Zeltser Nov 20 '18 at 18:53