d1 |>
filter(tic == "META") |>
group_by(fyearq) |>
summarize(oiadpq = sum(oiadpq, na.rm = TRUE), .groups = "drop") |>
hchart(type = "column", hcaes(x = as.factor(fyearq), y = oiadpq)) |>
hc_add_theme(hc_theme_economist())Highcharter Examples
Bar chart
Create a bar chart of Meta (Facebook) profits by fiscal year
Play around with a few themes and then finalize one theme that you like: https://jkunst.com/highcharter/articles/themes.html#themes-1 https://jkunst.com/highcharter/reference/index.html#section-themes
When you hover mouse over the bars, you will notice the tooltip shows “Series 1” rather than the variable name oibdp. Admittedly, both “Series 1” and oibdp are equally obtuse but we can do better. Let’s label the series “Operating Profits”
plot1 = d1 |>
filter(tic == "META") |>
group_by(fyearq) |>
summarize(oiadpq = sum(oiadpq, na.rm = TRUE), .groups = "drop") |>
hchart(type = "column", hcaes(x = as.factor(fyearq), y = oiadpq)) |>
hc_add_theme(hc_theme_monokai())
plot1When you hover mouse over the bars, you will notice the tooltip shows “Series 1” rather than the variable name oiadpq. Admittedly, both “Series 1” and oiadpq are equally obtuse but we can do better. Let’s label the series “Operating Profits”
The changes in the plot below are as follows:
The header of the tooltip clarifies that it is a fiscal year. Next, it also adds a hyperlink to the filings on the Securities and Exchange Commission’s (SEC’s) EDGAR system.
Changed the content of the tooltip and added more description replacing the default “Series 1” label
plot2 = plot1 |>
hc_tooltip(
headerFormat = "<b>Fiscal Year: {point.x} </b><a href='https://www.sec.gov/edgar/browse/?CIK=0001326801'>SEC </a><br>",
pointFormat = "<span style='color:#f82267'>\U25CF </span><b>Operating Profit: {point.y}</b>",
hideDelay = 1500,
useHTML = TRUE,
style = list(pointerEvents = 'auto')
)
plot2Change the axes titles
Note that I also changed the theme and rotated the X axis text by 270 degrees.
plot3 = plot2 |>
#hc_add_theme(hc_theme_ft()) |>
hc_xAxis(title = list(text = "Fiscal Year",
style = list(color = "#FFFFFF", fontWeight = "bold")),
labels = list(rotation = 270,
style=list(color="#FFFFFF"))) |>
hc_yAxis(title = list(text = "Operating Income in Million USD",
style = list(color = "#FFFFFF", fontWeight = "bold")),
labels=list(style=list(color="#FFFFFF")))
plot3Add title and subtitle
I will switch back to the original theme. But recall that in the previous plot I changed the axis titles color to black. This will not generate enough contrast when we use a dark theme. Therefore, I will make the font color white.
plot4 = plot3 |>
hc_xAxis(title = list(text = "Fiscal Year",
style = list(color = "white", fontWeight = "bold")),
labels = list(rotation = 270)) |>
hc_yAxis(title = list(text = "Operating Income in Million USD",
style = list(color = "white", fontWeight = "bold"))) |>
hc_title(text = "Evil = Profitable??", align = "center") |>
hc_subtitle(text = "Despite all the scandals, Facebook's operating income is consistently growing",
align = "center") |>
hc_add_theme(hc_theme_monokai())
plot4Next, add an emoji to the title. This requires useHTML set to TRUE inside hc_title(). You can get a relevant decimal code for any emoji online. For example, check this out: https://www.w3schools.com/charsets/ref_emoji.asp
plot5 = plot4 |>
hc_title(text = '<span style="font-family: helvetica, inter, sans-serif;"><strong><span style="color: #3598db;">Evil = Profitable??</span></strong></span> <span>🤑</span>',
useHTML = TRUE, align = "center")
plot5Line graph
Plot a line graph of Apple’s leverage ratio over the years.
The leverage ratio is given by (dlttq + dlcq) / atq where dlttq is long-term debt and dlcq is short-term debt. If any of these variables is missing, we should assume they are 0.
d1 |>
filter(tic == "AAPL") |>
mutate(leverage = (replace_na(dlttq, 0) + replace_na(dlcq, 0))/ atq,
leverage = round(leverage, 2)) |>
hchart("line", hcaes(x = datadate, y = leverage), name = "Leverage") |>
# Change these titles
#hc_xAxis() |>
# hc_yAxis() |>
hc_add_theme(hc_theme_538())Scatterplot
Create a scatterplot of profit by sales
d1 |>
hchart("scatter", hcaes(x = saleq, y = oibdpq, group = conm)) |>
hc_add_theme(hc_theme_538())Here, the colors are repeating because the color palette doesn’t have 7 unique colors. We can pass our own colors using hc_colors(). I will use viridis color palettes because it has 256 colors.
Notice that cols color vector in the code below has 8 characters instead of 6 as expected in a typical hex code. The two extra characters are for alpha. We have to remove them before we can use them here. Read more about it here: https://www.quackit.com/css/color/values/css_hex_color_notation_8_digits.cfm
cols = viridisLite::viridis(10, option = "H")
cols = substr(cols, 0, 7) # This will retain first 7 characters including the # sign.
d1 |>
hchart("scatter", hcaes(x = saleq, y = oibdpq, group = conm)) |>
hc_add_theme(hc_theme_538()) |>
hc_colors(cols)Use pals package for more discrete colors: https://rdrr.io/cran/pals/man/discrete.html
cols = pals::alphabet() |> unname()
# unname will remove the names from the vector. Highcharter throws an error if you pass a named vector with colors.
d1 |>
hchart("scatter", hcaes(x = saleq, y = oibdpq, group = conm)) |>
hc_add_theme(hc_theme_538()) |>
hc_colors(cols)Adding a regression line to the scatterplot
We will use a regression plugin to get a regression line. The plugins are available in the following folder on your computer:
Run this code in the console dir(system.file(“htmlwidgets/lib/highcharts/plugins”, package = “highcharter”))
Here is the vignette for regression plugin: https://jkunst.com/highcharter/reference/hc_add_dependency.html
d1 |>
filter(tic == "AAPL") |>
hchart("scatter", hcaes(x = saleq, y = oibdpq), regression = TRUE) |>
hc_add_dependency("plugins/highcharts-regression.js") |>
hc_add_theme(hc_theme_538())Heatmap
We did not see static heatmaps with ggplot2 so let’s learn how to get them using highcharter
To create a heatmap, highcharter needs a data frame or a matrix. A matrix is a data object similar to a data frame as it is 2D. However, a matrix must have ALL its elements of the same class. This is different from a data frame where every column must have elements of the same class but two columns may have different classes.
The most common heatmap is a correlation plot. cor() function from base R outputs a matrix of correlations. Here we visualize correlations between multiple variables in the data set.
cor_dt = d1 |>
select(saleq, oibdpq, cogsq, atq, xrdq, mkvaltq, cheq, capxy) |>
drop_na() |>
cor()class(cor_dt)[1] "matrix" "array"
cor_dt |>
hchart() |>
hc_colorAxis(
stops = color_stops(colors = rev(c("#000004FF",
"#56106EFF",
"#BB3754FF",
"#F98C0AFF",
"#FCFFA4FF")))
)Why are all the correlations positive? For example, why is the correlation between profits (oibdpg) and the costs (cogsg) positive? Shouldn’t that be negative?
d1 |>
select(saleq, oibdpq, cogsq, atq, xrdq, mkvaltq, cheq, capxy) |>
drop_na() |>
mutate(across(everything(), ~.x/saleq)) |>
select(-saleq) |>
cor() |>
hchart()Pie chart
Let’s create a pie chart for all the profits in the fiscal year 2021. This will be an ugly pie chart because there are 10 companies in the data. But interactive pie charts make life a little bit easier!
d1 |>
filter(fyearq == 2023) |>
group_by(conm) |>
summarize(oiadpq = sum(oiadpq, na.rm = TRUE), .groups = "drop") |>
arrange(oiadpq) |>
mutate(conm = str_to_title(conm)) |> # Convert company names to title case
hchart("pie", hcaes(x = conm, y = oiadpq))Change the tooltip to show the series name using name argument in hchart()
d1 |>
filter(fyearq == 2023) |>
group_by(conm) |>
summarize(oiadpq = sum(oiadpq, na.rm = TRUE), .groups = "drop") |>
arrange(oiadpq) |>
mutate(conm = str_to_title(conm)) |> # Convert company names to title case
hchart("pie", hcaes(x = conm, y = oiadpq), name = "Operating Profit")Wordcloud
Highcharter has a module that allows us to create wordclouds with minimal effort.
To create the wordcloud, we need words and their frequencies from text. For this example, I will use a few random tweets collected in November 2021.
tweets = readRDS(here::here("data", "file001.rds"))We will use tidytext package for getting the words from the tweets.
tweet_text = tibble(text = tweets$text) |>
mutate(text = gsub(x = text, pattern = "[0-9]+|[[:punct:]]|\\(.*\\)", replacement = "")) |>
tidytext::unnest_tokens(word, text)Next, let’s delete common words that don’t add much to the analysis. These are words such as “the”, “and”, etc. and called stopwords.
data(stop_words)
tweet_text = tweet_text |> anti_join(stop_words)Joining with `by = join_by(word)`
tweet_text |>
count(word, sort = TRUE)# A tibble: 40,543 × 2
word n
<chr> <int>
1 im 1177
2 dont 802
3 time 539
4 people 536
5 love 524
6 amp 444
7 game 392
8 lol 370
9 day 308
10 play 276
# ℹ 40,533 more rows
We can remove other commonly occurring useless words as follows:
tweet_text = tweet_text |>
filter(!word %in% c("im", "dont", "amp", "youre", "ive", "hes", "didnt", "isnt"))Now we are ready for the wordcloud
word_freq = tweet_text |>
count(word, sort = T)word_freq |>
filter(n > 100) |>
hchart("wordcloud", hcaes(name = word, weight = n), name = "Count")Aside: Wordcloud using wordcloud2 package. Note this is not part of highcharter
word_freq |>
filter(n > 100) |>
wordcloud2(color = "random-light", backgroundColor = "black",
minRotation = 0, maxRotation = 0)Visualizing stock market data
We will compare the stock price movement of Apple and Microsoft
aapl = getSymbols("AAPL", auto.assign = FALSE)
msft = getSymbols("MSFT", auto.assign = FALSE)highchart(type = "stock") |>
hc_add_series(aapl) |>
hc_add_series(msft)