How can I change the angle of the stripe pattern in only one element? For example, I want only the stripe pattern of "V" to be at -30 degrees.
Also, there seems to be an issue with my "NA" values / none pattern and no pattern appears after a NA value.
library(swimplot)
library(ggpattern)
library(tidyverse)
df <- data.frame(
study_id = c(3, 3, 3,3), primary_therapy = c("Si", "Si", "Si", "Si"),
additional_therapy = c("NA", "S", "NA", "V+S"), end_yr = c(0.08, 0.39, 3.03, 3.4)
)
swimmer_plot(
df = df, id = "study_id",
end = "end_yr", name_fill = "primary_therapy",
width = 0.85, color = NA) +
geom_col_pattern(aes(study_id, end_yr,
pattern = additional_therapy), color=NA,
fill = NA,
show.legend=FALSE, width=0.85,
pattern_spacing = 0.01, pattern_fill="black", pattern_color=NA,
pattern_size = 0.5, pattern_density=0.1,
pattern_linetype = 0.5, pattern_orientation="vertical") +
scale_pattern_manual(name="Additional Therapy", values = c("S"="stripe","V"="stripe","V+S"="crosshatch","NA"="none"))
For demonstration purposes, I changed your dataframe so you can see how the levels of additional_therapy get plotted, since your example dataframe didn't include any appearances of the level "V".
To achieve your goal of changing the stripe element for one level of additional_therapy, you need to add the argument pattern_angle back into geom_col_pattern and then add an extra line for scale_pattern_angle_manual() to specify which levels' patterns get set at which angles.
library(swimplot)
library(ggpattern)
library(tidyverse)
df <- data.frame(
study_id = c(3, 3, 3, 3, 3),
primary_therapy = c("Si", "Si", "Si", "Si", "Si"),
additional_therapy = c("NA", "NA", "S", "V", "V+S"),
end_yr = c(0.08, 1.11, 2.11, 3.03, 3.4)
)
# Convert additional_therapy to ordered factor (optional but highly recommended)
# This just determines the order that the items in the Additional Therapy legend appear in
df <- df %>% mutate(additional_therapy = factor(additional_therapy, levels = c("S", "V", "V+S", "NA")))
swimmer_plot(
df = df, id = "study_id",
end = "end_yr", name_fill = "primary_therapy",
width = 0.85, color = NA) +
geom_col_pattern(aes(study_id, end_yr,
pattern = additional_therapy,
pattern_angle = additional_therapy
),
color=NA,
fill = NA,
show.legend=TRUE, # so you can see the legend
width=0.85,
pattern_spacing = 0.01,
pattern_fill="black",
pattern_color=NA,
pattern_size = 0.5,
pattern_density=0.1,
pattern_linetype = 0.5,
pattern_orientation="vertical") +
scale_pattern_manual(name="Additional Therapy", values = c("S"="stripe","V"="stripe","V+S"="crosshatch","NA"="none")) +
scale_pattern_angle_manual(name="Additional Therapy", values = c(30, -30, 30, 30))
Unfortunately, to the best of my knowledge, there is a problem with ggpattern that is causing the issue with the x-axis. I discussed it in another of your questions here. I confirmed that it wasn't an issue with swimplot.
Related
Using ggpattern, how can I not show a pattern for "NA" values but then have patterns continue after that point? When I run this code, there are no more patterns after an "NA" value even though there should be.
library(swimplot)
library(ggpattern)
library(tidyverse)
df <- data.frame(
study_id = c(3, 3, 3,3), primary_therapy = c("Si", "Si", "Si", "Si"),
additional_therapy = c("NA", "S", "NA", "V+S"), end_yr = c(0.08, 0.39, 3.03, 3.4)
)
swimmer_plot(
df = df, id = "study_id",
end = "end_yr", name_fill = "primary_therapy",
width = 0.85, color = NA) +
geom_col_pattern(aes(study_id, end_yr,
pattern = additional_therapy), color=NA,
fill = NA,
show.legend=FALSE, width=0.85,
pattern_spacing = 0.01, pattern_fill="black", pattern_color=NA,
pattern_size = 0.5, pattern_density=0.1,
pattern_linetype = 0.5, pattern_orientation="vertical") +
scale_pattern_manual(name="Additional Therapy", values = c("S"="stripe","V"="circle","V+S"="crosshatch","NA"="none"))
Your question has two parts: 1) controlling the legend labels and 2) fixing the x-axis for geom_col_pattern().
For your first question, you can remove "NA" from the legend by converting additional_therapy to a factor:
df <- df %>%
mutate(additional_therapy = factor(additional_therapy,
levels = c("S", "V", "V+S", "NA")))
Then, you can specify breaks to control which legend labels show up:
+ scale_pattern_manual(name="Additional Therapy", breaks = c("S", "V", "V+S"), values = c("S"="stripe", "V"="circle", "V+S"="crosshatch", "NA"="none"))
However, to the best of my knowledge, there is a problem with ggpattern when it comes to repeating patterns. I was able to recreate this issue using base ggplot2 to confirm that it's not an issue with swimplot.
In the below code, you can see that fill acts appropriately, but pattern will never repeat twice, which causes the pattern from "S" to spill over into the second red bar, which shouldn't have any pattern because it's "NA". I recommend submitting an issue on Github.
library(ggpattern)
library(tidyverse)
df <- data.frame(
study_id = c(3, 3, 3, 3), primary_therapy = c("Si", "Si", "Si", "Si"),
additional_therapy = c("NA", "S", "NA", "V+S"), end_yr = c(0.08, 0.39, 3.03, 3.4))
df %>%
ggplot(aes(x = end_yr, y = study_id)) +
geom_col_pattern(aes(pattern = additional_therapy,
fill = additional_therapy),
color = NA,
show.legend = TRUE,
position = "fill",
width = 3,
pattern_spacing = 0.01,
pattern_fill = "black",
pattern_color = NA,
pattern_size = 0.5,
pattern_density = 0.1,
pattern_linetype = 0.5,
pattern_orientation = "vertical") +
scale_pattern_manual(
name = "Additional Therapy",
breaks = c("S", "V", "V+S"),
values = c("S" = "stripe", "V" = "circle", "V+S" = "crosshatch", "NA" = "none"))
I am having a hard time figuring out how to fix this graph. I thought it was a bug with ggpattern (see here and response to my bug report here); however, others seem to think it is not a bug, but an issue with "overlapping columns". When there are no overlapping patterns/values (e.g., "NA, "S", "V+S") the x-axis and patterns align; but when some repeat as in the code above the problems occur. I do not know how to reconcile these packages together to create a graph with appropriate patterns and x-axis values which consistently seem to both be incorrect. Thanks!
library(swimplot)
library(ggpattern)
library(tidyverse)
df <- data.frame(
study_id = c(3, 3, 3, 3), primary_therapy = c("Si", "Si", "Si", "Si"),
additional_therapy = c("NA", "S", "NA", "V+S"), end_yr = c(0.08, 0.39, 3.03, 3.4))
df <- df %>% mutate(additional_therapy = factor(additional_therapy,
levels = c("S", "V", "V+S", "NA")))
swimmer_plot(
df = df, id = "study_id",
end = "end_yr", name_fill = "primary_therapy",
width = 0.85, color = NA) +
geom_col_pattern(aes(study_id, end_yr,
pattern = additional_therapy), color=NA,
fill = NA,
show.legend=FALSE, width=0.85,
pattern_spacing = 0.01, pattern_fill="black", pattern_color=NA) +
scale_pattern_manual(name="Additional Therapy", values = c("S"="stripe","V"="circle","V+S"="crosshatch","NA"="none"),
breaks=c("S","V","V+S"))
I need to create a forestplot of high resolution. I used the forestplot() function from library(forestplot) to create my plot, and then attempted to use the tiff() function to create a high resolution image for publication. However, my image turned blank.
It works if I export directly from R but not as high resolution as it was supposed to.
library(forestplot)
df <- structure(list(
mean = c(NA, 0.22, 0.20, 0.27),
lower = c(NA, 0.05, 0.04, 0.01),
upper = c(NA, 0.95, 1.08, 9.12)),
.Names = c("mean", "lower", "upper"),
row.names = c(NA, -4L),
class = "data.frame")
tabletext <- cbind(
c("", "Pooled", "Group 1", "Group 2"),
c("N", "4334", "3354", "980"),
c("HR (95% CI)", "0.22 (0.05, 0.95)", "0.20 (0.04, 1.08)", "0.27 (0.01, 9.12)"),
c("p-value", "0.042", "0.061", "0.467")
)
ggfp <- forestplot(tabletext,
df,
new_page = TRUE,
is.summary = c(TRUE, rep(FALSE, 3)),
clip = c(0, 2),
colgap = unit(5, "mm"),
line.margin = unit(2, "mm"),
lineheight = unit(1, "in"),
txt_gp = fpTxtGp(label = gpar(cex = 1),
ticks = gpar(cex = 1)),
align = c("l", "c", "c", "c"),
boxsize = 0.2,
xticks = seq(0, 2.0, 0.5),
zero = 1,
col = fpColors(box = "royalblue",
line = "darkblue"),
mar = unit(c(-1, 0.5, -2, 0.5), "in"))
tiff("forestplot.tiff", units = "in", width = 9, height = 7, res = 300)
ggfp
dev.off()
The file was created but it was a blank page
This works for me (output file is 17MB):
library(forestplot)
setwd("/path/to/directory/for/plot")
df <- structure(list(
mean = c(NA, 0.22, 0.20, 0.27),
lower = c(NA, 0.05, 0.04, 0.01),
upper = c(NA, 0.95, 1.08, 9.12)),
.Names = c("mean", "lower", "upper"),
row.names = c(NA, -4L),
class = "data.frame")
tabletext <- cbind(
c("", "Pooled", "Group 1", "Group 2"),
c("N", "4334", "3354", "980"),
c("HR (95% CI)", "0.22 (0.05, 0.95)", "0.20 (0.04, 1.08)", "0.27 (0.01, 9.12)"),
c("p-value", "0.042", "0.061", "0.467")
)
tiff("forestplot.tiff", units = "in", width = 9, height = 7, res = 300)
forestplot(tabletext,
df,
new_page = TRUE,
is.summary = c(TRUE, rep(FALSE, 3)),
clip = c(0, 2),
colgap = unit(5, "mm"),
line.margin = unit(2, "mm"),
lineheight = unit(1, "in"),
txt_gp = fpTxtGp(label = gpar(cex = 1),
ticks = gpar(cex = 1)),
align = c("l", "c", "c", "c"),
boxsize = 0.2,
xticks = seq(0, 2.0, 0.5),
zero = 1,
col = fpColors(box = "royalblue",
line = "darkblue"),
mar = unit(c(-1, 0.5, -2, 0.5), "in"))
dev.off()
I am creating a forestplot using the forestplot package in R, and am having trouble with a few things.
Questions:
Is it possible to merge two adjacent text elements
Is it possible to modify either a single text element font, or the font of an entire row
My Code:
library(forestplot)
# creating text
text <- rbind(c('', 'N (%)', 'SRT', 'ART', 'HR [95% CI]'),
c('', '', '5 year survival %', '5 year survival %', ''),
c('Seminal Vesicle Involvement', '', '', '', ''),
c(' Yes', '10 (20%)', '94', '12', '0.73 [0.36, 1.50]'),
c(' No', '40 (80%)', '96', '10', '1.78 [0.73, 4.35]'),
c('Gender', '', '', '', ''),
c(' Male', '13 (22.5%)', '84', '22', '0.06 [-0.2, 0.86]'),
c(' Female', '37 (77.5%)', '93', '13', '1.89 [0.90, 6.67]'))
# creating the plot
forestplot(text,
mean = c(NA, NA, NA, 0.73, 1.78, NA, 0.06, 1.89),
lower = c(NA, NA, NA, 0.36, 0.73, NA, -0.2, 0.90),
upper = c(NA, NA, NA, 1.50, 4.35, NA, 0.86, 6.67),
is.summary=c(T, T, T, F, F, T, F, F),
lineheight = unit(0.9, "cm"),
graph.pos = 5,
graphwidth = unit(4, 'cm'),
xticks = c(-1, 0, 1, 2, 3, 4),
ci.vertices = T,
txt_gp = fpTxtGp(ticks = gpar(cex = 1),
xlab = gpar(cex = 1),
label = gpar(cex = 0.8),
summary = gpar(cex = 0.8)),
col=fpColors(box="black",
line="darkgrey",
summary="black",
zero='grey20',
axes='grey20'),
hrzl_lines = list("2" = gpar(lwd=1, col = "#000044")))
Output:
Desired:
I would like the two 5 year survival % text bits to be combined into 1 (and centered between the two headings above), and either just those elements or the whole row to be italic font.
I have tried using summary=list(gpar(...)) for the txt_gp option, but that only seems to be able to modify the whole column, and I have found nothing on merging cells at all.
If you make the colgap much smaller in forestplot than usual, you can split the text that is currently duplicated in row 2 in columns 3 and 4 into two parts:
> text[2, 4] <- 'survival % '
> text[2, 3] <- '5 year '
>
> forestplot(text,
+ mean = c(NA, NA, NA, 0.73, 1.78, NA, 0.06, 1.89),
+ lower = c(NA, NA, NA, 0.36, 0.73, NA, -0.2, 0.90),
+ upper = c(NA, NA, NA, 1.50, 4.35, NA, 0.86, 6.67),
+ is.summary=c(T, T, T, F, F, T, F, F),
+ lineheight = unit(0.9, "cm"),
+ graph.pos = 5,
+ graphwidth = unit(4, 'cm'),
+ xticks = c(-1, 0, 1, 2, 3, 4),
+ ci.vertices = T,
# add line---------
colgap=unit(.0011,"npc"),
#
+ txt_gp = fpTxtGp(ticks = gpar(cex = 1),
+ xlab = gpar(cex = 1),
+ label = gpar(cex = 0.8),
+ summary = gpar(cex = 0.8)),
+ col=fpColors(box="black",
+ line="darkgrey",
+ summary="black",
+ zero='grey20',
+ axes='grey20'),
+ hrzl_lines = list("2" = gpar(lwd=1, col = "#000044")))
I need to reorder the x-axis categorical variable with a numeric variable so the plot is simpler to follow with plotly, in R.
Here is some dummy data:
agg = structure(list(catvar = c("a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o"), v1 = c(1.1, 1.3, 1,
0.8, 1.2, 1.4, 0.7, 2.5, 0.9, 2.5, 1.7, 0.9, 1.7, 1.1, 0.9),
v2 = c(0.1, 0.1, 0.1, 0, 0.1, 0.1, 0, 0.2, 0, 0.2, 0.1, 0.1,
0.1, 0.1, 0.1), v3 = c(7.3, 8.2, 6.4, 6, 7.5, 8.4, 5.8, 12.4,
6.4, 13.1, 9.3, 6.2, 9.4, 7.1, 6.3)), .Names = c("catvar",
"v1", "v2", "v3"), class = "data.frame", row.names = c(NA, -15L
))
Here is what I've been trying out. It seems recently a new feature was added to handle this but it's not working.
# the reordering is handled here:
ax <- list(
type = "category",
categoryorder = "array",
categoryarray = agg$catvar[order(agg[['v1']])],
showgrid = TRUE,
showticklabels = TRUE
)
p <- plot_ly(agg, x =~catvar,
y =~v2, name = 'v2',
type = 'scatter', mode = 'lines') %>%
add_trace(y =~v1, name = 'v1') %>%
add_trace(y =~v3, name = 'v3') %>%
layout(
xaxis = ax,
hovermode = 'x+y')
p
All I need is to re-order the x-axis (catvar) based on any of the numeric varaibles in the data.frame, these are v1, v2, v3.
You need to add to your code a command for reordering your dataset according to v1.
agg2 <- agg[order(agg[['v1']]),]
p <- plot_ly(agg2, x =~catvar,
y =~v2, name = 'v2',
type = 'scatter', mode = 'points') %>%
add_trace(y =~v1, name = 'v1') %>%
add_trace(y =~v3, name = 'v3') %>%
layout(
xaxis = ax,
hovermode = 'x+y')
p