ggplot2 Line graph legend text labels - r

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.

Related

Setting time limits on axis removes all values

I have this simple data:
structure(list(ID = 1:2, timing = structure(c(1654641111.14,
1654640774.523), tzone = "CET", class = c("POSIXct", "POSIXt"))), class = "data.frame", row.names = c(NA,
-2L))
ID timing
1 1 2022-06-08 00:31:51.140
2 2 2022-06-08 00:26:14.523
When I plot using ggplot2, I get this:
ggplot(df_test,
aes(x = ID,
y = timing)) +
geom_point()
But when I set limits, the graph is empty:
lims <- as.POSIXct(strptime(c("35:00", "25:00"),
format = "%M:%OS",
tz = "CET"))
ggplot(df_test,
aes(x = ID,
y = timing)) +
geom_point() +
scale_y_datetime(limits = lims)
Warning message:
Removed 2 rows containing missing values (geom_point).
I tried to find any solution, but I can't figure out why the limits remove all my values. Does anyone have a solution?
This is simply due to your limits being round the wrong way (they should be earliest, latest whereas you have latest, earliest).
So you can do:
ggplot(df_test,
aes(x = ID,
y = timing)) +
geom_point() +
scale_y_datetime(limits = rev(lims))

ggplotly() does not display geom_vline / geom_hline when data is POSIXct

I am trying to make a graph with "time markers". These time markers are vertical lines for certain dates. Time data are POSIXct format. I would like to use the awesome interactive interface of Plotly and use my ggplot objects in it.
The problem is that these "time markers" doesn't show in after using ggplotly(). I ave already tried with plotly::add_segments() but it does not work.
Here are two reproductible examples :
1. With non-POSIXct data it works fine
# dummy dataset
df2 = data.frame(id = 1:10, measure = runif(10, 0, 20))
events2 = data.frame(number = c(2,3,8))
# ggplot graph
p2 = ggplot() + geom_line(data = df2, aes(x = id, y = measure)) +
geom_vline(data = events2, aes(xintercept = events2$number), color = "red")
p2
# plotly graph that displays the geom_vline properly
ggplotly(p2)
2. With POSIXct data is doesn't display the correct result
# dummy dataset
df = data.frame(date = seq(as.POSIXct("2017-07-01", tz = "UTC", format = "%Y-%m-%d"),
as.POSIXct("2018-04-15", tz = "UTC", format = "%Y-%m-%d"),
"1 month"),
measure = runif(10, 0, 20))
events = data.frame(date_envents = as.POSIXct(c("2017-10-12", "2017-11-12", "2018-03-15"), tz = "UTC", format = "%Y-%m-%d"))
# ggplot graph
p = ggplot() + geom_line(data = df, aes(x = date, y = measure)) +
geom_vline(data = events, aes(xintercept = events$date), color = "red")
p
# plotly graph that does not display the geom_vline properly
ggplotly(p)
I have seen some workaround (like this one : Add vertical line to ggplotly plot) but it is "complicated". Is there a more simple way to solve this problem ?
I am using Windows 10 with R version 3.5.0, RStudio and the following packages :
library(tidyverse) and library(plotly)
A simple workaround is to set the xintecept of the geom_vline to numeric.
sample data
df = data.frame(date = seq(as.POSIXct("2017-07-01", tz = "UTC", format = "%Y-%m-%d"),
as.POSIXct("2018-04-15", tz = "UTC", format = "%Y-%m-%d"),
"1 month"),
measure = runif(10, 0, 20))
events = data.frame(date_envents = as.POSIXct(c("2017-10-12", "2017-11-12", "2018-03-15"), tz = "UTC", format = "%Y-%m-%d"))
code
p = ggplot() + geom_line(data = df, aes(x = date, y = measure)) +
geom_vline(data = events, aes(xintercept = as.numeric(events$date)), color = "red")
result
ggplotly(p)

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)

How to add total line on a ggplot stack bar chart

I struggle to add a line on top with the total of this stacked barchart:
demandDriversdf = structure(list(year = structure(c(1356998400, 1388534400, 1420070400,
1451606400, 1483228800), tzone = "GMT", tclass = c("POSIXct",
"POSIXt"), class = c("POSIXct", "POSIXt")), one= c(12.4882571461364,
13.0984912135388, 12.1908055157534, 8.35335266490711, 4.38593754938248
), two= c(8.73113484771066, -4.34931681021004, -3.04955505552055,
-1.69136803847247, 3.06500464975644), three= c(0.0669199673877559,
-0.194488564805058, 0.721483847234409, 2.85829802643513, 6.14894193920574
), four= c(6.98748008979101, 3.7122726468811, -15.0029846301367,
-20.3768539034347, 9.38948700033012)), .Names = c("year", "one",
"two", "three", "four"), row.names = c("2013-01-01", "2014-01-01",
"2015-01-01", "2016-01-01", "2017-01-01"), class = "data.frame")
demandDriversdf2 = reshape2::melt(demandDriversdf, id.vars=c("year"), value.name="driver")
rowS = rowSums(demandDriversdf[,setdiff(colnames(demandDriversdf),"year")])
demandDriversdf2 = rbind(demandDriversdf2, data.frame(year = names(rowS), variable="Total", driver = rowS))
demandDriversdf2$year=substr(demandDriversdf2$year,1,4)
demandDriversdf2_1 <- subset(demandDriversdf2,driver >= 0 & variable!="Total")
demandDriversdf2_2 <- subset(demandDriversdf2,driver < 0 & variable!="Total")
gdemandDrivers = ggplot2::ggplot() +
ggplot2::geom_bar(data = demandDriversdf2_1, aes(x=year, y=driver, fill=variable),stat = "identity") +
ggplot2::geom_bar(data = demandDriversdf2_2, aes(x=year, y=driver, fill=variable),stat = "identity") +
ggplot2::geom_line(data = subset(demandDriversdf2, variable=="Total"), aes(x=year, y=driver)) +
ggplot2::scale_fill_brewer(palette = 2, type = "qual")
I get this strange warning
geom_path: Each group consists of only one observation. Do you need to
adjust the group aesthetic?
and ideally would like the line to be in black with also black points.
Just add group = 1 to aes() in geom_line():
library(ggplot2)
ggplot() +
geom_bar(data = demandDriversdf2_1, aes(x=year, y=driver, fill=variable),stat = "identity") +
geom_bar(data = demandDriversdf2_2, aes(x=year, y=driver, fill=variable),stat = "identity") +
geom_line(data = subset(demandDriversdf2, variable=="Total"),
aes(x=year, y=driver, group = 1)) +
scale_fill_brewer(palette = 2, type = "qual")
The reason for this:
For line graphs, the data points must be grouped so that it knows which points to connect. In this case, it is simple -- all points should be connected, so group=1. When more variables are used and multiple lines are drawn, the grouping for lines is usually done by variable.
Reference: Cookbook for R, Chapter: Graphs Bar_and_line_graphs_(ggplot2), Line graphs.

Map custom color gradient to POSIXct values

Data:
df1 <- structure(list(Index = 1:11, Duration = structure(c(1487577655,
1487577670, 1487577675, 1487577680, 1487577685, 1487577680, 1487577700,
1487577705, 1487577695, 1487577700, 1487577680), class = c("POSIXct",
"POSIXt"), tzone = "")), .Names = c("Index", "Duration"), class = "data.frame", row.names = 3:13)
Now I construct the graph as follows:
g1 <- ggplot(df1, aes(x = Index, y = Duration, color = Duration))+
geom_point()+
geom_line()+
scale_y_datetime(labels = date_format("%M:%S"))
As it is now, the color scale is set to the default "Black" to "Blue" gradient.
The problem is, I get an error trying to assign a custom gradient to the data.
For a non-POSIXct object:
scale_color_gradient("Duration", low = "#D80427", high = "#07a0ff", space = "Lab")
works, but I get the following error with the POSIXct object df1$Duration as the explanatory variable:
Error in Ops.POSIXt((x - from[1]), diff(from)) : '/' not defined
for "POSIXt" objects
Is there a different gradient function I need to use when graphing a POSIXct object?
You may use trans = time_trans():
library(ggplot2)
library(scales)
g1 +
scale_color_gradient("Duration", low = "#D80427", high = "#07a0ff",
trans = time_trans())
If you wish another format of the labels in the legend, add e.g. labels = format(pretty(df1$Duration), "%M:%S").
We can convert date to number for colour:
library(ggplot2)
library(scales)
ggplot(df1, aes(x = Index, y = Duration, color = as.numeric(Duration))) +
geom_point() +
geom_line() +
scale_y_datetime(labels = date_format("%M:%S")) +
scale_color_gradient("Duration", low = "#D80427", high = "#07A0FF",
labels = c("00", "10", "20", "30", "40"))
As suggested by #Henrik, to avoid hardcoding the labels use below:
# avoid hardcoding labels using pretty()
ggplot(df1, aes(x = Index, y = Duration, color = as.numeric(Duration))) +
geom_point() +
geom_line() +
scale_y_datetime(labels = date_format("%M:%S")) +
scale_color_gradient("Duration", low = "#D80427", high = "#07A0FF",
breaks = pretty(as.numeric(df1$Duration)),
labels = format(pretty(df1$Duration), "%M:%S"))

Resources