Open stefaneng opened 1 year ago
There is a strange issue where @stefaneng's solution for adding text to different panels of create.scatterplot
does not work when calling create.scatterplot
and defining my.panel.text
within a larger wrapper function (e.g. making a new function for an R package):
suppressPackageStartupMessages(library(BoutrosLab.plotting.general));
to.plot.scatter <- data.frame(
x = rnorm(100),
y = rnorm(100),
z = c(1,2)
);
to.plot.scatter$z <- as.factor(to.plot.scatter$z);
wrapper <- function() {
group.scatter.text <- create.scatterplot(
y ~ x | z,
data = to.plot.scatter
);
my.panel.text <- c('panel 1', 'panel 2');
group.scatter.text + layer({
panel.key(
text = my.panel.text[[panel.number()]],
points = FALSE,
corner = c(0.05, 0.95)
)
});
}
wrapper();
Created on 2024-01-25 with reprex v2.0.2
Hey @jarbet ! layers/panels are weird and don't have a standard environment so you need to pass the data via the data
argument. I don't remember the specifics of how the layer environment works but this will definitely allow you to pass the info you need from the function to the plot.
suppressPackageStartupMessages(library(BoutrosLab.plotting.general));
to.plot.scatter <- data.frame(
x = rnorm(100),
y = rnorm(100),
z = c(1,2)
);
to.plot.scatter$z <- as.factor(to.plot.scatter$z);
wrapper <- function() {
group.scatter.text <- create.scatterplot(
y ~ x | z,
data = to.plot.scatter
);
my.panel.text <- c('panel 1', 'panel 2');
group.scatter.text + layer({
panel.key(
text = my.panel.text[[panel.number()]],
points = FALSE,
corner = c(0.05, 0.95)
)
}, data = list(my.panel.text = my.panel.text));
}
wrapper()
Created on 2024-01-25 with reprex v2.1.0
Thanks @stefaneng, this works great! Hope school is going well!!
@stefaneng thanks again for your help with the above problem! I'm curious if you have any ideas for how to put text above/below bars in create.barplot
when having multiple panels?
At a minimum, I know I can separately make each plot and add the text using text.above.bars
, then combine using create.multipanelplot
. However, I'm wondering if you think it is possible to more directly add the text when using |
in the create.barplot
formula?
For example, putting qvalue
above the bars in each panel?
suppressPackageStartupMessages(library(BoutrosLab.plotting.general));
set.seed(123);
dataset <- data.frame(
feature = c(rep('a', 3), rep('b', 3)),
group = rep(1:3, 2),
rho = runif(6, -1, 1),
qvalue = runif(6, 0, 1)
);
# how to put q-values above bars in each panel?
create.barplot(
formula = rho ~ group | feature,
data = dataset
);
Created on 2024-03-14 with reprex v2.0.2
There is probably a better way to do this via lattice... but almost the same solution as the other one is to split by the feature variable and pass the vector into each panel:
suppressPackageStartupMessages(library(BoutrosLab.plotting.general));
set.seed(123);
dataset <- data.frame(
feature = c(rep('a', 3), rep('b', 3)),
group = rep(1:3, 2),
rho = runif(6, -1, 1),
qvalue = runif(6, 0, 1)
);
# Create a lattice barplot with q-values above bars grouped by feature rho ~ group | feature
qvalue_feature_split <- split(round(dataset$qvalue, 2), dataset$feature)
create.barplot(
formula = rho ~ group | feature,
data = dataset,
ylimits = c(-1.2, 1.2)
) + layer({
ltext(x, y + sign(y) * 0.15, labels = qvalue_feature_split[[panel.number()]])
}, data = list(qvalue_feature_split = qvalue_feature_split))
Created on 2024-03-15 with reprex v2.1.0
There is probably a better way to do this via lattice... but almost the same solution as the other one is to split by the feature variable and pass the vector into each panel:
suppressPackageStartupMessages(library(BoutrosLab.plotting.general)); set.seed(123); dataset <- data.frame( feature = c(rep('a', 3), rep('b', 3)), group = rep(1:3, 2), rho = runif(6, -1, 1), qvalue = runif(6, 0, 1) ); # Create a lattice barplot with q-values above bars grouped by feature rho ~ group | feature qvalue_feature_split <- split(round(dataset$qvalue, 2), dataset$feature) create.barplot( formula = rho ~ group | feature, data = dataset, ylimits = c(-1.2, 1.2) ) + layer({ ltext(x, y + sign(y) * 0.15, labels = qvalue_feature_split[[panel.number()]]) }, data = list(qvalue_feature_split = qvalue_feature_split))
Created on 2024-03-15 with reprex v2.1.0
Genius! Thanks!!
Related to #137
add.text
has different behavior in a few different plotting functions. In particular,create.boxplot
differs in behavior from most of the others.Boxplot cannot add multiple text labels
A boxplot with multiple text labels and
text.x
ortext.y
will only draw the the first label but replicated for each of the coordinates.Boxplots grouped by a variable will put text in different panels
Only if a grouping variable is used will boxplot place one text label per each panel. This is actually opposite to what other plots do but this behavior seems the most intuitive.
Scatterplots draw multiple text labels as expected
Without grouping variables scatterplots draw on a single panel as expected with vector arguments.
Scatterplots with groups place same text on both panels
Scatterplots will draw the same text on each panel, following the same behavior as plot without groups. This is usually not what is desired and is somewhat counter-intuitive.
Solution: Add different text to each panel
A solution to allow for text to be added to each panel separately is to manually create a
latticeExtra::layer
withlattice::panel.text
. We can access the panel number withpanel.number()
and can create a vector of labels to index.Sometimes we don't want to specify
x
andy
coordinates but want to specify on a[0,1]
scale. In this case we can usepanel.key
and the coordinates withcorner
.Created on 2023-07-15 with reprex v2.0.2