r: Inserting ggtexttable() inside a ggplot graph - r

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)

Related

Issues with ggplot on R: code is correct but I keep receiving the error "Must request at least one color from a hue palette"

There was a similar question asked that I found but did not provide a specific answer for my situation. I am conducting an RNA seq and the following code was used to generate a ggplot of Cell Numbers, but I keep getting the same error.
Here is the code for the plot:
metadata %>%
ggplot(aes(x=sample, fill= sample))+
geom_bar()+
theme_classic()+
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))+
theme(plot.title = element_text(hjust = 0.5, face = "bold"))+
ggtitle("Number of cells")
I believe it is worth noting the metadata has the sample column, but all of the values are "N/A". This column was added earlier using the following code:
metadata$sample <- NA
metadata$sample[which(str_detect(metadata$cellIDs, "^c2_"))] <- "c2"
The cell IDs were added to the metadata using
metadata$cellIDs <- rownames(metadata)
If there is any further code missing that you may need to solve this issue, let me know! Restarting and redownloading R + the packages did not work.
Output of dput(head(metadata))
structure(list(seq_folder = structure(c(1L, 1L, 1L, 1L,1L,1L),levels = "SeuratProject", class = "factor"), nUMI = c(5621, 7010, 1360, 1849, 1062, 10906), nGene = c(1901L, 2241L, 630L, 1009L, 633L, 3036L), log10GenesperUMI = c(0.874438700026547, 0.871213604555057, 0.893347946622289, 0.91948245341875,0.925739735597602, 0.862454250595566), mitoratio =c(0.0158334815869062,0.00756062767475036, 0.0301470588235294, 0.018388318009735,0.0715630885122411,0.0151292866312122), percent.mt = c(1.58334815869062, 0.756062767475036,3.01470588235294, 1.8388318009735, 7.15630885122411, 1.51292866312122), cellIDs =c("AAACCTGAGCAGGCTA-1", "AAACCTGAGGTGCTAG-1", "AAACCTGGTAGCGTGA-1", "AAACCTGGTTAAGTAG-1", "AAACCTGTCGCTGATA-1", "AAACGGGAGATGCCAG-1"), sample =c(NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,NA_character_)), row.names = c("AAACCTGAGCAGGCTA-1", "AAACCTGAGGTGCTAG-1", "AAACCTGGTAGCGTGA-1", "AAACCTGGTTAAGTAG-1", "AAACCTGTCGCTGATA-1", "AAACGGGAGATGCCAG-1"), class = "data.frame")
You can avoid this error with all-missing data by "setting" a manual fill scale:
data = data.frame(x = NA_character_)
## same error as in the question
ggplot(data, aes(x = x, fill = x)) +
geom_bar()
## no error
ggplot(data, aes(x = x, fill = x)) +
geom_bar() +
scale_fill_manual()

Combining Text_Grob with ggplot via grid_arrange - delete Text_grob-Margins

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)

Plot doesn't show negative values

I am doing the map of the world showing profit and loss from different countries.
I already plotted the map, I prepared and joined data, Im at the final step.
My dataset is 'data_profit', 'Total_profit' are values Im using (negative and positive ones)- and it's used to fill the map with colors, depending on the value.
Rest of the code is map plotting.
ditch_the_axes <- theme(
axis.text = element_blank(),
axis.line = element_blank(),
axis.ticks = element_blank(),
panel.border = element_blank(),
panel.grid = element_blank(),
axis.title = element_blank()
)
terra<-ggplot(data_profit, aes( x = long, y = lat, group = group )) +
geom_polygon(aes(x = long, y = lat,fill = Total_profit),color = "black")+
coord_fixed(1.3) +
theme_bw() +
ditch_the_axes+
scale_fill_gradient2( low="black", high="red", space ="Lab" )
data_profit <-
structure(list(long = c(-69.8991241455078, -69.8957061767578,
-69.9421920776367, -70.004150390625, -70.0661163330078, -70.0508804321289
), lat = c(12.4520015716553, 12.4229984283447, 12.4385251998901,
12.50048828125, 12.5469722747803, 12.5970697402954), group = c(1,
1, 1, 1, 1, 1), order = 1:6, region = c("Aruba", "Aruba", "Aruba",
"Aruba", "Aruba", "Aruba"), Total_profit = c(0, 0, 0, 0, 0, 0
)), row.names = c(NA, 6L), class = "data.frame")
and this is the output map:
So, the thing is the final map doesn't show the negative values (which should be in shade of black and grey). I checked whether 'Total_profit' values are numeric (with is.finite and is.numeric).
Do you have any idea what to change in the code?
Your question is unfortunately not reproducible, so I created some different sample data. I also suggest using "world map" and geom_map instead of geom_polygon (see below).
I assume the problem in your plot is a combination of missing values and the lack of correct limits in scale_..._gradient. Using scale_...gradientn comes with another problem - the asymmetric midpoint. (see here)
library(tidyverse)
library(scales) #load this for the mid-point problem and using scales::rescale (see below)
WorldData <- map_data('world') #easier way to draw countries than using geom_polygon
# In the next steps I am merging your profit data with the world map. I am creating a different sample data frame
data_profit <- data.frame(region = sample(WorldData$region,6), Total_profit = c(-5, -3, 0, 3, 5, 10))
map_profit <- dplyr::left_join(WorldData, data_profit, by ='region')
#> Warning: Column `region` joining character vector and factor, coercing into
#> character vector
# This plot is the easier one - using scale_fill_gradient(...). No mid-point problem. Note I am specifying the NA color using na.value.
# I am also specifying the limits using limits = ... I am not hard coding this, giving more flexibility for future graphs.
ggplot() +
geom_map(data = map_profit, map = WorldData,
aes(x = long, y = lat, map_id = region, fill = Total_profit, na.rm = FALSE)) +
scale_fill_gradient(low="black", high="red", na.value = 'blue',
limits = c(min(map_profit$Total_profit), max(map_profit$Total_profit)))
#> Warning: Ignoring unknown aesthetics: x, y, na.rm
# The next plot comes with the problem of an asymmetric mid-point
# I therefore rescale the values using rescale
ggplot() +
geom_map(data = map_profit, map = WorldData,
aes(x = long, y = lat, map_id = region, fill = Total_profit, na.rm = FALSE)) +
scale_fill_gradientn(colors = c("black", 'white', "red"), na.value = 'blue',
values = rescale(c(min(map_profit$Total_profit, na.rm = TRUE),0, max(map_profit$Total_profit,na.rm = TRUE))),
limits = c(min(map_profit$Total_profit), max(map_profit$Total_profit)))
#> Warning: Ignoring unknown aesthetics: x, y, na.rm
Created on 2019-07-11 by the reprex package (v0.3.0)

ggplot2 Line graph legend text labels

Hello I have the following data below and want to create a ggplot and remove the legend. I also want the legend labels to appear at the end of the geom_line (but ensure the full text can be seen - either by creating more room or reducing text size or both).
library(ggplot2)
library(scales)
library(broom)
UKStyleCumRet<-structure(c(0, -0.000585875039538108, -0.006962293751684, -0.00487316877934685,
-0.0109322156426903, -0.00954861380031302, -0.00863618174408887,
-0.0126160092579903, -0.00346746110207252, -0.00698804834931765,
0, 0.00642130648368866, 0.0104608988908397, 0.0123164416591228,
0.0180710928245018, 0.0211313335579064, 0.0218241871758766, 0.0273053649897337,
0.0240991442158665, 0.021318026563254, 0, -0.0034821589928784,
-0.00271401741869348, -0.0052708110221289, -0.00802020396258762,
-0.00668050200086479, -0.00213736634044293, 0.00124544742777655,
0.0047421495214317, 0.00280451017173089, 0, 0.00708163636457226,
0.0092146297198139, 0.0146175909198509, 0.0134244056872652, 0.00981198385176496,
0.00687693458035366, 0.00814732987224276, 0.0113145349249557,
0.0115596102361639, 0, -0.00147125756270416, -0.00193209555472618,
-0.000413483341123344, 0.00397062028565909, 0.0162993066081654,
0.0244747264738796, 0.0384739793054933, 0.0368483148925325, 0.0395193224980617,
0, -0.00509324778817288, -0.0129206103387607, -0.0153404412987002,
-0.0115197832717627, -0.020793371655729, -0.0168090662065323,
-0.0152573615095838, -0.0226830591525301, -0.0251846595390262,
0, 0.00822555974347772, 0.00614539079362508, 0.000254730582853524,
0.0172546701472243, 0.0109266512888126, 0.0194770984091213, 0.0259083822721515,
0.0211296899871345, 0.0246010209576302, 0, -0.00346737847383671,
-0.00873995016754447, -0.0139191247002052, -0.0136553668938997,
-0.0122788514168595, -0.012192010337693, -0.0127271782491021,
-0.0220646485936103, -0.0218854932200848, 0, 0.00177167104904052,
-0.00680567977636182, -0.0125590474529261, -0.0150206907148072,
-0.0256276241816732, -0.0233943013777757, -0.0253102426751336,
-0.0322222349862453, -0.0341522649085629), index = structure(c(1485820800,
1488240000, 1490918400, 1493337600, 1496188800, 1498780800, 1501459200,
1504137600, 1506643200, 1507248000), tzone = "UTC", tclass = "Date"), .indexCLASS = "Date", tclass = "Date", .indexTZ = "UTC", tzone = "UTC", class = c("xts",
"zoo"), .Dim = c(10L, 9L), .Dimnames = list(NULL, c("Exchange Rate Sensitivity",
"Growth", "Leverage", "Liquidity", "Medium-Term Momentum", "Short-Term Momentum",
"Size", "Value", "Volatility")))
Current Code:
UKCum<-tidy(UKStyleCumRet)
UKCum$index<-as.POSIXct(UKCum$index, tz = "UTC")
ggplot(data=UKCum, aes(x=index, y=value, color=series))+ geom_line(lwd=2) +
scale_x_datetime(labels = date_format("%Y-%b"), breaks = date_breaks("1 month")) + geom_dl(aes(label = series), method = list(dl.combine("last.points")))
Removing the legend is done by adding theme(legend.position = "none") to your plot code. You can extend the x axis by specifying axis limits in the scale_x_datetime() line to ensure your labels are not cut off.
Also, you need to add an origin when you use as.POSIXct to format numeric times
UKCum$index <- as.POSIXct(UKCum$index, tz = "UTC",
origin = "1970-01-01 00:00:00") #add origin to times
ggplot(data = UKCum, aes(x = index, y = value, color = series)) +
geom_line(lwd = 2) +
scale_x_datetime(date_breaks = "1 month", date_labels = "%Y-%b",
#set high upper x limit to provide room for labels
#may need to adjust depending on size you export graph as
limits = c(min(UKCum$index), as.POSIXct("2018-05-01"))) +
geom_dl(aes(label = series), method = list(dl.combine("last.points")))+
theme(legend.position = "none") #remove legend
the resulting plot:
Unable to reproduce your code here. Anyway, try directlabels package.
install.packages('directlabels')
p <- <draw your plot here>
directlabels::directlabel(p, 'last.qp')
You can adjust size and other properties by listing the second argument just like this:
directlabels::directlabel(p, list('last.qp', cex = .5, vjust = 0, hjust = 1)
More properties are available.

Axis labels and title clipped in barplot clipped with plotly in Rshiny

I am having certain issues while converting ggplot2 plots to plotly plots.
Here is my code:
> dput(dat.c)
structure(list(Cell_Line = structure(1:15, .Label = c("NBLS",
"NBSD", "NGP", "NLF", "RPE1", "RPE1MYCN40HT", "RPE1MYCNWT", "RPE1WT40HT",
"SKNAS", "SKNDZ", "SKNFI", "SKNKAN", "SKNSH", "SMSSAN", "SY5Y"
), class = "factor"), A1CF = c(5.10772389542502, 5.04909249557583,
5.16367852798093, 5.14220860530212, 5.25310652067225, 5.26436607107436,
5.230991944454, 5.4310065318786, 5.18630235564568, 5.02696275142877,
5.04518295317946, 5.15650800484188, 5.18630235564568, 5.18630235564568,
5.04905014785891), A2M = c(5.95668979157631, 5.59054925920344,
5.87084903365957, 5.85359773104682, 5.94551823960579, 5.82444459419149,
5.69488212149351, 5.70563676209623, 5.81016207843128, 5.66186721932247,
5.62134775395947, 5.62471305571508, 5.67165736680416, 5.76130826308792,
5.88006576048066), A2ML1 = c(5.56172395998964, 5.50076886952901,
5.7884753846352, 5.86613223339835, 5.82836474266047, 5.62750510524894,
5.76666636363946, 5.95103526370421, 5.58407662670697, 5.44780492507868,
5.35529657578242, 5.58813057293296, 5.67254168845041, 5.68685275370324,
5.6859273460443), A4GALT = c(6.73058652581215, 6.57480531818191,
6.70607981578649, 6.97173508307211, 7.0975112557987, 6.8286006127757,
6.56835917368749, 7.07629253436335, 6.66209247382635, 6.5876785423068,
6.59571996076717, 6.46673750407667, 6.70110916967979, 6.85058340238055,
6.59506833206593), A4GNT = c(4.87275116647384, 4.60002647258705,
4.99494601675408, 4.69477600401491, 4.7985530619801, 4.8349540959233,
4.77659739577691, 4.95071744980212, 4.77868342368918, 4.8025955817638,
4.87887068068956, 4.84258505663777, 4.84258505663777, 4.84616620572434,
4.66050997534254)), .Names = c("Cell_Line", "A1CF", "A2M", "A2ML1",
"A4GALT", "A4GNT"), row.names = c(NA, -15L), class = "data.frame")
gene1 <- 'A2M'
# modify gene name, dashes present in most of them
gene1.mut <- paste('`',gene1,'`',sep='')
# ggplot
p <- ggplot(dat.c, aes_string(x='Cell_Line', y=gene1.mut, fill='Cell_Line')) + geom_bar(stat="identity") + theme(axis.text.x = element_text(angle=90)) + ggtitle(gene1)
ggplotly(p)
This generates a figure like this:
As you can see, the one bar with X label RPE1MYCN40HT is not shown completely. Also the X and Y axis titles are clipped. How do I adjust the X axis labels and title so that they are not clipped? I do want to stick with ggplotly() instead of plot_ly() if that is possible.
Try to adjust plot.margins:
# ggplot
ggplot(dat.c, aes_string(x='Cell_Line', y=gene1.mut, fill='Cell_Line')) +
geom_bar(stat = "identity") +
theme(axis.text.x = element_text(angle=90),
plot.margin = unit(c(3, 3, 3, 3), "cm")) +
ggtitle(gene1)
When window is small then Xaxis label is overlapped with X labels, but when window is big it doesn't.

Resources