Combining Text_Grob with ggplot via grid_arrange - delete Text_grob-Margins - r

I have been trying to merge a TextGrob with a ggplot for some time. Unfortunately, the TextGrob always creates a certain distance to the plot, which I do not want.
The whole thing becomes a bit clearer when looking at the current result:
The goal is to have the "Lennart" directly on the plot, as a kind of artificial axis label.
The current code looks like this: (I have adjusted the formatting somewhat, but the essentials should be recognisable)
png("PNGZwischenspeicher2.png", bg = "transparent", width = 2500, height = 1000)
p <- ggplot(DBE3, aes(x = reorder(emoji, n), y = n,reorder(emoji,-n)))+
theme(plot.margin = margin(0,0,0,0, "pt"))+
geom_col(alpha = 0.2, width = 0.2)+
coord_flip()+
theme(axis.title.y = element_blank())+
scale_fill_manual(values=c("transparent", "transparent", "transparent"))+
scale_y_continuous(expand = expansion(mult = c(0.00, .5)))
print(p)
dev.off()
img2 <- readPNG("PNGZwischenspeicher2.png")
PE2 <- rasterGrob(img2)
Header2 <- textGrob("Lennart", rot = 90, gp = gpar(fontsize = 12, fontface = 'plain'))
grid.arrange(Header2, PE2, nrow = 1)
Don't ask why it is necessary to edit the plot via the png-workaround, the current script doesn't allow it otherwise :D
If anyone knows a way to remove the space between the text_grob and the plot (or png), I would be very grateful.
My approach would be to adjust the size of the text_grob, but unfortunately I haven't found a working way to do this yet.
Thank you very much and have a nice evening!
Data needed for recreation:
dput(DBE3)
structure(list(author = structure(c(1L, 1L, 1L), .Label = c("Lennart",
"Toni Janina", "Toni"), class = "factor"), emoji = c("<U+0001F607>",
"<U+0001F64F>", "<U+0001F605>"), n = c(90L, 47L, 30L), name = c("smiling face with halo",
"folded hands", "grinning face with sweat"), hex_runes = c("1F607",
"1F64F", "1F605"), hex_runes1 = c("1F607", "1F64F", "1F605"),
emoji_url = c("https://abs.twimg.com/emoji/v2/72x72/1f607.png",
"https://abs.twimg.com/emoji/v2/72x72/1f64f.png", "https://abs.twimg.com/emoji/v2/72x72/1f605.png"
)), row.names = c(NA, -3L), groups = structure(list(author = structure(1L, .Label = c("Lennart",
"Toni Janina", "Toni"), class = "factor"), .rows = structure(list(
1:3), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr",
"list"))), row.names = c(NA, -1L), class = c("tbl_df", "tbl",
"data.frame"), .drop = TRUE), class = c("grouped_df", "tbl_df",
"tbl", "data.frame"))

Here is a simpler example that shows how to add a textGrob to a ggplot with {ggpp} (or {ggpmisc}). This could be also done with geom_text() but I guess you have something more complicated as the actual problem. This code can be used with any grob including bitmaps.
library(ggpp)
#> Loading required package: ggplot2
#>
#> Attaching package: 'ggpp'
#> The following object is masked from 'package:ggplot2':
#>
#> annotate
library(grid)
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
annotate(geom = "grob", x = 5, y = 40,
label = textGrob("Lennart", rot = 90, gp = gpar(fontsize = 12, fontface = 'plain')))
Created on 2021-07-29 by the reprex package (v2.0.0)

Related

Not able to add percentage labels with two decimals in ggplot2 geom_text

I'm trying to add the column values as geom text with ggplot2:
df <- structure(list(type = structure(1:4, .Label = c("a", "b", "c",
"d"), class = "factor"), values = c(0.166667, 0.416667, 0.083333,
0.333333)), class = "data.frame", row.names = c(NA, -4L))
Input:
round(df$values, digits = 4)
Out:
[1] 0.1667 0.4167 0.0833 0.3333
Input:
scales::percent(round(df$values, digits = 4))
Out:
[1] "16.7%" "41.7%" "8.3%" "33.3%"
As you can notice, the result only round to one decimals percentage values, but I need two decimals.
This line of code is for adding text for the plot:
geom_text(aes(label = scales::percent(round(df$values, digits = 4))), position = position_stack(vjust = 0.5))
How could I modify the paramters above to round them correctly? Thanks.
You can use accuracy with the scales::percent() function:
geom_text(aes(label = scales::percent(round(df$values, digits = 4), accuracy = 0.01)), position = position_stack(vjust = 0.5))
from documentation the correct code seems to be:
scales::percent(df$values, accuracy = 0.01)

R ggplot + ggplotly: color scale doesn't work

Beginning with ggplotly, and I can't seem to figure out how to use the colour scale. Here's what I've got:
> dput(set.df)
structure(list(Set.name = structure(1:6, .Label = c("set_3_1",
"set_3_2", "set_3_3", "set_3_4", "set_3_5", "set_3_6"), class = "factor"),
Set.size = c(36202L, 31389L, 74322L, 181981L, 204571L, 347844L
), TF.number = c(91, 16, 38, 91, 91, 91), Ref.set.size = c(3830L,
155L, 725L, 3830L, 3830L, 3830L), False.negatives = c(107L,
7L, 100L, 1159L, 1744L, 2310L), Sensitivity = c(0.972062663185379,
0.954838709677419, 0.862068965517241, 0.697389033942559,
0.544647519582245, 0.39686684073107), Specificity = c(0.0790835553530113,
0.296607846658412, 0.296159447758514, 0.300796981749767,
0.325487685108514, 0.451174177879625), Precision = c(0.00959662223642798,
0.00342695718619029, 0.00608000311296159, 0.0110294421274311,
0.0094999544585117, 0.0199195355603025)), row.names = c(NA,
-6L), class = "data.frame")
and
plot <- ggplot(set.df, aes(key=Set.name, size = Set.size, fill = TF.number, x = Specificity, y = Sensitivity)) +
geom_point(colour="#ffffff00") +
expand_limits(x = 0, y = 0) +
geom_hline(yintercept = 0.8, linetype = "dotted", colour= 'blue') +
scale_fill_continuous(low='skyblue', high='midnightblue')
ggplotly(plot, tooltip = c("Set.name", "Set.size", "TF.number", "Ref.set.size", "False.negatives", "Sensitivity", "Specificity", "Precision"))
and the output is:
The points don't show up in the expected nuance of blue, and I get the following warning message:
Warning message:
In L$marker$color[idx] <- aes2plotly(data, params, "fill")[idx] :
number of items to replace is not a multiple of replacement length
Also, somehow the point size legend doesn't show up.
Thanks for your input!
The main issue is that the fill aesthetic for geom_point() is only applicable to certain shapes (ones that have a border). This doesn't include the default shape so you need to use the color aesthetic instead. As for why the size legend doesn't show, ggplotly doesn't yet natively support multiple legends. See here.
myplot <- ggplot(set.df, aes(key = Set.name, size = Set.size, color = TF.number, x = Specificity, y = Sensitivity)) +
geom_point() +
expand_limits(x = 0, y = 0) +
geom_hline(yintercept = 0.8, linetype = "dotted", colour= 'blue') +
scale_color_continuous(low='skyblue', high='midnightblue')
ggplotly(myplot, tooltip = c("Set.name", "Set.size", "TF.number", "Ref.set.size", "False.negatives", "Sensitivity", "Specificity", "Precision"))

dumbbell plot in R

Hi I have series of time intervals stored in data frame df.
replicate ID timeA timeB mean
1 60 80 70
2 10 70 40
3 25 35 30
I am trying to plot a dumbbell:
library(ggplot2)
devtools::install_github("hrbrmstr/ggalt")
library(ggalt)
library(dplyr)
df <- arrange(df, timeA)
#calculate mean middle point between two values
df$mean <- rowMeans(df[2:3])
#add factor levels
df <- mutate(df, rep=factor(replicateID, levels=rev(replicateID)))
gg <- ggplot(df, aes(x=timeA, xend=timeB, y=rep))
gg <- gg + geom_dumbbell(colour="#a3c4dc",
point.colour.l="#0e668b",
point.colour.r="#0000ff",
point.size.l=2.5,
point.size.r=2.5)
gg <- gg + geom_point(aes(y = df$mean), color = "red", linetype = "dotted")
The dumbbell plot gets plotted correctly till a certain point, however, I would like to have the middle point of each pair of values displayed on the graph too and connect all the middle values with a line.
I tried to do that by adding geom_point but this doesn't work.
Any suggestion?
First of all, the parameter/aesthetic names have changed, so don't get confused. If you don't update you'll have to use your parameter names. But for geom_segment and geom_point it will be like below:
#data
df=structure(list(replicateID = c(2, 3, 1), timeA = c(10, 25, 60
), timeB = c(70, 35, 80), mean = c(40, 30, 70), rep = structure(3:1, .Label = c("1",
"3", "2"), class = "factor"), time_mean = c(40, 30, 70)), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -3L), groups = structure(list(
rep = structure(1:3, .Label = c("1", "3", "2"), class = "factor"),
.rows = list(3L, 2L, 1L)), row.names = c(NA, -3L), class = c("tbl_df",
"tbl", "data.frame"), .drop = TRUE))
gg <- gg + geom_dumbbell(colour="#a3c4dc",
colour_x = "#0e668b",
colour_xend="#0000ff",
size_x=2.5,
size_xend=2.5,
linetype = "dotted")
gg <- gg + geom_point(aes(x = mean), color = "red") #draws the points
gg+geom_path(aes(x=mean,group=1)) #draws the line
You could also try to use geom_line with the same parameters. Here you would get a connection from ID 1-3 which might not be what you're looking for. I'm not sure from your question.
PS: in the future please consider posting the output from dput(df) as this is easier for others to read into an r-session
Using the dumbbell R package
##Load some libraries
library(tidyverse)
library(ggplot2)
library(rlang)
library(utils)
library(data.table)
library(dumbbell)
## reformat the data
df2<-df %>% mutate("key"="Time") %>% mutate("diff"=timeA-timeB)
df3<-df2%>% arrange(desc(timeA))
df2$replicateID<-factor(df2$replicateID, df3$replicateID)
##Plot
dumbbell::dumbbell(df2,key="key",id="replicateID", column1 = "timeA", column2="timeB", lab1 = "timeA", lab2="timeB", pt_val = 1, delt=1, textsize = 3) + geom_point(aes(x = df2$mean, y=df2$replicateID), color = "red") +
geom_path(aes(x=df2$mean,y=df2$replicateID,group=1))
Dont have enough points so here is the link to the plot
dumbbell R package

r does not allow the x axis to display the title (now with added data)

The question was how to get R to display titles on the x- and y-axes when the plot is rotated. mtext was not allowing this to happen. The question then became how to do this with the data at hand.
Here is my edited code and data.
Small segment of my Data:
library(ggplot)
x <- structure(list(
CS1 = c(51.176802507837, 11.289327763008, 10.8584547767754, 5.37665764546685, 6.47159365761892),
CS2 = c(34.9956506731101, 45.7147446193383, 23.788413903316, 42.4969135802469, 18.8998879103283),
CS3 = c(3.59556251631428, 5.59228312932411, 11.7117536894149, 15.7240944017563, 9.72486977228754),
CS4 = c(0.830633241559198, 2.57358541893362, 3.05352639873916, 7.01238591916558, 2.98276253547777),
CS5 = c(6.6094547746612, 7.67873290538655, 9.93544994944388, 8.49609094535301, 6.71423210935406)),
class = c("tbl_df", "tbl", "data.frame"))
Now some code to make a ggplot.
xplot<-ggplot(x, aes(y = test, y = CS2, group = test))+
geom_boxplot()+
labs(y = "Intensity",
x = "Variable")+
scale_x_discrete()
xplot
Try using ggplot from the tidyverse.
<del>It is useful to have a basic dataset to run from:<\del> Now that you have some data
library(tidyverse)
x <-structure(list(
CS1 = c(51.176802507837, 11.289327763008, 10.8584547767754, 5.37665764546685, 6.47159365761892),
CS2 = c(34.9956506731101, 45.7147446193383, 23.788413903316, 42.4969135802469, 18.8998879103283),
CS3 = c(3.59556251631428, 5.59228312932411, 11.7117536894149, 15.7240944017563, 9.72486977228754),
CS4 = c(0.830633241559198, 2.57358541893362, 3.05352639873916, 7.01238591916558, 2.98276253547777),
CS5 = c(6.6094547746612, 7.67873290538655, 9.93544994944388, 8.49609094535301, 6.71423210935406)),
row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame")
)
Now gather that data into two columns
x1 <- gather(x, test, values, CS1:CS5)
Now plot
xplot<-ggplot(x1, aes(x = test, y = values, group = test))+
geom_boxplot()+
labs(y = "Intensity",
x = "Variable")
xplot + coord_flip()

r: Inserting ggtexttable() inside a ggplot graph

I'm trying to insert a table that I created using the ggtexttable() function from the ggpubr package inside the plotting boundary of my ggplot plot. However, I keep getting this error:
Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) :
cannot coerce class "c("gg", "ggplot")" to a data.frame
I don't understand why I am getting error but I have a feeling it has to do with that I have dates on my x-axis? I would appreciate any feedback to fix this issue! Thanks!
Data:
HUC_df1 <- structure(list(charnam = c("Total dissolved solids", "Total dissolved solids",
"Total dissolved solids"), stdate = structure(c(11297, 11296,
11298), class = "Date"), val = c(439, 437, 510), HUC14 = c("HUC02030104020030",
"HUC02030104020030", "HUC02030104020030")), .Names = c("charnam",
"stdate", "val", "HUC14"), row.names = c(NA, -3L), class = c("tbl_df",
"tbl", "data.frame"))
HUC1_count<-structure(list(year = "2000", n_greater = 1L, percentage = 33.33,
n = 3L), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-1L), .Names = c("year", "n_greater", "percentage", "n"))
Code:
library(ggpubr)
library(ggplot2)
theme_graphs<- theme_linedraw()+
theme(plot.title=element_text(size=15, face="bold",vjust=0.5,hjust = 0.5),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
plot.background = element_blank(),
panel.background = element_blank(),
legend.position = c(0.5, 0.2),
legend.background = element_blank(),
legend.text=element_text(size=10, face="bold"))
HUC1_table<-ggtexttable(HUC1_count,
theme = ttheme("classic"),rows=NULL,
cols=c("Year","Number of Samples\n>500",
"Percent of Samples\n>500","Total Samples"))
HUC1<-ggplot(data = HUC_df1, aes(x =stdate, y = val)) +
geom_point()+
geom_hline(aes(yintercept = 500,color="red"),size=1.3)+
scale_y_continuous(expand = c(0, 0), limits = c(0))+
coord_cartesian(ylim = c(0, 700))+
scale_x_date(date_labels ="%b%Y")+
ggtitle("Elizabeth R (below Elizabeth CORP BDY) (HUC02030104020030)\nTDS Concentration (mg/L);1997-2018") +
xlab("Year") + ylab(" TDS Concentration (mg/L)")+
scale_color_manual("",
values = c("red"),
labels=c("Freshwater Aquatic Life Criteria for TDS = 500 mg/L"))+
theme_graphs+
theme(legend.position =c(0.5, -0.098))
HUC1<-HUC1+annotation_custom(tableGrob(HUC1_table), xmin=1.5,
xmax=1.8,
ymin=200, ymax=300)
I see two problems here. First, tableGrob is a function for creating a grob from a data.frame. But you've already created your table do you don't need that function. But ggtexttable returns a ggplot object, but you need a grob, so you need ot use ggplotGrob to turn that ggplot object into something you can use with annotation_custom.
The second problem is the range you specific for your x values. Since your data is formatted as a Date vector, those values are stored as the number of days since 1970-01-01 so values of 1.5 and 1.8 are way outside the range of what you are actually plotting. You can see your actual range with
range(as.numeric((HUC_df1$stdate)))
# [1] 11296 11298
So fixing those two problems, what you want for the example is
HUC1+annotation_custom(ggplotGrob(HUC1_table), xmin=11296,
xmax=11298,
ymin=200, ymax=300)

Resources