Using breaks in Scale_x_datetime - r

I am trying to plot a graph with limits from 2022-05-29 07:00:00 to 2022-05-29 07:00:00 PM on the x axis. Within these limits I would like 1 hour breaks. I am using scale_x_datetime so that I can graph as continuous variable instead of discrete. I created a vector with all breaks called axisorder.
c("2022-05-29 07:00:00", "2022-05-29 08:00:00", "2022-05-29 09:00:00",
"2022-05-29 10:00:00", "2022-05-29 11:00:00", "2022-05-29 12:00:00",
"2022-05-29 01:00:00", "2022-05-29 02:00:00", "2022-05-29 03:00:00",
"2022-05-29 04:00:00", "2022-05-29 05:00:00", "2022-05-29 06:00:00",
"2022-05-29 07:00:00", "2022-05-29 08:00:00")
here is my data
structure(list(Id = c("user_6", "user_6", "user_6", "user_6",
"user_6", "user_6", "user_6", "user_6", "user_6", "user_6", "user_6",
"user_6", "user_6", "user_6", "user_6", "user_6", "user_6", "user_6",
"user_6", "user_6", "user_6", "user_6", "user_6", "user_6"),
ActivityHour = structure(c(1653825600, 1653786000, 1653789600,
1653793200, 1653796800, 1653800400, 1653804000, 1653807600,
1653811200, 1653814800, 1653818400, 1653822000, 1653825600,
1653786000, 1653789600, 1653793200, 1653796800, 1653800400,
1653804000, 1653807600, 1653811200, 1653814800, 1653818400,
1653822000), class = c("POSIXct", "POSIXt"), tzone = ""),
TotalIntensity = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 28L, 13L,
13L, 143L, 20L, 11L, 19L, 54L, 9L, 19L, 24L, 19L, 9L, 0L,
0L, 0L, 0L), AverageIntensity = c(0, 0, 0, 0, 0, 0, 0, 0.466667,
0.216667, 0.216667, 2.383333, 0.333333, 0.183333, 0.316667,
0.9, 0.15, 0.316667, 0.4, 0.316667, 0.15, 0, 0, 0, 0)), row.names = c(NA,
-24L), class = "data.frame")
and last but not least my graph code
ggplot(data=df2, aes(x = ActivityHour, y = AverageIntensity)) +
geom_point() +
geom_line() +
theme(axis.text.x = element_text(angle = 45)) +
scale_x_datetime(breaks = "axisorder"), limits = c(as.POSIXct("2022-05-29 07:00:00"),as.POSIXct("2022-05-29 07:00:00")) +
ggtitle("Average Intensity user_6",
subtitle = "4-12-2016")
I just don't understand how to set up scale_x_datetime to have those limits and breaks? My x axis data is already formatted in (posixct.)
Any help would be appreciated!
UPDATE -- Here is where I am at..
I have converted my df2$ActivityHour to POSIXct
1653800400, 1653804000, 1653807600, 1653811200, 1653814800, 1653818400,
1653822000, 1653825600, 1653786000, 1653789600, 1653793200, 1653796800,
1653800400, 1653804000, 1653807600, 1653811200, 1653814800, 1653818400,
1653822000), class = c("POSIXct", "POSIXt"), tzone = "")
I then updated date_breaks = "hour" and changed my limits limits = c(as.POSIXct("2022-05-29 07:00:00"), as.POSIXct("....))
my new plot data looks like this
ggplot(data=df2, aes(x = ActivityHour, y = AverageIntensity)) +
geom_point() +
geom_line() +
theme(axis.text.x = element_text(angle = 45)) +
scale_x_datetime(date_breaks = "hour", limits = c(as.POSIXct("2022-05-29 07:00:00"),as.POSIXct("2022-05-29 19:00:00"))) +
ggtitle("Average Intensity user_6",
subtitle = "4-12-2016")
my plot comes out weird, as if df2$AverageIntensity is not plotting values correctly with $ActivityHour values. For instance, 13:00:00 no longer correlates to averageintensity of .31 INSTEAD there is no data. I understand this is because df2$ActivityHour values after 12:00:00 should be 13:00:00, 14:00:00, 15:00:00, etc. not back to 01:00:00. so I am looking for the quickest way to fix this?
UPDATE2 -- I fixed this with replace function
df2$ActivityHour <- replace(df2$ActivityHour,1,"2022-05-29 00:00:00")
and then replaced by position for each one.
Syntax: replace(list , position , replacement_value)

You have a couple of issues.
Firstly, your axisorder is in character format rather than the required POSIXct. Secondly, you have put "axisorder" in quotation marks, so ggplot thinks you want a single break at a location called "axisorder". You don't actually need axisorder anyway, since, as Stefan points out, you can use date_breaks = "hour"
Thirdly, and most importantly, you need to use 24-hour time formatting, so your second limit should be "2022-05-29 19:00:00". The same is also true for all the times in your data frame. The times after midday require 12 hours added on to them (and the initial value at midnight needs 12 hours removed):
df2$ActivityHour[14:24] <- df2$ActivityHour[14:24] + 12 * 3600
df2$ActivityHour[1] <- df2$ActivityHour[1] - 12 * 3600
ggplot(data=df2, aes(x = ActivityHour, y = AverageIntensity)) +
geom_point() +
geom_line() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_datetime(date_breaks = "hour",
limits = c(as.POSIXct("2022-05-29 07:00:00"),
as.POSIXct("2022-05-29 19:00:00"))) +
ggtitle("Average Intensity user_6", subtitle = "4-12-2016")

Related

r ggplot not recognizing date format

I have the following chart.
p1 <- ggplot(data = mydat, aes(x = time))+
geom_line(aes(y = sumabsdiff, colour = 'sumabsdiff'))+
geom_line(aes(y = windsize, col='windsize'))+
scale_x_time(breaks = scales::date_breaks('1 sec'))+ #('15 secs'))+
scale_color_manual(values=c('sumabsdiff' = 'black',
"windsize" = "red"))+
theme(legend.position = "top")
As you can see, the date is all messed up even though time seems perfectly fine to me.
> mydat$time
[1] "2022-09-19 12:44:47 UTC" "2022-09-19 12:44:48 UTC" "2022-09-19 12:44:49 UTC" "2022-09-19 12:44:50 UTC"
[5] "2022-09-19 12:44:50 UTC" "2022-09-19 12:44:50 UTC".
Any idea why?
Data:
mydf <- structure(list(time = structure(c(1663591487.801, 1663591488.614,
1663591489.626, 1663591490.097, 1663591490.202, 1663591490.717
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), bid = c(11735.68,
11735.18, 11734.93, 11734.43, 11734.3, 11734.43), ask = c(11737.58,
11737.08, 11736.83, 11736.33, 11736.2, 11736.33), flags = c(6,
6, 6, 6, 6, 6), typical = c(11736.63, 11736.13, 11735.88, 11735.38,
11735.25, 11735.38), row = 266:271, prevrow_short = c(258L, 258L,
260L, 261L, 262L, 265L), windsize = c(9, 10, 9, 9, 9, 7), diff = c(-0.119999999998981,
-0.5, -0.25, -0.5, -0.130000000001019, 0.130000000001019), absdiff = c(0.119999999998981,
0.5, 0.25, 0.5, 0.130000000001019, 0.130000000001019), sumabsdiff = c(3.60999999999694,
4.10999999999694, 3.72999999999593, 3.85999999999694, 3.61999999999898,
2.13000000000102), positive = c(FALSE, FALSE, FALSE, FALSE, FALSE,
TRUE), meanpos = c(0.444444444444444, 0.4, 0.333333333333333,
0.222222222222222, 0.222222222222222, 0.285714285714286), posdiff = c(0,
0, 0, 0, 0, 0.130000000001019), negdiff = c(0.119999999998981,
0.5, 0.25, 0.5, 0.130000000001019, 0), sumposdiff_short = c(1.36999999999898,
1.36999999999898, 1.23999999999796, 0.869999999998981, 0.869999999998981,
0.630000000001019), sumnegdiff_short = c(2.23999999999796, 2.73999999999796,
2.48999999999796, 2.98999999999796, 2.75, 1.5), power_short = c(0.37950138504159,
0.333333333333333, 0.332439678283999, 0.225388601036184, 0.240331491712493,
0.295774647887661), market_open = c(FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE), timediff = c(0.219000101089478, 0.812999963760376,
1.01199984550476, 0.470999956130981, 0.105000019073486, 0.515000104904175
), avgspeed = c(2.71247733209185, 2.42072135038066, 2.44698207323042,
2.3255814641193, 2.8019926211971, 2.14658085742225), relative_positive_diff = c(0.37950138504159,
0.333333333333333, 0.332439678283999, 0.225388601036184, 0.240331491712493,
0.295774647887661), timesec = structure(c(1663591487, 1663591488,
1663591489, 1663591490, 1663591490, 1663591490), class = c("POSIXct",
"POSIXt"), tzone = "UTC")), pandas.index = <environment>, row.names = 266:271, class = "data.frame")
By the way, the time actually includes milliseconds, perhaps that is the cause
?scale_x_time:
These are the default scales for the three date/time class. These
will usually be added automatically. To override manually, use
scale_*_date for dates (class 'Date'), scale_*_datetime for
datetimes (class 'POSIXct'), and scale_*_time for times (class
'hms').
Your time variable is class POSIXt, not hms, so you should be using scale_x_datetime instead.
ggplot(data = mydf, aes(x = time))+
geom_line(aes(y = sumabsdiff, colour = 'sumabsdiff'))+
geom_line(aes(y = windsize, col='windsize'))+
scale_x_datetime(breaks = "1 secs") +
scale_color_manual(values=c('sumabsdiff' = 'black',
"windsize" = "red"))+
theme(legend.position = "top")
You can format the axis labels with date_labels= and %-codes (listed in ?strptime):
ggplot(data = mydf, aes(x = time))+
geom_line(aes(y = sumabsdiff, colour = 'sumabsdiff'))+
geom_line(aes(y = windsize, col='windsize'))+
# scale_x_datetime(breaks = scales::date_breaks('1 sec'))+ #('15 secs'))+
scale_x_datetime(breaks = "1 sec", date_labels = "%H:%M:%S") +
scale_color_manual(values=c('sumabsdiff' = 'black',
"windsize" = "red"))+
theme(legend.position = "top")

plotting a 3D bubble graph on R

I am currently trying to plot a 3D bubble graph with 2 (then later i will try with 3) axes, as in excel, but on R (here is an example of the 3D bubble plot i am trying to plot) :
https://fr.extendoffice.com/documents/excel/2017-excel-create-bubble-chart.html
library(ggplot2)
library(scales)
p <- ggplot(plot_3D, aes(x = var_2020_2021_valeur, y = var_2020_2021_CA)) +
geom_point(aes(color = Specialite, size = CA.annee.N), alpha = 0.5) +
scale_color_manual(values = c("#00AFBB", "#E7B800", "#FC4E07",
"#FFB5C5", "#BF87B3", "#7F5AA2", "#3F2D91", "#000080",
"#2468A0", "#a32cc4", "#9073db", "#c51f5d",
"#5800ff", "#4455ff", "#48ff50")) +
scale_size(range = c(0.5, 12)) + # Réglage de la plage de tailles des points
ylim(-100, 100) +
xlim (-100, 100) +
geom_hline(yintercept=0) +
geom_vline(xintercept=0) +
scale_y_continuous(labels = percent) +
scale_x_continuous(labels = percent)
I get the following message of error :
"Scale for 'y' is already present. Adding another scale for 'y',
which
will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x',
which
will replace the existing scale."
Even when i abandon the two last lines of code, it doesn't work...
Here is the structure of my dataset plot_3D :
structure(list(Specialite = c("ANESTHESIE REANIMATION", "Autres",
"CHIRURGIE GENERALE ET VISCERALE", "CHIRURGIE PLASTIQUE", "GASTRO ENTEROLOGIE",
"GYNECOLOGIE OBSTETRIQUE", "IMAGERIE", "MAXILLO STOMATO", "MEDECINE GENERALE et
INTERNE",
"OPHTALMOLOGIE", "ORL", "ORTHOPEDIE", "PNEUMOLOGIE", "URGENTISTE",
"UROLOGIE"), CA.annee.N = c(64310L, 25298L, 1205537L, 42020L,
3694964L, 344370L, 3454L, 588033L, 228439L, 1849804L, 27358L,
2739286L, 0L, 916L, 432907L), Nombre.de.sejours.annee.N = c(171L,
34L, 1504L, 56L, 9224L, 682L, 9L, 1103L, 888L, 2276L, 57L, 4068L,
0L, 2L, 720L), CA.annee.N.1 = c(50135L, 454L, 790559L, 15531L,
2644858L, 304242L, 3026L, 402195L, 459813L, 1308933L, 20597L,
2269691L, 0L, 3901L, 318352L), Nombre.de.sejours.annee.N.1 = c(150L,
1L, 1067L, 25L, 7276L, 627L, 9L, 802L, 1918L, 1693L, 43L, 3519L,
0L, 7L, 547L), CA.annee.N.2 = c(48583L, 453L, 941610L, 16675L,
3140507L, 385813L, 2950L, 642017L, 691982L, 1704005L, 51602L,
2261368L, 7145L, 4648L, 308169L), Nombre.de.sejours.annee.N.2 = c(154L,
1L, 1264L, 28L, 8317L, 831L, 8L, 1286L, 3231L, 2269L, 127L, 3610L,
26L, 10L, 551L), CA_par_sejour_N = c(376.081871345029, 744.058823529412,
801.553856382979, 750.357142857143, 400.581526452732, 504.941348973607,
383.777777777778, 533.121486854034, 257.251126126126, 812.743409490334,
479.964912280702, 673.374139626352, NaN, 458, 601.259722222222
), CA_par_sejour_N1 = c(334.233333333333, 454, 740.917525773196,
621.24, 363.504398020891, 485.234449760766, 336.222222222222,
501.490024937656, 239.735662148071, 773.14412285883, 479, 644.981813015061,
NaN, 557.285714285714, 581.99634369287), CA_par_sejour_N2 = c(315.474025974026,
453, 744.944620253165, 595.535714285714, 377.600937838163, 464.275571600481,
368.75, 499.235614307932, 214.169606932838, 750.993829881005,
406.314960629921, 626.417728531856, 274.807692307692, 464.8,
559.290381125227), var_2020_2021_valeur = c(0.125207553640259,
0.638896087069189, 0.0818395145215454, 0.207837780659878, 0.101999119223065,
0.0406131494220115, 0.141440846001322, 0.063074957314078, 0.0730615704860669,
0.051218505658529, 0.00201443064864667, 0.0440203522616658, NaN,
-0.178159446295822, 0.0330987964754596), var_2020_2021_CA = c(0.282736611149895,
54.7224669603524, 0.524917178856986, 1.70555662867813, 0.397036816343259,
0.131895004634469, 0.141440846001322, 0.462059448774848, -0.503191514811456,
0.413215191304673, 0.328251687138904, 0.206898207729598, NaN,
-0.765188413227378, 0.35983753832236)), class = "data.frame", row.names = c(NA,
-15L))
Could anyone help ?
You should remove xlim and ylim because they can be used when you don't specify anything else on your axis. So your could add the limits to both scale_*_continuous in the limits arguments like this:
library(ggplot2)
library(scales)
p <- ggplot(plot_3D, aes(x = var_2020_2021_valeur, y = var_2020_2021_CA)) +
geom_point(aes(color = Specialite, size = CA.annee.N), alpha = 0.5) +
scale_color_manual(values = c("#00AFBB", "#E7B800", "#FC4E07",
"#FFB5C5", "#BF87B3", "#7F5AA2", "#3F2D91", "#000080",
"#2468A0", "#a32cc4", "#9073db", "#c51f5d",
"#5800ff", "#4455ff", "#48ff50")) +
scale_size(range = c(0.5, 12)) + # Réglage de la plage de tailles des points
geom_hline(yintercept=0) +
geom_vline(xintercept=0) +
scale_y_continuous(labels = percent, limits = c(-100, 100)) +
scale_x_continuous(labels = percent, limits = c(-100, 100))
p
#> Warning: Removed 1 rows containing missing values (geom_point).
Created on 2022-07-12 by the reprex package (v2.0.1)

R ggplot2 facet_wrap() with scales = "free", but each panel having fixed

I want to produce a figure that will have several scatterplots. Each scatterplot should have its own axis limits, but I want the aspect ratio of each plot to be 1 so that the 1:1 line goes through the plot at a 45 degree angle.
Here's an example of what I have going on:
met <- structure(list(datetime = structure(c(946756800, 946756800, 946756800,946756800, 946756800, 946756800, 946756800, 960465600, 960465600,960465600), class = c("POSIXct", "POSIXt"), tzone = "UTC"), Met_Parameter = c("1/MO l","albedo", "Bowen r", "conv mix h", "mech mix h", "MO l", "sens h flux","wind s", "wstar", "z0"), `Original Met` = c(0.0746268656716418,0.15, 0.8, -999, 24, 13.4, -0.7, 4, 1.2, 1), `Converted Met` = c(-0.0105263157894737,0.15, 0.8, 600, 367, -95, 21.6, 4, 1.2, 1)), row.names = c(1L,2L, 3L, 4L, 5L, 6L, 7L, 1054L, 1055L, 1056L), class = "data.frame")
pOUT <-
ggplot2::ggplot(data = met,
aes(x = `Original Met`,
y = `Converted Met`)) +
ggplot2::geom_point()+
ggplot2::geom_abline(intercept = 0,
slope = 1
) +
ggplot2::facet_wrap("Met_Parameter",
scales = "free") +
ggplot2::ggtitle("Comparison of Original Meteorology Versus Up Over Down Meterology") +
ggplot2::theme_bw()
What I am missing still is how to make the x and y axes fixed within the plot.
Thanks!

Add character variable (weekdays) to plot

I want to add on this plot the weekday as text on top of the bars.
The only function to add text in ggplot I found, is "annotate", which does not work the way I want.
It should look like this:
Plot with weekdays
geom_text gives me this
Geom_text
My code:
ggplot(data = filter(T2G2_dayav, site %in% c("S17S", "S17N"), !is.na(distance)),
mapping = aes(as.factor(x = date_days))) +
geom_col(mapping = aes(y = T2pn_av, fill = as.factor(distance)),
position = position_dodge(width = 0.9)) +
theme_bw() + ylab("Particle Number (#/cm³), day-av") + xlab("Date") +
scale_y_continuous(limits = c(0, 30000)) +
scale_fill_discrete(name = "T2, Distance from road (m)") +
scale_color_grey(name = "Reference intrument G2") +
ggtitle("Day-averaged Particle Number (PN) per distance")
the head of my data:
distance date_days site T2pn_av T2pn_avambient T2wdir_med weekday Date G2pn_av G2pn_min G2pn_max G2ws_av G2ws_min G2ws_max G2wdir_med
<int> <dttm> <chr> <dbl> <dbl> <dbl> <chr> <dttm> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 -10 2017-07-18 S17N 28814.83 16917.831 110 Di 2017-07-18 13655.29 4621 105100 0.6781284 0 3.6 51.0
2 -10 2017-07-19 S17N 24210.95 15565.951 100 Mi 2017-07-19 10627.73 2908 67250 1.3673618 0 5.5 70.0
3 -10 2017-07-24 S17N 16143.44 7907.442 80 Mo 2017-07-24 11686.54 3582 55080 0.8178753 0 4.8 95.5
4 -10 2017-07-29 S17N 11762.56 5574.563 270 Sa 2017-07-29 12180.73 5413 45490 1.0304985 0 5.7 265.0
5 -10 2017-07-30 S17N 12138.22 6360.225 290 So 2017-07-30 10404.75 6113 23860 1.2385791 0 6.6 274.0
6 -10 2017-07-31 S17N 13815.32 9008.320 270 Mo 2017-07-31 11849.89 4595 46270 0.8554044 0 4.4 230.0
dput(head(T2G2_dayav))
structure(list(distance = c(-10L, -10L, -10L, -10L, -10L, -10L
), date_days = structure(c(1500328800, 1500415200, 1500847200,
1501279200, 1501365600, 1501452000), class = c("POSIXct", "POSIXt"
), tzone = "Europe/Berlin"), site = c("S17N", "S17N", "S17N",
"S17N", "S17N", "S17N"), T2pn_av = c(28814.8306772908, 24210.9512670565,
16143.442364532, 11762.5630630631, 12138.2247114732, 13815.3198380567
), T2pn_avambient = c(16917.8306772908, 15565.9512670565, 7907.44236453202,
5574.56306306306, 6360.22471147318, 9008.31983805668), T2wdir_med = c(110,
100, 80, 270, 290, 270), weekday = c("Di", "Mi", "Mo", "Sa",
"So", "Mo"), Date = structure(c(1500328800, 1500415200, 1500847200,
1501279200, 1501365600, 1501452000), class = c("POSIXct", "POSIXt"
), tzone = "Europe/Berlin"), G2pn_av = c(13655.2885517401, 10627.7329973352,
11686.5429216867, 12180.7308516181, 10404.7472642001, 11849.8893070109
), G2pn_min = c(4621, 2908, 3582, 5413, 6113, 4595), G2pn_max = c(105100,
67250, 55080, 45490, 23860, 46270), G2ws_av = c(0.678128438241936,
1.36736183524505, 0.817875347544022, 1.0304984658137, 1.23857912107,
0.855404388351763), G2ws_min = c(0, 0, 0, 0, 0, 0), G2ws_max = c(3.6,
5.5, 4.8, 5.7, 6.6, 4.4), G2wdir_med = c(51, 70, 95.5, 265, 274,
230)), .Names = c("distance", "date_days", "site", "T2pn_av",
"T2pn_avambient", "T2wdir_med", "weekday", "Date", "G2pn_av",
"G2pn_min", "G2pn_max", "G2ws_av", "G2ws_min", "G2ws_max", "G2wdir_med"
), row.names = c(NA, -6L), class = c("grouped_df", "tbl_df",
"tbl", "data.frame"), vars = c("distance", "date_days"), drop = TRUE, indices = list(
0L, 1L, 2L, 3L, 4L, 5L), group_sizes = c(1L, 1L, 1L, 1L,
1L, 1L), biggest_group_size = 1L, labels = structure(list(distance = c(-10L,
-10L, -10L, -10L, -10L, -10L), date_days = structure(c(1500328800,
1500415200, 1500847200, 1501279200, 1501365600, 1501452000), class = c("POSIXct",
"POSIXt"), tzone = "Europe/Berlin")), row.names = c(NA, -6L), class = "data.frame", vars = c("distance",
"date_days"), drop = TRUE, .Names = c("distance", "date_days"
)))
The idea is that you add a text on top of every bar (that's why vjust = 0, but you could also do vjust = -.5 to allow more space or vjust = 1.5 to put it in the bars, which is nice as well). The rest within the geom_text ist basically the same as in geom_col. But in general, you could put commonly used aesthetics in the first occurency within ggplot(aes(...)), as you already did with the x-value.
ggplot(data = filter(T2G2_dayav, site %in% c("S17S", "S17N"), !is.na(distance)),
mapping = aes(as.factor(x = date_days))) +
geom_col(mapping = aes(y = T2pn_av, fill = as.factor(distance)),
position = position_dodge(width = 0.9)) +
geom_text(aes(label = weekday, y = T2pn_av), vjust = -.5, # add these
position = position_dodge(width = 0.9)) + # lines
theme_bw() + ylab("Particle Number (#/cm³), day-av") + xlab("Date") +
scale_y_continuous(limits = c(0, 30000)) +
scale_fill_discrete(name = "T2, Distance from road (m)") +
scale_color_grey(name = "Reference intrument G2") +
ggtitle("Day-averaged Particle Number (PN) per distance")
The following should solve your problem with too many labels. It takes the highest label and places it in the center of the bars of that x-value. Find a plot below with additional rows added to your data:
T2G2_dayav <- rbind(T2G2_dayav %>% ungroup(), T2G2_dayav %>% ungroup() %>% mutate(distance = 5)) # add more observations for testing
T2G2_dayav <- T2G2_dayav %>% mutate(T2pn_av = ifelse(distance == 5, T2pn_av/2, T2pn_av)) # label only the highest bar
The following should work with your data:
ggplot(data = filter(T2G2_dayav, site %in% c("S17S", "S17N"), !is.na(distance)) %>%
group_by(date_days) %>% # group by days
mutate(weekday2 = ifelse(T2pn_av == max(T2pn_av), weekday, NA)), # within each day (group), only label the highest
mapping = aes(as.factor(x = date_days))) +
geom_col(mapping = aes(y = T2pn_av, fill = as.factor(distance)),
position = position_dodge(width = 0.9)) +
geom_text(aes(label = weekday2, y = T2pn_av), vjust = -.5, # add these
position = position_dodge(with = 0.9)) + # lines
theme_bw() + ylab("Particle Number (#/cm³), day-av") + xlab("Date") +
scale_y_continuous(limits = c(0, 30000)) +
scale_fill_discrete(name = "T2, Distance from road (m)") +
scale_color_grey(name = "Reference intrument G2") +
ggtitle("Day-averaged Particle Number (PN) per distance")

Function to label local extrema in ggplot2 line graph in R

I am plotting a time series and I would like to automatically label specific points such as the last point, and local extrema, the highest and lowest.
How would I wrap this in a function to automatically label key points. Specifically by adding more local extrema.
Here is an example dataset:
latest <- structure(list(ReleaseDate = structure(c(1363928400, 1364533200,
1365138000, 1365742800, 1366347600, 1366952400, 1367557200, 1368162000,
1368766800, 1369371600, 1369976400, 1370581200, 1371186000, 1371790800,
1372395600, 1373000400, 1373605200, 1374210000, 1374814800, 1375419600,
1376024400, 1376629200, 1377234000, 1377838800, 1378443600, 1379048400,
1379653200, 1380258000, 1380862800, 1381467600, 1382072400, 1382677200,
1383282000, 1383890400, 1384495200), class = c("POSIXct", "POSIXt"
), tzone = ""), Count = c(1746L, 1748L, 1738L, 1771L, 1758L,
1754L, 1764L, 1769L, 1769L, 1762L, 1771L, 1765L, 1771L, 1759L,
1748L, 1757L, 1759L, 1770L, 1776L, 1782L, 1778L, 1791L, 1776L,
1776L, 1767L, 1768L, 1761L, 1744L, 1756L, 1743L, 1739L, 1738L,
1742L, 1754L, 1762L)), .Names = c("ReleaseDate", "Count"), row.names = 150:184, class = "data.frame")
library(ggplot2)
libary(ddply)
last <- tail(latest, 1)
high <- subset(latest, Count == max(Count))
mid <- subset(latest[5:20,], Count == min(Count))
ggplot(latest, aes(ReleaseDate, Count)) + geom_line() +
geom_text(data = last, aes(ReleaseDate, Count), label = last$Count, vjust = -1) +
geom_text(data = high, aes(ReleaseDate, Count), label = high$Count, vjust = -.1) +
geom_text(data = mid, aes(ReleaseDate, Count), label = mid$Count, vjust = 1)
Here I've attempted to manually add specific points, but it would not be concise if I wanted to add 10 labels to a longer series.

Resources