Plotting time-series with Date labels on x-axis - r

I know that this question might be a cliche, but I'm having hard time doing it.
I've data set in the following format:
Date Visits
11/1/2010 696537
11/2/2010 718748
11/3/2010 799355
11/4/2010 805800
11/5/2010 701262
11/6/2010 531579
11/7/2010 690068
11/8/2010 756947
11/9/2010 718757
11/10/2010 701768
11/11/2010 820113
11/12/2010 645259
I want to create a time-series plot, with x-axis representing time & y-axis vists. Also, I want to mark the x-axis with date. The code I was using is the following:
dm$newday = as.POSIXct(strptime(dm$Day, format="%Y-%m-%d"))
plot(as.Date(dm$day),dm$visits)
axis.Date(1,Day,at=seq(as.Date("2010/10/30"), as.Date("2011/01/29"),by="days"))

1) Since the times are dates be sure to use "Date" class, not "POSIXct" or "POSIXlt". See R News 4/1 for advice and try this where Lines is defined in the Note at the end. No packages are used here.
dm <- read.table(text = Lines, header = TRUE)
dm$Date <- as.Date(dm$Date, "%m/%d/%Y")
plot(Visits ~ Date, dm, xaxt = "n", type = "l")
axis(1, dm$Date, format(dm$Date, "%b %d"), cex.axis = .7)
The use of text = Lines is just to keep the example self-contained and in reality it would be replaced with something like "myfile.dat" . (continued after image)
2) Since this is a time series you may wish to use a time series representation giving slightly simpler code:
library(zoo)
z <- read.zoo(text = Lines, header = TRUE, format = "%m/%d/%Y")
plot(z, xaxt = "n")
axis(1, dm$Date, format(dm$Date, "%b %d"), cex.axis = .7)
Depending on what you want the plot to look like it may be sufficient just to use plot(Visits ~ Date, dm) in the first case or plot(z) in the second case suppressing the axis command entirely. It could also be done using xyplot.zoo
library(lattice)
xyplot(z)
or autoplot.zoo:
library(ggplot2)
autoplot(z)
Note:
Lines <- "Date Visits
11/1/2010 696537
11/2/2010 718748
11/3/2010 799355
11/4/2010 805800
11/5/2010 701262
11/6/2010 531579
11/7/2010 690068
11/8/2010 756947
11/9/2010 718757
11/10/2010 701768
11/11/2010 820113
11/12/2010 645259"

I like using the ggplot2 for this sort of thing:
df$Date <- as.Date( df$Date, '%m/%d/%Y')
require(ggplot2)
ggplot( data = df, aes( Date, Visits )) + geom_line()

Your code has lots of errors.
You are mixing up dm$Day and dm$day. Probably not the same thing
Your column headings are Date and Visits. So you would access them (I'm guessing) as dm$Date and dm$Visits
In the date field you have %Y-%m-%d this should be %m/%d/%Y
The following code should plot what you want:
dm$newday = as.Date(dm$Date, "%m/%d/%Y")
plot(dm$newday, dm$Visits)

You can rotate the dates by hacking axis notations with text()
Lines <- "Date Visits
11/1/2010 696537
11/2/2010 718748
11/3/2010 799355
11/4/2010 805800
11/5/2010 701262
11/6/2010 531579
11/7/2010 690068
11/8/2010 756947
11/9/2010 718757
11/10/2010 701768
11/11/2010 820113
11/12/2010 645259"
dm <- read.table(textConnection(Lines), header = TRUE)
dm$Date <- as.Date(dm$Date, "%m/%d/%Y")
plot(Visits ~ Date, dm, xaxt = "n", type = "l")
axis(1,at=NULL, labels=F)
text(x = dm$Date, par("usr")[3]*.97, labels = paste(dm$Date,' '), srt = 45, pos = 1, xpd = TRUE,cex=.7)

It's possible in ggplot and you can use scale_date for this task
library(ggplot2)
Lines <- "Date Visits
11/1/2010 696537
11/2/2010 718748
11/3/2010 799355
11/4/2010 805800
11/5/2010 701262
11/6/2010 531579
11/7/2010 690068
11/8/2010 756947
11/9/2010 718757
11/10/2010 701768
11/11/2010 820113
11/12/2010 645259"
dm <- read.table(textConnection(Lines), header = TRUE)
dm <- mutate(dm, Date = as.Date(dm$Date, "%m/%d/%Y"))
ggplot(data = dm, aes(Date, Visits)) +
geom_line() +
scale_x_date(format = "%b %d", major = "1 day")

I like ggplot too.
Here's one example:
df1 = data.frame(
date_id = c('2017-08-01', '2017-08-02', '2017-08-03', '2017-08-04'),
nation = c('China', 'USA', 'China', 'USA'),
value = c(4.0, 5.0, 6.0, 5.5))
ggplot(df1, aes(date_id, value, group=nation, colour=nation))+geom_line()+xlab(label='dates')+ylab(label='value')

Related

Plotting/Mutating Data on R

I've trying to plot data that has been mutated into quarterly growth rates from nominal levels.
i.e the original dataset was
Date GDP Level
2010Q1 457
2010Q2 487
2010Q3 538
2010Q4 589
2011Q1 627
2011Q2 672.2
2011Q3 716.4
2011Q4 760.6
2012Q1 804.8
2012Q2 849
2012Q3 893.2
2012Q4 937.4
Which was in an excel file which I have imported using
dataset <- read_excel("xx")
Then, I have done the below in order to mutate it to quarter on quarter growth ("QoQ Growth):
dataset %>%
mutate(QoQ Growth= (GDP Level) / lag(GDP Level, n=1) - 1)
I would like to now plot this % growth across time, however I'm not too sure how what the geom_line code is for a mutated variable, any help would be really truly appreciated! I'm quite new to R and really trying to learn, thanks!
Something like this?
library(tidyverse)
df %>%
mutate(QoQGrowth = (GDPLevel) / lag(GDPLevel, n=1) - 1) %>%
ggplot(aes(factor(Date), QoQGrowth, group=1)) +
geom_line()
Output
Data
df <- structure(list(Date = c("2010Q1", "2010Q2", "2010Q3", "2010Q4",
"2011Q1", "2011Q2", "2011Q3", "2011Q4", "2012Q1", "2012Q2", "2012Q3",
"2012Q4"), GDPLevel = c(457, 487, 538, 589, 627, 672.2, 716.4,
760.6, 804.8, 849, 893.2, 937.4)), class = "data.frame", row.names = c(NA,
-12L))
Package zoo defines a S3 class "yearqtr" and has a function to handle quarterly dates, as.yearqtr. Combined with ggplot2's scale_x_date, the formating of quarterly axis labels becomes easier.
dataset <- read.table(text = "
Date 'GDP Level'
2010Q1 457
2010Q2 487
2010Q3 538
2010Q4 589
2011Q1 627
2011Q2 672.2
2011Q3 716.4
2011Q4 760.6
2012Q1 804.8
2012Q2 849
2012Q3 893.2
2012Q4 937.4
", header = TRUE, check.names = FALSE)
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(zoo))
library(ggplot2)
dataset %>%
mutate(Date = as.yearqtr(Date, format= "%Y Q%q"),
Date = as.Date(Date)) %>%
mutate(`QoQ Growth` = `GDP Level` / lag(`GDP Level`, n = 1) - 1) %>%
ggplot(aes(Date, `QoQ Growth`)) +
geom_line() +
scale_x_date(date_breaks = "3 months", labels = as.yearqtr) +
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))
#> Warning: Removed 1 row(s) containing missing values (geom_path).
Created on 2022-03-08 by the reprex package (v2.0.1)
Convert dataset to a zoo object z, use diff.zoo to get the growth, QoQ Growth, and then use autoplot.zoo with scale_x_yearqtr.
library(zoo)
library(ggplot2)
z <- read.zoo(dataset, FUN = as.yearqtr)
`QoQ Growth` <- diff(z, arith = FALSE) - 1
autoplot(`QoQ Growth`) +
scale_x_yearqtr(format = "%YQ%q", n = length(`QoQ Growth`)) +
xlab("")

Trying to format ggplot output

I am trying to plot WaterLevel vs Datetime (I formatted the datetime), however I get an error like
Error in seq.int(0, to0 - from, by) : 'to' must be a finite number
library(ggplot2)
library(scales)
library(shiny)
library(stringi)
file = "http://dd.weather.gc.ca/hydrometric/csv/SK/hourly/SK_hourly_hydrometric.csv"
skdat <- read.csv(file, head=T, sep=",", dec=".", stringsAsFactors = F)
colnames(skdat) <- c("ID", "Date", "WaterLevel", "Grade1", "Symbol1",
"QAQC-1", "DischargeDebit", "Grade2", "Symbol2",
"QAQC-2")
subds <- subset(skdat, ID=='05EF001')
subds$datetime <- as.POSIXct(subds$Date, format = "%Y-%m-%dT%H%m%S-06:00")
p2 <- ggplot(subds, aes(x = datetime, y = WaterLevel)) + geom_line()
p2
I have tried different formats and I know the data is good as it plots in a simple plot as well.
Use -
subds$datetime <- as.POSIXct(subds$Date, format = "%Y-%m-%dT%H:%M:%OS")#"%Y-%m-%dT%H:%m:%S-06:00")
This would cast your date properly to give the datetime column and not give NAs.
After this the plot will get generated -

ploting time series with day time in horizontal axis

Hi there I have some working code that selects data from a single station and plots it as a time series.in this data is a date time of the format:
28 11AC068 2018-08-30T02:15:00-06:00
29 11AC068 2018-08-30T02:20:00-06:00
file = "http://dd.weather.gc.ca/hydrometric/csv/SK/hourly/SK_hourly_hydrometric.csv"
skdat <- read.csv(file, head=T, sep=",", dec=".")
skdate <- skdat
colnames(skdat) <- c("ID", "Date", "Water.Level", "Grade.1", "Symbol.1",
"QA/QC-1", "Discharge/Debit", "Grade.2", "Symbol.2",
"QA/QC-2")
#There are 151 Factors of ID
str(skdat$ID)
skdat$Date <- as.Date(skdat$Date, "%h/%m")
#"05AH050","05EF001"#,..: 151 151 151 151 151 151 151 151 151 151 ...
plot.ts(subset(skdat, skdat$ID=='05EF001')$Water.Level, main="Plot TS of ID = 05EF001")
axis.Date(1, at=seq(min(skdat$Date), max(skdat$Date), by="hour"), format="%h-%m")
in the subset the date time is filtered out is there any way to keep that column in the data and use it to plot the horizontal axis just as hour min?
You could try something like this.
library(tidyverse)
file = "http://dd.weather.gc.ca/hydrometric/csv/SK/hourly/SK_hourly_hydrometric.csv"
skdat <- read.csv(file, head=T, sep=",", dec=".", stringsAsFactors = F)
colnames(skdat) <- c("ID", "Date", "Water.Level", "Grade.1", "Symbol.1",
"QA/QC-1", "Discharge/Debit", "Grade.2", "Symbol.2",
"QA/QC-2")
skdat %>% filter(ID=='05EF001') %>%
mutate(Date = gsub("-06:00$", "", Date) %>% lubridate::parse_date_time(., orders = "ymd HMS")) %>%
ggplot(aes(Date, Water.Level))+
geom_line()+
scale_x_datetime(breaks = "4 hours", date_labels = "%H:%M")
Created on 2018-09-01 by the reprex
package (v0.2.0).

Issues with multiple y axis ranges in plotly in R

I am attempting to plot multiple lines on the same graph in plotly. The problem is for every variable that is being plotted, plotly is creating new set of y axis values. Can this be solved. I want the same y axis for all the line plots that I create. Following is the code and the plot generated.
p1 <- plot_ly(data = st_data, x = ~Date) %>% add_lines(y = ~Close,name =
"Close") %>%
add_lines(y=~Bollinger,name="Bollinger")
In the graph the y axis has values ranging once from 61.85 to 65.90 and again from 62.15 to 65.49.
Ideally I am looking for the y axis values to be between 61.85 and 65.90 and the two lines plotted on the same axis.
Adding the input data:
Date Close Bollinger
1/30/2015 9:34 65.55 NA
1/30/2015 9:34 65.43 NA
1/30/2015 9:35 65.52 NA
1/30/2015 9:35 65.37 NA
1/30/2015 9:36 65.68 65.184
1/30/2015 9:36 65.4 65.303
1/30/2015 9:36 65.51 65.4155
1/30/2015 9:36 65.8 65.499
1/30/2015 9:36 65.6 65.548
Yes, your code should already work. I think sjakw is correct in that you have some other code that creates a problem. Try opening a new script, and paste the following code. You should get a plot with a single y axis.
library(data.table)
library(plotly)
st_data <- fread('Date , Close, Bollinger
1/30/2015 9:34, 65.55, NA
1/30/2015 9:34, 65.43, NA
1/30/2015 9:35, 65.52, NA
1/30/2015 9:35, 65.37, NA
1/30/2015 9:36, 65.68, 65.184
1/30/2015 9:36, 65.4 , 65.303
1/30/2015 9:36, 65.51, 65.4155
1/30/2015 9:36, 65.8 , 65.499
1/30/2015 9:36, 65.6 , 65.548 ')
p1 <- plot_ly(data = st_data, x = ~Date) %>% add_lines(y = ~Close,name = "Close") %>%
add_lines(y=~Bollinger,name="Bollinger")
p1
I like the following approach better.
p2 <- plot_ly()
p2 <- add_lines(p, data = st_data, x = ~Date, y = ~Close, name = "Close")
p2 <- add_lines(p, data = st_data, x = ~Date, y = ~Bollinger, name = "Bollinger")
p2
Your data is in "wide" format. You can use similar code to the R Plotly Book if you melt your data into "long" format:
st_data_long <- melt.data.table(st_data, id = "Date", measure.vars = c("Close", "Bollinger"),
value.factor = TRUE, variable.name = "PriceType", value.name = "Price")
p3 <- plot_ly(st_data_long, x = ~Date, y = ~Price) %>%
add_lines(color = ~PriceType)
p3
I also tried it with a sample dataset included in R:
# First make Date one column
airquality <- data.table(airquality)
airquality[, Date := do.call(paste, .SD), .SDcols = c("Month", "Day")]
p4 <- plot_ly()
p4 <- add_lines(p1, data = airquality, x = ~Date, y = ~Ozone, name = "Ozone")
p4 <- add_lines(p1, data = airquality, x = ~Date, y = ~Temp, name = "Temp")
p4

Faceting a Dataset

This is a beginner question. I have spent most of the day trying to work out how to facet my data, but all of the examples of faceting that I have come across seem unsuited to my dataset.
Here are the first five rows from my data:
Date Germany.Yield Italy.Yield Greece.Yield Italy_v_Germany.Spread Greece_v_Germany.Spread
2020-04-19 -0.472 1.820 2.287 2.292 2.759
2020-04-12 -0.472 1.790 2.112 2.262 2.584
2020-04-05 -0.345 1.599 1.829 1.944 2.174
2020-03-29 -0.441 1.542 1.972 1.983 2.413
2020-03-22 -0.475 1.334 1.585 1.809 2.060
I simply want to create two line charts. On both charts the x-axis will be the date. On the first chart, the y-axis should be Italy_v_Germany.Spread and on the second, the y-axis should be Greece_v_Germany.Spread.
The first chart looks like this:
So I want the two charts to appear alongside each other, like this:
The one on the left should be Italy_v_Germany.Spread, and the one on the right should be Greece_v_Germany.Spread.
I really have no idea where to start with this. Hoping that someone can point me in the right direction.
In the interest I making the example reproducible, I will share a link to the CSV files which I'm using: https://1drv.ms/u/s!AvGKDeEV3LOsmmlHkzO6YVQTRiOX?e=mukBVy. Unforunately these files convert into excel format when shared via this link, so you may have to export the files to CSVs so that the code works.
Here is the code that I have so far:
library(ggplot2)
library(scales)
library(extrafont)
library(dplyr)
library(tidyr)
work_dir <- "D:\\OneDrive\\Documents\\Economic Data\\Historical Yields\\Eurozone"
setwd(work_dir)
# Germany
#---------------------------------------
germany_yields <- read.csv(file = "Germany 10-Year Yield Weekly (2007-2020).csv", stringsAsFactors = F)
germany_yields <- germany_yields[, -(3:6)]
colnames(germany_yields)[1] <- "Date"
colnames(germany_yields)[2] <- "Germany.Yield"
#---------------------------------------
# Italy
#---------------------------------------
italy_yields <- read.csv(file = "Italy 10-Year Yield Weekly (2007-2020).csv", stringsAsFactors = F)
italy_yields <- italy_yields[, -(3:6)]
colnames(italy_yields)[1] <- "Date"
colnames(italy_yields)[2] <- "Italy.Yield"
#---------------------------------------
# Greece
#---------------------------------------
greece_yields <- read.csv(file = "Greece 10-Year Yield Weekly (2007-2020).csv", stringsAsFactors = F)
greece_yields <- greece_yields[, -(3:6)]
colnames(greece_yields)[1] <- "Date"
colnames(greece_yields)[2] <- "Greece.Yield"
#---------------------------------------
# Join data
#---------------------------------------
combined <- merge(merge(germany_yields, italy_yields, by = "Date", sort = F),
greece_yields, by = "Date", sort = F)
combined <- na.omit(combined)
combined$Date <- as.Date(combined$Date,format = "%B %d, %Y")
combined["Italy_v_Germany.Spread"] <- combined$Italy.Yield - combined$Germany.Yield
combined["Greece_v_Germany.Spread"] <- combined$Greece.Yield - combined$Germany.Yield
#--------------------------------------------------------------------
fl_dates <- c(tail(combined$Date, n=1), head(combined$Date, n=1))
ggplot(data=combined, aes(x = Date, y = Italy_v_Germany.Spread)) + geom_line() +
scale_x_date(limits = fl_dates,
breaks = seq(as.Date("2008-01-01"), as.Date("2020-01-01"), by="2 years"),
expand = c(0, 0),
date_labels = "%Y")
You need to get your data into a long format, for example, by using pivot_wider. Then it should work.
library(dplyr)
library(tidyr)
library(ggplot2)
data <- tribble(~Date, ~Germany.Yield, ~Italy.Yield, ~Greece.Yield, ~Italy_v_Germany.Spread, ~Greece_v_Germany.Spread,
"2020-04-19", -0.472, 1.820, 2.287, 2.292, 2.759,
"2020-04-19", -0.472, 1.820, 2.287, 2.292, 2.759,
"2020-04-12", -0.472, 1.790, 2.112, 2.262, 2.584,
"2020-04-05", -0.345, 1.599, 1.829, 1.944, 2.174,
"2020-03-29", -0.441, 1.542, 1.972, 1.983, 2.413,
"2020-03-22", -0.475, 1.334, 1.585, 1.809, 2.060
)
data %>%
mutate(Date = as.Date(Date)) %>%
pivot_longer(
cols = ends_with("Spread"),
names_to = "country",
values_to = "Spread_v_Germany",
values_drop_na = TRUE
) %>%
ggplot(., aes(x = Date, y = Spread_v_Germany, group = 1)) +
geom_line() +
facet_wrap(. ~ country)

Resources