I have weekly time series for 2 variables. Now I need to add 2 vertical lines (geom_vline) at "2019-11-10" and "2020-04-26 date points.
structure(list(week = structure(c(18119, 18126, 18133, 18140,
18147, 18154, 18161, 18168, 18175, 18182, 18189, 18196, 18203,
18210, 18217, 18224, 18231, 18238, 18245, 18252, 18259, 18266,
18273, 18280, 18287, 18294, 18301, 18308, 18315, 18322, 18329,
18336, 18343, 18350, 18357, 18364, 18371, 18378, 18385, 18392,
18399, 18406, 18413, 18420, 18427, 18434, 18441, 18448, 18455,
18462, 18469, 18476, 18483, 18490, 18497, 18504, 18511, 18518,
18525, 18532, 18539, 18546, 18553, 18560, 18567, 18574, 18581,
18588, 18595, 18602, 18609, 18616, 18623, 18630, 18637, 18644,
18651, 18658, 18665, 18672, 18679, 18686, 18693, 18700, 18707,
18714, 18721, 18728, 18735, 18742, 18749, 18756, 18763, 18770,
18777, 18784, 18791, 18798, 18805, 18812, 18819, 18826, 18833,
18840, 18847, 18854, 18861, 18868, 18875, 18882, 18889, 18896,
18903, 18910, 18917, 18924, 18931, 18938, 18945, 18952, 18959,
18966, 18973, 18980, 18987, 18994, 19001, 19008, 19015, 19022,
19029, 19036, 19043, 19050, 19057, 19064, 19071, 19078, 19085,
19092, 19099, 19106, 19113, 19120, 19127, 19134, 19141, 19148,
19155, 19162, 19169, 19176, 19183, 19190, 19197, 19204, 19211,
19218, 19225, 19232, 19239, 19246, 19253, 19260, 19267), class = "Date"),
X = c(6L, 104L, 123L, 82L, 67L, 108L, 89L, 1153L, 311L, 346L,
220L, 219L, 184L, 257L, 585L, 342L, 197L, 184L, 351L, 278L,
120L, 204L, 206L, 146L, 216L, 186L, 171L, 200L, 198L, 170L,
192L, 139L, 136L, 414L, 256L, 306L, 281L, 221L, 271L, 311L,
315L, 277L, 342L, 394L, 493L, 855L, 1617L, 954L, 1143L, 1031L,
692L, 380L, 378L, 493L, 381L, 706L, 546L, 653L, 447L, 1004L,
499L, 442L, 926L, 564L, 568L, 755L, 581L, 572L, 780L, 601L,
739L, 563L, 300L, 454L, 727L, 733L, 673L, 648L, 614L, 754L,
827L, 719L, 874L, 692L, 752L, 536L, 658L, 817L, 913L, 813L,
844L, 811L, 977L, 877L, 818L, 673L, 1419L, 809L, 818L, 709L,
577L, 802L, 508L, 536L, 663L, 782L, 634L, 665L, 583L, 685L,
908L, 1013L, 903L, 965L, 981L, 1030L, 1205L, 1197L, 956L,
936L, 901L, 707L, 565L, 384L, 341L, 529L, 510L, 597L, 610L,
587L, 715L, 777L, 638L, 619L, 617L, 677L, 1118L, 1173L, 1025L,
655L, 1006L, 1129L, 811L, 773L, 796L, 993L, 891L, 900L, 1072L,
1182L, 947L, 743L, 759L, 616L, 584L, 613L, 597L, 734L, 671L,
1119L, 906L, 825L, 1109L, 1085L, 913L), Y = c(0L, 23L, 50L,
35L, 38L, 38L, 43L, 173L, 128L, 134L, 115L, 103L, 104L, 122L,
168L, 186L, 158L, 136L, 122L, 91L, 87L, 73L, 105L, 97L, 96L,
84L, 121L, 108L, 83L, 106L, 108L, 107L, 96L, 151L, 128L,
135L, 148L, 133L, 114L, 150L, 175L, 172L, 182L, 185L, 181L,
224L, 451L, 369L, 399L, 377L, 325L, 259L, 245L, 268L, 284L,
338L, 375L, 383L, 307L, 318L, 341L, 290L, 401L, 333L, 336L,
404L, 406L, 333L, 372L, 372L, 388L, 236L, 162L, 264L, 378L,
390L, 350L, 327L, 341L, 359L, 462L, 413L, 421L, 400L, 424L,
283L, 377L, 459L, 478L, 482L, 411L, 416L, 522L, 557L, 502L,
479L, 631L, 533L, 514L, 442L, 477L, 432L, 378L, 365L, 443L,
407L, 384L, 451L, 381L, 435L, 603L, 612L, 685L, 567L, 603L,
576L, 564L, 643L, 671L, 722L, 695L, 463L, 328L, 228L, 160L,
235L, 282L, 346L, 332L, 340L, 396L, 433L, 354L, 356L, 355L,
367L, 462L, 445L, 454L, 355L, 566L, 628L, 491L, 517L, 429L,
569L, 595L, 520L, 601L, 646L, 630L, 590L, 513L, 465L, 390L,
356L, 356L, 417L, 420L, 443L, 450L, 482L, 540L, 611L, 572L
)), row.names = c(NA, -165L), class = c("tbl_df", "tbl",
"data.frame"))
Firstly I convert it into xts object and next use ts_plot() for visualization
#Create xts object
df.xts <- xts(df[, 2:3], order.by = df.w$week)
#plot
library(TSstudio)
ts_plot(df.xts,
slider = TRUE)
I tried the following codes, but it give me the "NULL" in the output
+ geom_vline(xintercept = as.Date("2020-03-01"))
or
+ geom_vline(xintercept = as.POSIXct("2020-03-01"))
Edit
You could use the add_segments function from plotly. You could also add multiple lines by specifying vectors like this:
library(xts)
library(TSstudio)
library(dplyr)
library(plotly)
#Create xts object
df.xts <- xts(df[, 2:3], order.by = df$week)
# plot
ts_plot(df.xts) %>%
add_segments(y = c(0, 0, 0),
x = as.Date(c("2020-03-01", "2020-06-01", "2020-08-01")),
yend = c(1500, 1500, 1500),
xend = as.Date(c("2020-03-01", "2020-06-01", "2020-08-01")),
color = c('red', 'green', 'purple'),
showlegend = FALSE)
Created on 2022-10-12 with reprex v2.0.2
Because you are using xts data format, you can use the function addEventLines to add some vertical lines. Here is a reproducible example:
library(xts)
library(rtweet)
#Create xts object
df.xts <- xts(df[, 2:3], order.by = df$week)
# plot
plot(df.xts)
addEventLines(xts('', as.Date("2020-03-01")), pos = 2, srt = 90, col = 'blue')
Created on 2022-10-11 with reprex v2.0.2
I would like to add 2-row x-axis labels on my line plot, but not sure how to also incorporate the continuous labels and breaks I have for my 1st x-axis (Column "CYR" - short for calendar year). I'd like to have the 2nd axis (WYR) start half-way between the first label and the second (WYR = 2010 starts between CYR = 2009 -> 2010). I also wasn't sure how to add 2 x-axis titles either, maybe at the beginning of each x-axis row?
My data:
> dput(wet_pivot)
structure(list(WYR = c("WR_2010", "WR_2011", "WR_2012", "WR_2013",
"WR_2014", "WR_2015", "WR_2016", "WR_2017", "WR_2018", "WR_2019",
"WR_2020", "WR_2021", "WR_2022"), CYR = c(2009, 2010, 2011, 2012,
2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021), Season = structure(c(2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("DRY",
"WET"), class = "factor"), N = c(59L, 63L, 69L, 70L, 72L, 71L,
71L, 72L, 71L, 68L, 70L, 48L, 72L), n_mean = c(0.00696806934430411,
0.000649730847004026, 0.00288256551918419, 0.01141088388474,
0.000536174103147671, 0.00349584646220785, 0.000482925207291882,
0.00245359625194744, 0.00292096956686587, 0.00252817293686805,
0.00196286772014134, 0.00501799463867351, 0.00132244297252478
), n_median = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), sd = c(0.030946706350869,
0.00248965525641742, 0.0100973832581282, 0.051577934580242, 0.00331468784320076,
0.0266064084754242, 0.00212505905295283, 0.00675243933898364,
0.0119729983336735, 0.00639785127193391, 0.00930625647382774,
0.0136275258272549, 0.00543420856675111), se = c(0.00402891799826298,
0.000313667078988821, 0.00121558209746373, 0.0061647423020683,
0.000390639708573979, 0.00315759975690469, 0.000252198110662322,
0.000795782607691024, 0.00142093348159893, 0.000775853428563995,
0.00111231039833223, 0.00196696392618855, 0.000640427621321956
)), row.names = c(NA, -13L), class = "data.frame")
My attempt:
years <- seq(2009,2021,1)
labs <- seq(2009,2021,by=1)
myplot <- ggplot(wet_pivot, aes(x = CYR, y = n_mean)) +
geom_errorbar(aes(ymin=n_mean-se, ymax=n_mean+se), width=.2, color = "black") +
geom_point(color = "black", shape = 1, size = 2) +
geom_line(color = "black") +
scale_y_continuous(limits = c(0, 0.04), expand = expansion(mult = c(0, 0.05))) +
scale_x_continuous(breaks= years, labels = labs)
myplot +
annotate(geom = "text",
x = 1:nrow(wet_pivot),
y = min(wet_pivot$n_mean),
label = labs,
vjust = 3.5) +
annotate(geom = "text",
x = 1:nrow(wet_pivot),
y = min(wet_pivot$n_mean),
label = wet_pivot$WYR,
vjust = 5)
You indeed can use text annotations to substitute for x-axis labels. A few recommendations:
Set y = -Inf to automatically place text as bottom, independent of whatever data is on the plot. vjust can indeed be used to place it further down.
You'd need coord_cartesian(clip = "off") to actually show the text.
You can place 'titles' with an extra annotation layer, with x = -Inf to place it on the left.
I used the above for the example below. Maybe the text is still to big, so you could set the 8.8 / .pt to something smaller. (The / .pt translates between mm, which geom_text() uses, to points, which is used in theme)
library(ggplot2)
# wet_pivot <- structure(...) # omitted for previty
ggplot(wet_pivot, aes(x = CYR, y = n_mean)) +
geom_errorbar(aes(ymin=n_mean-se, ymax=n_mean+se), width=.2, color = "black") +
geom_point(color = "black", shape = 1, size = 2) +
geom_line(color = "black") +
scale_y_continuous(limits = c(0, 0.04), expand = expansion(mult = c(0, 0.05))) +
scale_x_continuous(breaks= years, labels = ~ rep("", length(.x))) +
annotate(geom = "text",
x = wet_pivot$CYR,
y = -Inf,
label = labs,
size = 8.8 / .pt,
vjust = 2.5) +
annotate(geom = "text",
x = wet_pivot$CYR,
y = -Inf,
label = wet_pivot$WYR,
size = 8.8 / .pt,
vjust = 4) +
# Titles
annotate(geom = "text",
x = -Inf,
y = -Inf,
label = c("CYR", "WYR"),
vjust = c(2.5, 4), hjust = 1,
size = 8.8 / .pt
) +
coord_cartesian(clip = "off") +
theme(
# Make extra space between axis ticks and axis title
axis.text.x.bottom = element_text(margin = margin(t = 8.8, b = 8.8))
)
Created on 2022-05-19 by the reprex package (v2.0.1)
I created a bar chart using geom_bar with "Group" on the x-axis (Female, Male), and "Values" on the y-axis. Group is further subdivided into "Session" such that there is "Session 1" and "Session 2" for both Male and Female (i.e. four bars in total).
Since all participants participated in Session 1 and 2, I overlayed a dotplot (geom_dot) over each of the four bars, to represent the individual data.
I am now trying to connect the observations for all participants ("PID"), between session 1 and 2. In other words, there should be lines connecting several sets of two-points on the "Male" portion of the x-axis (i.e. per participant), and "Female portion".
I tried this with "geom_line" (below) but to no avail (instead, it created a single vertical line in the middle of "Male" and another in the middle of "Female"). I'm not too sure how to fix this.
See code below:
ggplot(data_foo, aes(x=factor(Group),y=Values, colour = factor(Session), fill = factor(Session))) +
geom_bar(stat = "summary", fun.y = "mean", position = "dodge") +
geom_dotplot(binaxis = "y", stackdir = "center", dotsize = 1.0, position = "dodge", fill = "black") +
geom_line(aes(group = PID), colour="dark grey") +
labs(title='My Data',x='Group',y='Values') +
theme_light()
Sample data (.txt)
data_foo <- readr::read_csv("PID,Group,Session,Values
P1,F,1,14
P2,F,1,13
P3,F,1,16
P4,M,1,18
P5,F,1,20
P6,M,1,27
P7,M,1,19
P8,M,1,11
P9,F,1,28
P10,F,1,20
P11,F,1,24
P12,M,1,10
P1,F,2,26
P2,F,2,21
P3,F,2,19
P4,M,2,13
P5,F,2,26
P6,M,2,15
P7,M,2,23
P8,M,2,23
P9,F,2,30
P10,F,2,21
P11,F,2,11
P12,M,2,19")
The trouble you have is that you want to dodge by several groups. Your geom_line does not know how to split the Group variable by session. Here are two ways to address this problem. Method 1 is probably the most "ggploty way", and a neat way of adding another grouping without making the visualisation too overcrowded. for method 2 you need to change your x variable
1) Use facet
2) Use interaction to split session for each Group. Define levels for the right bar order
I have also used geom_point instead, because geom_dot is more a specific type of histogram.
I would generally recommend to use boxplots for such plots of values like that, because bars are more appropriate for specific measures such as counts.
Method 1: Facets
library(ggplot2)
ggplot(data_foo, aes(x = Session, y = Values, fill = as.character(Session))) +
geom_bar(stat = "summary", fun.y = "mean", position = "dodge") +
geom_line(aes(group = PID)) +
geom_point(aes(group = PID), shape = 21, color = 'black') +
facet_wrap(~Group)
Created on 2020-01-20 by the reprex package (v0.3.0)
Method 2: create an interaction term in your x variable. note that you need to order the factor levels manually.
data_foo <- data_foo %>% mutate(new_x = factor(interaction(Group,Session), levels = c('F.1','F.2','M.1','M.2')))
ggplot(data_foo, aes(x = new_x, y = Values, fill = as.character(Session))) +
geom_bar(stat = "summary", fun.y = "mean", position = "dodge") +
geom_line(aes(group = PID)) +
geom_point(aes(group = PID), shape = 21, color = 'black')
Created on 2020-01-20 by the reprex package (v0.3.0)
But everything gets visually not very compelling.
I suggest doing a few visualization tips to have a more informative chart. For example, I feel like having a differentiation of colors for PID will help us track the changes of each participant for different levels of other variables. Something like:
library(ggplot2)
ggplot(data_foo, aes(x = factor(Session), y = Values, fill = factor(Session))) +
geom_bar(stat = "summary", fun.y = "mean", position = "dodge") +
geom_line(aes(group = factor(PID), colour=factor(PID)), size=2, alpha=0.7) +
geom_point(aes(group = factor(PID), colour=factor(PID)), shape = 21, size=2,show.legend = F) +
theme_bw() +
labs(x='Session',fill='Session',colour='PID')+
theme(legend.position="right") +
facet_wrap(~Group)+
scale_colour_discrete(breaks=paste0('P',1:12))
And we have the following plot:
Hope it helps.