Related
Wondering if there is a way to use yf_get() to grab a previousClose value from Yahoo Finance if there is no value for the date given. For example:
curr <- yf_get(tickers, first_date = Sys.Date() - 1, last_date = Sys.Date())
prev_q <- yf_get(tickers = tickers,
first_date = quarters[1]-.5,
last_date = quarters[1])
prev_q_closes <- round(prev_q$price_close,2)
prev_q2 <- yf_get(tickers = tickers,
first_date = quarters[2]-.5,
last_date = quarters[2], thresh_bad_data = 0.45)
prev_q2_closes <- round(prev_q2$price_close,2)
prev_q3 <- yf_get(tickers = tickers,
first_date = quarters[3]-.5,
last_date = quarters[3])
prev_q3_closes <- round(prev_q3$price_close,2)
close_prices <- cbind(prev_q3_closes, prev_q2_closes, prev_q_closes, current_close)
tick_close <- data.frame(Tickers = tickers,
ClosingPrices = close_prices,
PercentChanges = percent_changes)
dates <- rev(quarters)
dates_change <- as.character(format(dates, "%m-%d"))
#colnames(tick_close) <- c("Tickers", "Prev Q3 Closing Prices", "Prev Q2 Closing Prices", "Prev Q1 Closing Prices", "Current Closing Prices")
colnames(tick_close) <- c("Tickers", as.character(dates[1]), as.character(dates[2]), as.character(dates[3]), as.character(CurrentDate),
paste(dates_change[1],dates_change[2], sep=" to "), paste(dates_change[1], dates_change[3], sep=" to "),
paste(dates_change[1],as.character(format(CurrentDate, "%m-%d")), sep=" to "),
paste(dates_change[3],as.character(format(CurrentDate, "%m-%d")), sep=" to "))
etc and I then grab the previous quarterly date values, for some Chinese companies on Yahoo Finance they do not have a value for December 31st, and my algorithm falls apart because it cannot grab a different value. I want it to grab the December 30th value IF there is no December 31st value on Yahoo Finance!
I am trying to generate a series of plots that show the same patient taking drinks and urinating at different times. Each plot represents a single day. I want to compare the days and hence I need to ensure that all graphs plotted have the same x-axis. My code is below which I cribbed from How to specify the actual x axis values to plot as x axis ticks in R
### Data Input
time_Thurs <- c("01:10", "05:50", "06:00","06:15", "06:25", "09:35", "10:00", "12:40",
"14:00", "17:20", "18:50", "19:10", "20:10", "21:00", "22:05", "22:35")
event_Thurs <- c("u", "u", "T", "T", "u", "u", "T","T","u", "u", "T", "T", "T", "T", "u", "W")
volume_Thurs <- c(NA, NA, 0.25, 0.25, NA, NA, 0.125, 0.625, NA, NA, 0.25, 0.25, 0.25, 0.25,
NA, 0.25)
total_liquids_Thurs <- sum(volume_Thurs, na.rm=TRUE)
time_Thurs <- paste("04/04/2019", time_Thurs, sep=" ")
time_Fri <- c("01:15", "06:00", "06:10", "06:25", "06:30", "07:10", "08:40", "09:20",
"12:45", "13:45")
event_Fri <- c("u","u", "T","T","u","uu","T", "u", "T", "u")
volume_Fri <- c(NA, NA, 0.25, 0.25, NA, NA, 0.125, NA, 0.625, NA)
total_liquids_Fri <- sum(volume_Fri, na.rm=TRUE)
time_Fri <- paste("05/04/2019", time_Fri, sep=" ")
### Collect all data together
event <- c(event_Thurs, event_Fri)
Volume <- c(volume_Thurs, volume_Fri)
time_log <- c(time_Thurs, time_Fri)
time_log <- strptime(time_log, format = "%d/%m/%Y %H:%M")
time_view <- format(time_log, "%H:%M")
### Put into Dataframe
patient_data <- data.frame(time_log, time_view, event, Volume)
# write.csv(patient_data, file="patient_data.csv", row.names = FALSE)
daily_plot <- function(x, day) {
# x patient data - a data.frame with four columns:
# POSIXct time, time, event and Volume
# date number of day of month
# y volume of liquid
# TotVol total volume of intake over week
# Event - drink or otherwise
x <- x[as.numeric(format(x[,1], "%d")) == day, ]
TotVol <- sum(x[,4], na.rm = TRUE)
DayOfWeek <- weekdays(x[1,1], abbreviate = FALSE)
plot(x[,1],x[,4],
xlim = c(x[1,1],x[length(x[,1]),1]),
xlab="Hours of Study", ylab = "Volume of Liquid Drank /L",
main = paste("Total Liquids Drank = ", TotVol, " L on ", DayOfWeek, "Week 1, Apr 2019"),
sub = "dashed red line = urination", pch=16,
col = c("black", "yellow", "green", "blue")[as.numeric(x[,3])],
xaxt = 'n'
)
xAxis_hrs <- seq(as.POSIXct(x[1,1]), as.POSIXct(x[length(x[,1]),1]), by="hour")
axis(1, at = xAxis_hrs, las = 2)
abline( v = c(x[x[,3] == "u",1]), lty=3, col="red")
}
When I run the function,
daily_plot(patient_data, 4)
I want to print out my x-axis, as amended in the form of hours representing the events over the 24 hour period.
When I wrap my xAxis_hrs vector in strptime(xAxis_hrs, format = "%H") the code crashes - that is the x-axis doesn't print out and I see, Error in axis(1, at = xAxis_hrs, las = 2) : (list) object cannot be coerced to type 'double' . Any help?
The issue is that you pass the labels to the wrong named argument, namely at (which should be the numeric positions of the labels). Use the following instead:
axis(1, at = xAxis_hrs, labels = strptime(xAxis_hrs, format = "%H"), las = 2)
Unfortunately this doesn’t change the fact that the axis labels don’t fit into the plot, and collide with the axis title. The former can be fixed by adjusting the plot margins. I’m not aware of a good solution for the latter, although changing the time format might help: it’s probably not necessary/helpful to print the full minutes and seconds (which are always 0). In fact, did you mean to use format instead of strptime?
Apart from that I fundamentally agree with the other answer recommending ggplot2 in the long run. It makes this kind of stuff a lot less painful.
If you're open to a ggplot solution:
library(tidyverse)
library(lubridate)
daily_ggplot <- function(df, selected_day) {
df_day <- filter(df, day(time_log) == selected_day)
df_urine <- filter(df_day, event == "u")
df_drink <- filter(df_day, event != "u")
TotVol <- sum(df_day$Volume, na.rm = TRUE)
Date <- floor_date(df_day$time_log[1], 'days')
DayOfWeek <- weekdays(Date, abbreviate = F)
plot_title <- paste0("Total drank = ", TotVol, "L on ", DayOfWeek, " Week 1, Apr 2018")
ggplot(df_drink) +
aes(time_log, Volume, color = event) +
geom_point(size = 2) +
geom_vline(data = df_urine, aes(xintercept = time_log), color = "red", linetype = 3) +
labs(x = "Hours of Study", ylab = "Volume of Liquid Drank (L)",
title = plot_title, subtitle = "lines = urination") +
theme_bw() +
scale_x_datetime(date_labels = "%H:%M", limits = c(Date, Date + days(1)))
}
daily_ggplot(patient_data, 4)
I am new to this kind of plotting and therefore please forgive my inexperience.
I would like to plot the max temperatures over Europe in a given n day.
Data can be accessed here http://www.ecad.eu/download/ensembles/data/Grid_0.44deg_rot/tx_0.44deg_rot_v16.0.nc.gz (258MB..sorry).
This is a netcdf file with 3 dimensions and 4 variables.
Here what I did:
library(ncdf4)
max_tmp_0_44_deg = "tx_0.44deg_rot_v16.0.nc"
max_tmp_0_44_deg = nc_open(max_tmp_0_44_deg)
# create variables
temp = ncvar_get(max_tmp_0_44_deg, 'tx')
lon = ncvar_get(max_tmp_0_44_deg, 'Actual_longitude')
lat = ncvar_get(max_tmp_0_44_deg, 'Actual_latitude')
time = ncvar_get(max_tmp_0_44_deg, 'time')
How can I plot a grid (lat and lon) of max temperatures in a given day?
max_day = temp[,,30] #subset max temp on the 30th day
Then how can I plot max_day?
It should be quite straightforward but I couldn't find a solution yet.
thanks
You can use the image function:
temp_use <- temp[,,30]
temp_use <- round(temp_use)
n_colors <- length(table(temp_use))
image(temp_use,
col = heat.colors(n_colors),
xaxt = "n",
yaxt = "n")
temp_max <- temp_use == max(temp_use, na.rm = T) & !is.na(temp_use)
temp_max[temp_max == F] <- NA
image(temp_max,
add = T,
col = "blue",
xaxt = "n",
yaxt = "n")
Hi everybody I am trying to solve a little problem with a lattice graphic in R. I build a double y axis plot with lattice. It works awesome. I add the code and dput version of my data (xx list of data frames in the final part):
library(lattice)
library(latticeExtra)
#First graph
#Format
comma_fomatter <- function (lim, logsc = FALSE, at = NULL, ...)
{
ans <- yscale.components.default(lim = lim, logsc = logsc,
at = at, ...)
xx = as.numeric(ans$left$labels$labels)
ans$left$labels$labels <- formatC(xx, format="fg",big.mark = ",")
ans
}
#Plot
DD=barchart(a1 ~ a5,xx, yscale.components =comma_fomatter)
#Second graph
#Format
percent1 <- function(x, digits = 2, format = "f", ...)
{
paste(formatC(100 * x, format = format, digits = digits, ...), "%", sep = "")
}
percent <- function (lim, logsc = FALSE, at = NULL, ...)
{
ans <- yscale.components.default(lim = lim, logsc = logsc,
at = at, ...)
xx = as.numeric(ans$left$labels$labels)
ans$left$labels$labels <- percent1(xx)
ans
}
#Second plot
D3=xyplot(a3+a4 ~ a5, xx, type = "b",yscale.components=percent)
#Final graph
DF=doubleYScale(DD, D3,style1 = 3, style2 = 0, add.ylab2 = FALSE,text = c("a3", "a4","a1"),main="Nuevo Gráfico")
All works perfect but when I plot DF I got this:
How you can see the left side y axis doesn't show its values and I think this fact is due to the size of square that has all plots. My question is if it is any way to reduce the size of that square and showing the complete values inside of y axis scale. The dput() version of my list of data frames is the next:
xx=structure(list(a1 = c(560492.29, 1433973.37, 3016748.66, 4241217.73,
6251742.27, 6757161.24, 7408081.05, 7899980.33), a2 = 1:8, a3 = c(0,
0.00793734405263048, 0.0129172080248807, 0.0324335034787285,
0.0397094648625047, 0.0555107413716237, 0.0521541081141384, 0.0515512600016815
), a4 = c(0.0142731668976214, 0.010460445301017, 0.0928151568317925,
0.0707344020275045, 0.0303915279604129, 0.0517968992552855, 0.0202481585970229,
0.0253165187311296), a5 = structure(1:8, .Label = c("abr 2013",
"may 2013", "jun 2013", "jul 2013", "ago 2013", "sep 2013", "oct 2013",
"nov 2013"), class = "factor")), .Names = c("a1", "a2", "a3",
"a4", "a5"))
I have looked for any advice at lattice graphics book but I can't solve this element. Many thanks for your help.
Not sure why it didn't work for you. I've taken the liberty to reformat your code, other than that nothing important has changed. Anyway, here's the plot:
EDIT: The problem seems to be related to the settings of lattice (see ?trellis.par.get). I've updated the source accordingly, that should solve the problem.
And here's the source:
library(lattice)
library(latticeExtra)
# xx <- ... paste your dataset here
# Adapt these to your needs:
parSettings <- list(layout.widths=list(left.padding=5))
#First graph
comma_formatter <- function (lim, logsc = FALSE, at = NULL, ...) {
ans <- yscale.components.default(lim = lim, logsc = logsc, at = at, ...)
xxPrime <- as.numeric(ans$left$labels$labels)
ans$left$labels$labels <- formatC(xxPrime, format = "fg", big.mark = ",")
ans
}
#Plot
DD <- barchart(a1 ~ a5, xx, yscale.components = comma_formatter, par.settings = parSettings)
#Second graph
percent <- function (lim, logsc = FALSE, at = NULL, ...) {
# Helper function (never needed elsewhere, so we can declare it here)
percent1 <- function(x, digits = 2, format = "f", ...)
paste(formatC(100 * x, format = format, digits = digits, ...), "%", sep = "")
ans <- yscale.components.default(lim = lim, logsc = logsc, at = at, ...)
xxPrime <- as.numeric(ans$left$labels$labels)
ans$left$labels$labels <- percent1(xxPrime)
ans
}
#Plot
D3 <- xyplot(a3+a4 ~ a5, xx, type = "b", yscale.components = percent, par.settings = parSettings)
#Final graph
DF <- doubleYScale(DD, D3, style1 = 3, style2 = 0, add.ylab2 = FALSE,
text = c("a3", "a4", "a1"), main = "Nuevo Gráfico")
plot(DF)
I'm using Paul Bleicher's Calendar Heatmap to visualize some events over time and I'm interested to add black-and-white fill patterns instead of (or on top of) the color coding to increase the readability of the Calendar Heatmap when printed in black and white.
Here is an example of the Calendar Heatmap look in color,
and here is how it look in black and white,
it gets very difficult to distinguish between the individual levels in black and white.
Is there an easy way to get R to add some kind of patten to the 6 levels instead of color?
Code to reproduce the Calendar Heatmap in color.
source("http://blog.revolution-computing.com/downloads/calendarHeat.R")
stock <- "MSFT"
start.date <- "2012-01-12"
end.date <- Sys.Date()
quote <- paste("http://ichart.finance.yahoo.com/table.csv?s=", stock, "&a=", substr(start.date,6,7), "&b=", substr(start.date, 9, 10), "&c=", substr(start.date, 1,4), "&d=", substr(end.date,6,7), "&e=", substr(end.date, 9, 10), "&f=", substr(end.date, 1,4), "&g=d&ignore=.csv", sep="")
stock.data <- read.csv(quote, as.is=TRUE)
# convert the continuous var to a categorical var
stock.data$by <- cut(stock.data$Adj.Close, b = 6, labels = F)
calendarHeat(stock.data$Date, stock.data$by, varname="MSFT Adjusted Close")
update 02-13-2013 03:52:11Z, what do I mean by adding a pattern,
I envision adding a pattern to the individual day-boxes in the Calendar Heatmap as pattern is added to the individual slices in the pie chart to the right (B) in this plot,
found here something like the states in this plot.
I answered this question before he becomes a bounty. It looks like the OP find my previous answer a little bit complicated. I organized the code in a single gist here. you need just to download the file and source it.
I create new function extra.calendarHeat which is an extension of the first one to draw hetmap of double time series.(dat,value1,value2). I addedthis new parameters:
pch.symbol : vector of symbols , defualt 15:20
cex.symbol : cex of the symbols , default = 2
col.symbol : color of symbols , default #00000044
pvalues : value of symbols
Here some examples:
## I am using same data
stock <- "MSFT"
start.date <- "2012-01-12"
end.date <- Sys.Date()
quote <- paste("http://ichart.finance.yahoo.com/table.csv?s=",
stock,
"&a=", substr(start.date,6,7),
"&b=", substr(start.date, 9, 10),
"&c=", substr(start.date, 1,4),
"&d=", substr(end.date,6,7),
"&e=", substr(end.date, 9, 10),
"&f=", substr(end.date, 1,4),
"&g=d&ignore=.csv", sep="")
stock.data <- read.csv(quote, as.is=TRUE)
p1 <- extra.calendarHeat(dates= stock.data$Date, values = stock.data$Adj.Close,
pvalues = stock.data$Volume,
varname="W&B MSFT Adjusted Close
\n Volume as no border symbol ")
## multiply symbols
p2 <- extra.calendarHeat(dates= stock.data$Date, values = stock.data$Adj.Close,
pvalues = stock.data$Volume,
varname="W&B MSFT Adjusted Close \n
black Volume as multiply symbol ",
pch.symbol = c(3,4,8,9),
col.symbol='black')
## circles symbols
p3 <- extra.calendarHeat(dates= stock.data$Date, values = stock.data$Adj.Close,
pvalues = stock.data$Volume,
varname="W&B MSFT Adjusted Close \n blue Volume as circles",
pch.symbol = c(1,10,13,16,18),
col.symbol='blue')
## triangles symbols
p4 <- extra.calendarHeat(dates= stock.data$Date, values = stock.data$Adj.Close,
pvalues = stock.data$Volume,
varname="W&B MSFT Adjusted Close \n red Volume as triangles",
pch.symbol = c(2,6,17,24,25),
col.symbol='red')
p5 <- extra.calendarHeat(dates= stock.data$Date, values = stock.data$Adj.Close,
varname="MSFT Adjusted Close",
pch.symbol = LETTERS,
col.symbol='black')
# symbols are LETTERS
p6 <- extra.calendarHeat(dates= stock.data$Date, values = stock.data$Adj.Close,
pvalues = stock.data$Volume,
varname="MSFT Adjusted Close \n Volume as LETTERS symbols",
pch.symbol = letters,
color='r2b')
You can panel.level.plot from latticeExtra to add pattern. I think the question as it is asked is a little bit specific. So I try to generalize it. The idea is to give the steps to transform a time series to a calendar heatmap: with 2 patterns (fill color and a shape). We can imagine multiple time series (Close/Open). For example, you can get something like this
or like this, using a ggplot2 theme:
The function calendarHeat , giving a single time series (dat,value) , transforms data like this :
date.seq value dotw woty yr month seq
1 2012-01-01 NA 0 2 2012 1 1
2 2012-01-02 NA 1 2 2012 1 2
3 2012-01-03 NA 2 2 2012 1 3
4 2012-01-04 NA 3 2 2012 1 4
5 2012-01-05 NA 4 2 2012 1 5
6 2012-01-06 NA 5 2 2012 1 6
So I assume that I have data formated like this, otherwise, I extracted from calendarHeat the part of data transformation in a function(see this gist)
dat <- transformdata(stock.data$Date, stock.data$by)
Then the calendar is essentially a levelplot with custom sacles , custom theme and custom panel' function.
library(latticeExtra)
levelplot(value~woty*dotw | yr, data=dat, border = "black",
layout = c(1, nyr%%7),
col.regions = (calendar.pal(ncolors)),
aspect='iso',
between = list(x=0, y=c(1,1)),
strip=TRUE,
panel = function(...) {
panel.levelplot(...)
calendar.division(...)
panel.levelplot.points(...,na.rm=T,
col='blue',alpha=0.5,
## you can play with cex and pch here to get the pattern you
## like
cex =dat$value/max(dat$value,na.rm=T)*3
pch=ifelse(is.na(dat$value),NA,20),
type = c("p"))
},
scales= scales,
xlim =extendrange(dat$woty,f=0.01),
ylim=extendrange(dat$dotw,f=0.1),
cuts= ncolors - 1,
colorkey= list(col = calendar.pal(ncolors), width = 0.6, height = 0.5),
subscripts=TRUE,
par.settings = calendar.theme)
Where the scales are:
scales = list(
x = list( at= c(seq(2.9, 52, by=4.42)),
labels = month.abb,
alternating = c(1, rep(0, (nyr-1))),
tck=0,
cex =1),
y=list(
at = c(0, 1, 2, 3, 4, 5, 6),
labels = c("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"),
alternating = 1,
cex =1,
tck=0))
And the theme is setting as :
calendar.theme <- list(
xlab=NULL,ylab=NULL,
strip.background = list(col = "transparent"),
strip.border = list(col = "transparent"),
axis.line = list(col="transparent"),
par.strip.text=list(cex=2))
The panel function uses a function caelendar.division. In fact, the division of the grid(month black countour) is very long and is done using grid package in the hard way (panel focus...). I change it a little bit, and now I call it in the lattice panel function: caelendar.division.
We can use ggplot2's scale_shape_manual to get us shapes that appear close to shading, and we can plot these over the grey heatmap.
Note: This was adapted from #Jay's comments in the original blog posting for the calendar heatmap
# PACKAGES
library(ggplot2)
library(data.table)
# Transofrm data
stock.data <- transform(stock.data,
week = as.POSIXlt(Date)$yday %/% 7 + 1,
month = as.POSIXlt(Date)$mon + 1,
wday = factor(as.POSIXlt(Date)$wday, levels=0:6, labels=levels(weekdays(1, abb=FALSE)), ordered=TRUE),
year = as.POSIXlt(Date)$year + 1900)
# find when the months change
# Not used, but could be
stock.data$mchng <- as.logical(c(0, diff(stock.data$month)))
# we need dummy data for Sunday / Saturday to be included.
# These added rows will not be plotted due to their NA values
dummy <- as.data.frame(stock.data[1:2, ])
dummy[, -which(names(dummy) %in% c("wday", "year"))] <- NA
dummy[, "wday"] <- weekdays(2:3, FALSE)
dummy[, "mchng"] <- TRUE
rbind(dummy, stock.data) -> stock.data
# convert the continuous var to a categorical var
stock.data$Adj.Disc <- cut(stock.data$Adj.Close, b = 6, labels = F)
# vals is the greyscale tones used for the outer monthly borders
vals <- gray(c(.2, .5))
# PLOT
# Expected warning due to dummy variable with NA's:
# Warning message:
# Removed 2 rows containing missing values (geom_point).
ggplot(stock.data) +
aes(week, wday, fill=as.factor(Adj.Disc),
shape=as.factor(Adj.Disc), color=as.factor(month %% 2)) +
geom_tile(linetype=1, size=1.8) +
geom_tile(linetype=6, size=0.4, color="white") +
scale_color_manual(values=vals) +
geom_point(aes(alpha=0.2), color="black") +
scale_fill_grey(start=0, end=0.9) + scale_shape_manual(values=c(2, 3, 4, 12, 14, 8)) +
theme(legend.position="none") + labs(y="Day of the Week") + facet_wrap(~ year, ncol = 1)