I want to generate figure like this, where each row should have its value on y axis, I used red arrow to indicate where the values should be, the values stem from the data, so each bar should have a value, I added the values in the fig manually and they look same number, obviously they are not. I'm using synergyfinder package (https://github.com/IanevskiAleksandr/SynergyFinder#readme), it uses ggplot:
This is my code:
if (!require("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("synergyfinder")
s
a
.libPaths()
library(synergyfinder)
library(readxl)
res <- ReshapeData(
data = data,
data_type = "inhibition",
impute = TRUE,
impute_method = NULL,
noise = TRUE,
seed = 1)
res <- CalculateSynergy(
data = res,
method = c("ZIP", "HSA", "Bliss", "Loewe"),
Emin = NA,
Emax = NA,
correct_baseline = "non")
res$drug_pairs
res <- CalculateSensitivity(
data = res,
correct_baseline = "non"
)
sensitive_columns <- c(
"block_id", "drug1", "drug2",
"ic50_1", "ic50_2",
"ri_1", "ri_2",
"css1_ic502", "css2_ic501", "css")
res$drug_pairs[, sensitive_columns]
for (i in c(1, 2)){
PlotDoseResponseCurve(
data = res,
plot_block = 1,
drug_index = i,
plot_new = FALSE,
record_plot = FALSE
)
}
par(mar = c(4, 8, 4, 6) + 0.1)
PlotMultiDrugBar(
data = res,
plot_block = 1,
plot_value = c("response", "ZIP_synergy", "Loewe_synergy", "HSA_synergy", "Bliss_synergy"),
sort_by = "response",
highlight_label_size = 4
)
This is the head of dput:
dput(head(data))
structure(list(block_id = c(1, 1, 1, 1, 1, 1), drug1 = c("X",
"X", "X", "X", "X", "X"), drug2 = c("N", "N", "N", "N", "N",
"N"), cell_line_name = c("A", "A", "A", "A", "A",
"A"), conc1 = c(0, 10, 3.333, 1.111, 0.37, 0.123), conc2 = c(0,
0, 0, 0, 0, 0), response = c(0, 94.7124199185235, 93.1970077742489,
94.9121253949008, 92.6627816399623, 90.6942562299578), conc_unit = c("μM",
"μM", "μM", "μM", "μM", "μM")), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))
This is the best that I could've come up with:
install.packages("scales")
library(dplyr)
library(scales)
library(ggplot2)
library(gridExtra)
library(readxl)
data <- read_xlsx("N+X+syn.xlsx")
head(data)
res <- ReshapeData(
data = data,
data_type = "inhibition",
impute = TRUE,
impute_method = NULL,
noise = TRUE,
seed = 1
)
res <- CalculateSynergy(
data = res,
method = c("ZIP", "HSA", "Bliss", "Loewe"),
Emin = NA,
Emax = NA,
correct_baseline = "non"
)
res <- CalculateSensitivity(
data = res,
correct_baseline = "non"
)
# Convert to data frame and clean the data
res <- as.data.frame(res)
res_clean <- res %>%
rename(
N = synergy_scores.conc1,
X = synergy_scores.conc2,
response = response.response,
ZIP_synergy = synergy_scores.ZIP_synergy,
Bliss_synergy = synergy_scores.Bliss_synergy,
Loewe_synergy = synergy_scores.Loewe_synergy,
HSA_synergy = synergy_scores.HSA_synergy
)
res_selected <- res_clean %>%
select(N, X, response, ZIP_synergy, Bliss_synergy, Loewe_synergy, HSA_synergy)
highlight_threshold <- 1
create_plot <- function(data, column_name, plot_number) {
fill_condition <- if (column_name %in% c("N", "X", "response")) {
"FALSE" # No highlighting for N, X, or response
} else {
paste0(column_name, " > ", highlight_threshold) # Apply threshold to synergy scores
}
ggplot(data, aes_string(x = column_name, y = column_name, fill = fill_condition)) +
geom_bar(stat = "identity", width = 0.6, show.legend = FALSE) +
geom_text(aes_string(label = column_name), hjust = -0.3, size = 5, color = "black") +
scale_fill_manual(values = c("lightblue", "orange")) + # Keep threshold highlight color consistent
coord_flip() +
theme_minimal() +
labs(
title = paste(column_name),
subtitle = "",
x = "",
y = "Value"
) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 16),
plot.subtitle = element_text(hjust = 0.5, size = 12),
axis.text.y = element_blank() # Remove y-axis labels
)
}
plots <- lapply(1:7, function(i) create_plot(res_selected, names(res_selected)[i], i))
grid.arrange(grobs = plots, ncol = 7, nrow = 1)
and got this ugly figure ...lol:
It's great that you added data to your question, but you didn't make sure that that data recreated the issue...you know...made it reproducible. To get the best answers quickly, that's always your best bet.
In lieu of your data, I used the example data used in the synergy package.
You wrote, "I used red arrow to indicate where the values should be"...but I don't know where your 'red arrows' are...
I've started with some simple examples of where the data came from and how I can move the labels where I would like them to go.
First, here's the data and plot I built with the PlotMultiDrugBar
. Note it's an object named plt
here.
library(synergyfinder)
library(tidyverse)
data("mathews_screening_data") # from example in synergy pkg
dta <- ReshapeData(mathews_screening_data)
res <- CalculateSynergy(dta)
plt <- PlotMultiDrugBar( # from your question
data = res,
plot_block = 1,
plot_value = c("response", "ZIP_synergy", "Loewe_synergy", "HSA_synergy", "Bliss_synergy"),
sort_by = "response",
highlight_label_size = 4
)
Typically, you can get the data used in your plot by call for data. For example, I named the plot plt
so normally I can get the data by calling plt$data
. However, that's not the case here. The data is nested in the layer that builds the bar plot, so plt$layer[[1]]$data
.
In this first example, I kept it simple, using the value as the label and the y placement -- note that this is a faceted plot -- think x -> y and y -> x, if I move y
it moves right and left.
It's ugly!
plt + geom_text(data = plt[["layers"]][[1]][["data"]],
mapping = aes(x = id, y = value, label = value))
If I just format the values, set y = 10, and make the size relative to the size of the plot....
still pretty ugly...and illegible
plt + geom_text(data = plt[["layers"]][[1]][["data"]],
mapping = aes(x = id, label = format(value, digits = 3)), # <-format me!
size = rel(2.3), y = 10) # <--- I'm new
If I wanted to right-justify my labels, I've got to do it by group, because each groups range is different. In this next example, I grouped the data by the column it's in (metric
) and then captured the groups' max values. That new column (mxg
) is what I assigned to y
.
It's the least ugly so far.
plt + geom_text(data = plt[["layers"]][[1]][["data"]] %>% group_by(metric) %>%
mutate(mxg = max(value)) %>% ungroup(), # group max val!
mapping = aes(x = id, y = mxg, # <--- I'm new
label = format(value, digits = 3)),
size = rel(2.3))
Alright, so there are some labeling options for you to pick through. As for some of the other elements you called out in your code, here's what I think you were trying to do.
I'll start with renaming the faceted column names in the data, then add the color and theme options you identified.
The appearance and readability is definitely much improved here. The x-axis is a bit difficult to read.
levels( plt[["layers"]][[1]][["data"]]$metric ) # current levels
# [1] "ispinesib\n(nM)" "ibrutinib\n(nM)"
# [3] "Response\n(% inhibition)" "ZIP Synergy Score"
# [5] "Loewe Synergy Score" "HSA Synergy Score"
# [7] "Bliss Synergy Score"
# change the names
levels(plt$layers[[1]]$data$metric) <- c("N", "X", "response", "Zip Synergy",
"Bliss Synergy", "Loewe Synergy", "HSA Synergy")
# with renamed columns
plt + geom_text(data = plt[["layers"]][[1]][["data"]] %>% group_by(metric) %>%
mutate(mxg = max(value)) %>% ungroup(), # group max val!
mapping = aes(x = id, y = mxg,
label = format(value, digits = 3)),
size = rel(2.3)) +
scale_fill_discrete(c("lightblue", "orange")) +
theme_minimal() %>%
theme(strip.text = element_text(face = "bold", size = rel(.8)), # facet titles
axis.text = element_text(size = rel(.75))) # axis tick text
# there is no subtitle, the titles are already centered, there is no y-axis text...unless you knew they switched...hmmm