I'm trying to format a chart using GGPLOT2. What I'm trying to accomplish feels like it should be fairly straightforward, but try as I might, no dice. I have the following chart.
#packages
library(ggplot2)
library(plyr)
library(reshape2)
library(PerformanceAnalytics)
library(timeSeries)
library(quantmod)
library(ggthemes)
#stock data
getSymbols(c("^FCHI","^GSPC"), from = "2008-12-31")
stockmarketdata <- cbind(GSPC$GSPC.Close, FCHI$FCHI.Close)
#normalize data
stockmarketdata$CAC40 <- stockmarketdata[,2] / 3217.97
stockmarketdata$SNP <- stockmarketdata[ ,1] / 903.25
#Isolate normalized data
marketdata <- stockmarketdata[,3:4]
GSPC.DF<-data.frame(Date=index(GSPC),coredata(GSPC))
FCHI.DF<-data.frame(Date=index(FCHI),coredata(FCHI))
#format before making ggplot chart
market.df <- data.frame(Date=index(marketdata), marketdata)
market.df.eco <- market.df
colnames(market.df.eco) <- c("Date", "CAC40", "S&P500")
market.df.eco.mlt <- melt(market.df.eco, id = "Date")
ggplot chart
chart.EQ <-
ggplot(market.df.eco.mlt, aes(x=Date, y=value, colour = variable, group = variable)) +
geom_line() +
labs(title="Equity Market", x= "", y = "", color="December 31st 2008=1", title.vjust=1) +
theme_economist() +
scale_color_economist() +
theme(legend.position = c(0,1),
legend.justification=c(0,1),
legend.direction="horizontal",
plot.title = element_text(vjust=1),
legend.title=element_text(vjust=1),
legend.title.align=0)
which looks like this
Ideally, I would like the title and legend to be flush with the left side. I would like both the legend and the title to be above the chart itself with the legend title directly below the chart title and the labels in the legend below the legend title. More like this.
If someone could help me with this formatting that would be excellent. Whenever I remove the justification argument from the theme(), the legend flies half way off the image. Thanks for any help you can offer!
If you don't have the finance packages here is a small sample of the data frame 'marketdata' if you apply the transformations from the code above you should be able to get a similar chart
marketdata<-
structure(c(0.999999990988107, 1.04093261932212, 1.04411163621786,
1.05539205492904, 1.03981394730218, 1.03305191720246, 1.02533584837646,
1.00874778726961, 0.993760008017477, 0.948424006438842, 0.930984404142985,
0.937469895617423, 0.929060849231037, 0.909045152378674, 0.902920185085629,
0.891748561049357, 0.885384230741741, 0.918395795175219, 0.918134733698574,
0.955885235101632, 0.935294611198986, 0.92416023828687, 0.910527459547479,
0.926792323421287, 0.953703729369758, 0.952864706321066, 0.970422359127027,
0.9741763027623, 0.938712915285102, 0.94087886804414, 0.921183257768096,
0.931599768487587, 0.920524420985901, 0.893491853559853, 0.893131405202659,
0.892674604797434, 0.854746951960397, 0.847699051575994, 0.841539867991311,
0.838081126300121, 1, 1.03160806864102, 1.02679215278162, 1.03481872349848,
1.00376421145862, 1.0071740714088, 0.985718213119291, 0.963476346526432,
0.965170194298367, 0.932875721007473, 0.934115682258511, 0.94117907002491,
NA, 0.891469660669803, 0.930240786050374, 0.916136174923886,
0.92106284195959, 0.926177699418766, 0.936296730694714, 0.967716608912261,
0.935665668419596, 0.914342657071686, 0.913855523941323, 0.928325502352615,
0.921372798228619, 0.936451675615832, 0.961638500968724, 0.963066720177138,
0.915759726543039, 0.923044550235262, 0.924649877663991, 0.915405510102408,
NA, 0.873700507057847, 0.872870172156103, 0.862374760033213,
0.85253250816496, 0.82295047550512, 0.8559535178522, 0.846830915029062
), .indexCLASS = "Date", .indexTZ = "UTC", tclass = "Date", tzone = "UTC", src = "yahoo", updated = structure(1440080950.2661, class = c("POSIXct",
"POSIXt")), class = c("xts", "zoo"), index = structure(c(1230681600,
1230854400, 1231113600, 1231200000, 1231286400, 1231372800, 1231459200,
1231718400, 1231804800, 1231891200, 1231977600, 1232064000, 1232323200,
1232409600, 1232496000, 1232582400, 1232668800, 1232928000, 1233014400,
1233100800, 1233187200, 1233273600, 1233532800, 1233619200, 1233705600,
1233792000, 1233878400, 1234137600, 1234224000, 1234310400, 1234396800,
1234483200, 1234742400, 1234828800, 1234915200, 1235001600, 1235088000,
1235347200, 1235433600, 1235520000), tzone = "UTC", tclass = "Date"), .Dim = c(40L,
2L), .Dimnames = list(NULL, c("CAC40", "SNP")))
Related
Hi I have a dataset here,
> dput(data2)
structure(list(Date = structure(c(1651795200, 1651795200, 1652400000,
1652400000, 1653004800, 1653004800, 1653609600, 1653609600, 1654214400,
1654214400), tzone = "UTC", class = c("POSIXct", "POSIXt")),
Country = c("MYR", "JPY", "MYR", "JPY", "MYR", "JPY", "MYR",
"JPY", "MYR", "JPY"), Value = c(-4.58032749341578, -11.8566176470588,
-5.27883238229476, -10.9425785482124, -5.06949191159718,
-10.00938379731, -4.84618722451869, -9.46424356856266, -5.06949191159718,
-12.0721271393643)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -10L))
I have some code to run an animation bar chart
plot1 <- ggplot(data2, aes(x=reorder(Country, -Value), y=Value, fill=Country)) + geom_bar(stat='identity')
plot1 + coord_flip() + transition_states(Date, transition_length = 2,state_length = 1, wrap =
FALSE) + geom_text(x=1 ,y=-10, family="Times",aes(label=as.character(Date)),size=6, color
="blue") + xlab("Country")
The rendered plot looks great except I have a random character appearing after the date is shown.
I have an xts object, a snapshot of the data is as follow:
ts <- structure(c(620519.432512971, 619086.596917204, 620478.784694651,
620997.044378227, 620885.262877848, 620275.545603053), index = structure(c(1519954199.9845,
1519955999.7115, 1519957799.9675, 1519959599.9935, 1519961399.9365,
1519963199.2225), tzone = "", tclass = c("POSIXct", "POSIXt")), .indexCLASS = c("POSIXct",
"POSIXt"), .indexTZ = "", tclass = c("POSIXct", "POSIXt"), tzone = "", class = c("xts",
"zoo"), .Dim = c(6L, 1L), .Dimnames = list(NULL, "yy"))
All the timestamps are within the same date, and I am trying to add more tick marks on the x axis (time), which I managed to achieve. It looks as follow:
ggplot(data=ts) +
geom_line(aes(x=Index,y=yy,colour = "yy"),na.rm=T) +
scale_x_datetime(date_breaks ="20 min")
As you can see the timestamps above are correct, but i want to remove the date part and just have the time on the x-axis. So I tried the following code:
ggplot(data=ts) +
geom_line(aes(x=Index,y=yy,colour = "yy"),na.rm=T) +
scale_x_datetime(date_breaks ="20 min",labels = date_format("%H:%M:%S"))
But the times are all incorrect. What should I do to fix this to make it print only the time, leaving out the date, since the xts data are all within the same date ?
I believe your times are being converted to UTC times when you plot them. You can convert to your timezone. Here is how I convert to using the "US/Pacific" time zone. I added the tz argument to date_format
ggplot(data=ts) +
geom_line(aes(x=Index,y=yy,colour = "yy"),na.rm=T) +
scale_x_datetime(date_breaks ="20 min",
labels = date_format("%H:%M:%S", tz = "US/Pacific"))
You may have to change the timezone (see OlsonNames()
It is very simple,
ggplot(data=ts) +
geom_line(aes(x = Index,y = yy,colour = "yy"), na.rm=T) +
scale_x_datetime(date_breaks = "20 min", date_labels = "%H:%M:%S")
You just have to use parameter date_labels to set the formatting option of your datetime object.
Sources:
- http://ggplot2.tidyverse.org/reference/scale_date.html
- https://www.stat.berkeley.edu/~s133/dates.html
I have a dataframe with dates. Here are the first 3 rows with dput:
df.cv <- structure(list(ds = structure(c(1448064000, 1448150400, 1448236800
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), y = c(10.4885204292416,
10.456538985014, 10.4264986311659), yhat = c(10.4851491194439,
10.282089547027, 10.4354960430083), yhat_lower = c(10.4169914076864,
10.2162549984153, 10.368531352493), yhat_upper = c(10.5506038959764,
10.3556867861042, 10.5093092789713), cutoff = structure(c(1447977600,
1447977600, 1447977600), class = c("POSIXct", "POSIXt"), tzone = "UTC")),.Names = c("ds",
"y", "yhat", "yhat_lower", "yhat_upper", "cutoff"), row.names = c(NA,
-3L), class = c("`enter code here`tbl_df", "tbl", "data.frame"))
I'm trying to plot the data with ggplot + geom_line from similar day/month combinations in one plot. So, for example, I want the y-value of 2016-01-01 to appear on the same x-value as 2017-01-01. If found a way to do this, but it seems to be a very complex workaround:
library(tidyverse)
library(lubridate)
p <- df.cv %>%
mutate(jaar = as.factor(year(ds))) %>%
mutate(x = as_date(as.POSIXct(
ifelse(jaar==2016, ds + years(1), ds),
origin = "1970-01-01")))
ggplot(p %>% filter(jaar!=2015), aes(x=x, group=jaar, color=jaar)) +
geom_line(aes(y=y))
It works, but as you can see I first have to extract the year, then use an ifelse to add one year to only the 2016 dates, convert with POSIXct because ifelse strips the class, convert back into POSIXct while supplying an origin, and finally remove the timestamp with as_date.
Isn't there a simpler, more elegant way to do this?
Use year<- to replace the year with any fixed leap year:
p <- df.cv %>%
mutate(jaar = as.factor(year(ds)),
x = `year<-`(as_date(ds), 2000))
ggplot(p, aes(x = x, y = y, color = jaar)) +
geom_line()
What I am basically trying to do is to put s$cluster numbers on top of each bar
library("quantmod")
# xts object
s <-
structure(c(1300, 1301.349976, 1281.199951, 1316.900024, 1312.310059,
1278, 1304.439941, 1304.709961, 1313.900024, 1323.089966, 1314.98999,
1301.719971, 1291.630005, 1271.01001, 1281.199951, 1311.040039,
1288.329956, 1273, 1301.189941, 1287.030029, 1307.890015, 1317.030029,
1288.959961, 1299.699951, 372300, 453800, 347600, 376400, 488200,
567300, 1301.189941, 1287.030029, 1307.890015, 1317.030029, 1288.959961,
1299.699951, 0.0034153392307692, 0.00258192266643587, 0.0255230051909361,
0.00470038870619693, 0.00204214772387123, 0.0185602276995305,
-0.00643845769230766, -0.0233142248891853, 0, -0.0044498328599013,
-0.0182731991083518, -0.00391236306729259, 0.000915339230769252,
-0.0110039169048249, 0.02083208321946, 9.87204781157658e-05,
-0.0177931258240853, 0.016979617370892, 4, 3, 1, 4, 3, 1), .indexCLASS = "Date", .indexTZ = "UTC", tclass = "Date", tzone = "UTC", src = "yahoo", updated = structure(1459599733.74441, class = c("POSIXct",
"POSIXt")), class = c("xts", "zoo"), index = structure(c(1458777600,
1459123200, 1459209600, 1459296000, 1459382400, 1459468800), tzone = "UTC", tclass = "Date"), .Dim = c(6L,
10L), .Dimnames = list(NULL, c("PCLN.Open", "PCLN.High", "PCLN.Low",
"PCLN.Close", "PCLN.Volume", "PCLN.Adjusted", "h", "l", "c",
"cluster")))
I have tried the following:
# plot
chart_Series(s)
# add text on top of each bar:
text(x = s, y = s$cluster, label = as.character(s$cluster))
I have tried searching online but cannot seem to find the answer for chartSeries() plots. thanks in advance
In the text call, x is supposed to be a numeric vector of the x-coordinates of the location of the text you want to plot, but you provide a xts/matrix. I'd guess that the text call uses the first 6 observations of the first column, since that's how many observations are in your drawn chart. The first 6 values are between 1278 and 1317, which are >> 6, so they don't appear on your drawn plot.
Similarly, y is supposed to be the y-coordinates of the location of the text you want to plot. You provide a vector with a range between 1 and 4, while the y values on the data you plot are in the 1250-1350 range, so your text coordinates are off the drawn plot.
The x-coordinates should just be 1:nrow(s) and the y-coordinates should be something close to Lo(s) and Hi(s) for each observation. For example:
text(x = seq(nrow(s)), y = Hi(s)+1, label = as.character(s$cluster))
So I am using the PerformanceAnalytics package to plot performance summary of a simple PnL series so
library(xts)
library(PerformanceAnalytics)
dates <- structure(c(14008, 14011, 14012, 14013, 14014, 14015, 14018, 14019, 14020, 14021),
class = "Date")
PnL.xts = structure(c(0, -0.00510803851321091, -0.0102109843849305, -0.00138369232677364,
-0.00255257489213331, -0.00200279255353461, 0.0104232666033935,
0.00181846800788812, 4.72633257030091e-05, 0.0138334493571853),
.Dim = c(10L, 1L),
index = structure(c(1210291200, 1210550400, 1210636800, 1210723200,
1210809600, 1210896000, 1211155200, 1211241600,
1211328000, 1211414400),
tzone = "UTC", tclass = "Date"),
.indexCLASS = "Date", tclass = "Date",
.indexTZ = "UTC", tzone = "UTC", .Dimnames = list(NULL, "PnL"),
class = c("xts", "zoo"))
PnL.cum = cumsum(PnL.xts)
ret.ann = Return.annualized(PnL.xts, geometric = FALSE)
ret.cum = Return.cumulative(PnL.xts, geometric = FALSE)
ret.min = min(PnL.cum)
stdev = StdDev.annualized(PnL.xts)
sharpe = SharpeRatio.annualized(PnL.xts, geometric = FALSE)
stats = paste(paste("Annualized Return:", percent(round(ret.ann, 5))),
paste("Cumulative Return:", percent(round(ret.cum, 5))),
paste("Standard Deviation:", round(stdev, 5)),
paste("Sharpe Ratio:", round(sharpe, 5)), sep = '\n' )
lag = 1
descr = paste("Following fitted Granger model - ", lag, " day lag", sep = "")
charts.PerformanceSummary(R = PnL.xts, geometric = FALSE)
text(midrange(dates),ret.min, labels = stats, cex = 1)
mtext(descr, side = 3, line = 31)
However, I want to add some descriptive text into the cumulative PnL chart such as annualized return, cumulative return, standard deviation, and sharpe. How can I paste this into the whitespace in the first graph?
If I plotted the graph by itself, I could just do it with the above code. However, since the charts.PerformanceSummary function automatically plots 3 graphs, I can only access the 3rd graph it seems. Is there any way to access the first of 3 graphs printed by a function, so that I can write text on it relative to its own coordinates?
Here is an example of what I want: http://i.imgur.com/QXUb2Aq.png. But in this case, I had to manually, test values of the y coordinate until I found somthing that worked. Thanks!