Electrino
Electrino

Reputation: 2890

How to create a Barplot from a matrix in R?

This question has been asked before here... however, I'm having trouble adapting my code to it.

I am trying to make a Barplot using symmetrical matrix data. Here's some example code:

n <- 5 # no of rows
p <- 5 # no of columns

# Create matrix of values
mat <- matrix(runif(n*p, 0, 1), nrow=n) # create matrix     
colnames(mat) <- paste0("x", 1:p)  # column names
rownames(mat) <- paste0("x", 1:nrow(mat)) # row names

diag(mat) <- 0 # set diagonals to 0
mat <- (mat+t(mat))/2  # make matrix symmetrical


# Base-R barplot:
barplot(mat, beside = T,
        col = c("red","green", "yellow", "blue", "black"))

This will produce something like this:

Base R barplot

But what I'm trying to achieve is something more like this: ggplot barplot

But I'm not sure exactly how I would achieve this. Below is an idea of how I would do it, but Im not sure:

library(ggplot2)
ggplot(mat, aes(x = variable names, y = values)) +
    geom_col(aes(fill = values)) +
    scale_fill_gradient2(low = "floralwhite",
                         high = "dodgerblue4") +
    theme_minimal() +
    theme(axis.title.y = element_text(angle = 0, vjust = 0.5)) +
    coord_flip()

But since mat is in matrix format is can't do the above... and I don't know what exactly to put as the aesthetics?

Any suggestions?

Upvotes: 0

Views: 6062

Answers (2)

Parfait
Parfait

Reputation: 107567

Consider reshaping matrix data long via data frame operations:

# CONVERT TO DATA FRAME
df <- transform(data.frame(mat), y=row.names(mat))

# RESHAPE LONG
long_df <- reshape(df, varying = colnames(mat), times = colnames(mat),
                   timevar="x", v.names="value", direction="long")

# ORDER VALUES
long_df <- with(long_df, long_df[order(value),])
long_df$xy <- with(long_df, paste(x, y, sep=":"))

# CONVERT TO MATRIX
new_mat <- matrix(long_df$value, dimnames=list(long_df$xy, "value"))
new_mat

# BASE R barplot:
barplot(new_mat, beside = TRUE, horiz = TRUE, 
        main = "Horizontal Bar Graph Descending Order",
        names.arg = row.names(new_mat),
        las=1, col = rainbow(nrow(new_mat)))

Online Demo (click Run for plot)

Plot Output

Upvotes: 2

Ronak Shah
Ronak Shah

Reputation: 388817

Do you mean to do something like this ?

library(dplyr)
library(tidyr)
library(ggplot2)

pivot_longer(data.frame(mat), cols = everything()) %>%
   group_by(name) %>%
   mutate(newname = unique(.$name), 
          newname = paste(pmin(name, newname), 
                          pmax(name, newname), sep = ":")) %>%
   ungroup() %>%
   select(-name) %>%
   distinct() %>%
   arrange(value)  %>%
   mutate(newname = factor(newname, unique(newname))) %>%
   ggplot() + aes(x = newname, y = value, group = value, fill = value) +
   geom_bar(stat = "identity", position = "dodge") +
   theme_minimal() + 
   theme(axis.title.y = element_text(angle = 0, vjust = 0.5)) + 
   coord_flip()

enter image description here

Upvotes: 1

Related Questions