如果您喜欢使用 R 进行数据科学创建交互式数据可视化,那么请你收藏。
今天,我们将使用折线图、柱状图和散点图来可视化资产回报。
对于我们的数据,我们将使用以下 5 只 ETF 的 5 年月回报率。
+ SPY (S&P500 fund) + EFA (a non-US equities fund) + IJS (a small-cap value fund) + EEM (an emerging-mkts fund) + AGG (a bond fund)
我们将需要以下包。
library(tidyverse) library(timetk) library(kableExtra) library(highcharter)
由于这不是一篇关于使用 R 处理和转换数据的文章,因此我不会详细介绍如何导入价格数据并转换为月度回报的逻辑,但完整的代码在这里。
symbols <- c("SPY","EFA", "IJS", "EEM","AGG")prices <- getSymbols(symbols, src = 'yahoo', from = "2013-01-01",to = "2017-12-31",auto.assign = TRUE, warnings = FALSE) %>% map(~Ad(get(.))) %>%reduce(merge) %>% `colnames<-`(symbols)prices_monthly <- to.monthly(prices, indexAt = "last", OHLC = FALSE)asset_returns_xts <- na.omit(Return.calculate(prices_monthly, method = "log"))asset_returns_xts <- asset_returns_xts * 100asset_returns_long <- prices %>% to.monthly(indexAt = "last", OHLC = FALSE) %>% tk_tbl(preserve_index = TRUE, rename_index = "date") %>%gather(asset, returns, -date) %>% group_by(asset) %>% mutate(returns = (log(returns) - log(lag(returns))) *100) %>% na.omit()
我们将使用保存每月资产收益的两个数据对象。第一个称为asset_returns_xts
。查看前几行。
SPY EFA IJS EEM AGG 2013-02-28 1.267821 -1.296938 1.6175381 -2.310525 0.58911556 2013-03-28 3.726766 1.296938 4.0257940 -1.023505 0.09849772 2013-04-30 1.903006 4.896773 0.1222544 1.208504 0.96389678 2013-05-31 2.333571 -3.065563 4.1976371 -4.948359 -2.02136579 2013-06-28 -1.343432 -2.715331 -0.1402974 -5.473912 -1.57786534 2013-07-31 5.038578 5.186029 6.3541287 1.315986 0.26879677
我们的每只 ETF 月度回报都有一列,但请注意,日期位于无名列中。事实上,日期根本不在列中,它被视为此矩阵的基于时间的索引。
将其与 进行比较asset_returns_long
。
date | asset | returns |
---|---|---|
2013-02-28 | SPY | 1.267821 |
2013-03-28 | SPY | 3.726766 |
2013-04-30 | SPY | 1.903007 |
2013-05-31 | SPY | 2.333571 |
2013-06-28 | SPY | -1.343432 |
2013-07-31 | SPY | 5.038578 |
此对象有一个名为 的列date
,一个名为 的列asset
和一个名为 的列returns
。它被视为长数据对象,因为 ETF 堆叠成行,而asset_returns_xts
被视为宽数据对象,因为每个 ETF 都有自己的列并使对象更宽。asset_returns_long
和asset_returns_xts
保存完全相同的信息,但格式不同。我们将研究如何使用 highcharter 可视化这两者,因为两者都是金融界流行的数据格式。让我们开始asset_returns_xts
使用 Highcharts 工具链的 Highstock 部分。要从 R 调用此功能,我们首先提供要绘制图表的数据。请注意,我们指定 type = “line”,但这不是必需的,因为默认是折线图。
highchart(type = "stock")highchart(type = "stock") %>% hc_add_series(asset_returns_xts$SPY, type = "line")
两行简短的代码和一个非常漂亮的交互式时间序列!查看图表,注意底部有一个导航器,右上角有一个日期范围选择器。我们不必编写这些代码,默认情况下会创建它们,这对我们的最终用户来说是一个非常好的功能。highchart(type = "stock")
如果我们喜欢不同的颜色,我们可以用 来改变它。color = "green"
highchart (type = “stock” )%>% hc_add_series (asset_returns_xts $ SPY , type = “line” ,color = “green” )
如果我们想要的是柱形图而不是折线图怎么办?代码流程相同,只是我们指定了。type = "column"
highchart(type = "stock") %>% hc_add_series(asset_returns_xts$SPY, type = "column")
将鼠标悬停在这两个图表上,注意工具提示如何自动从 x 轴拉出日期。
对于散点图,我们使用相同的代码流,更改为,但我们还要通过附加 来添加 EFA ETF 的回报。我们可以对所有 5 个 ETF 执行此操作,逐行添加它们,以将所有 5 个放在同一个散点图上。type = "scatter"
hc_add_series(asset_returns_xts$EFA)
highchart(type = "stock") %>% hc_add_series(asset_returns_xts$SPY, type = "scatter") %>% hc_add_series(asset_returns_xts$EFA, type = "scatter"
该图表看起来符合我们的要求,但将鼠标悬停在某个点上时,会发现一些不太理想的外观特征。首先,工具提示显示的日期与 x 轴上显示的日期不一致。其次,它显示的完整 y 轴值超出了小数点后 10 位;第三,它将这两个 ETF 称为和,因为我们没有提供名称。让我们解决这三个问题。series 1
series 2
首先,系列名称用和很容易添加。name = "SPY"
name = "EFA"
highchart(type = "stock") %>% hc_add_series(asset_returns_xts$SPY, type = "scatter", name = "SPY") %>% hc_add_series(asset_returns_xts$EFA, type = "scatter", name = "EFA")
接下来,我们通过添加到流程并使用 更改 x 点显示的格式来修改工具提示格式。这是告诉工具提示使用日期格式。hc_tooltip(pointFormat = )
{point.x:%Y-%m-%d}
然后,我们用 更改 y 点显示,这告诉工具提示四舍五入到小数点后四位,然后在其后放置 % 符号。尝试将其更改为并查看结果。{point.y:.4f}%
{point.y:.8f}
highchart(type = "stock") %>% hc_add_series(asset_returns_xts$SPY, type = "scatter", name = "SPY") %>% hc_add_series(asset_returns_xts$EFA, type = "scatter", name = "EFA") %>% hc_tooltip(pointFormat = '{point.x: %Y-%m-%d}{point.y:.4f}%')
我喜欢 highcharter 选择的默认颜色,但我们可以使用参数自定义它们color
。
highchart(type = "stock") %>% hc_add_series(asset_returns_xts$SPY, type = "scatter", name = "SPY", color = "lightblue") %>% hc_add_series(asset_returns_xts$EFA, type = "scatter", name = "EFA", color = "pink") %>% hc_tooltip(pointFormat = '{point.x: %Y-%m-%d}{point.y:.4f}% ')
这就是所保存的数据的全部内容asset_returns_xts
,让我们探索如何从长格式的数据构建相同的可视化效果。
回想一下 的结构asset_returns_long
。
date | asset | returns |
---|---|---|
2013-02-28 | SPY | 1.267821 |
2013-03-28 | SPY | 3.726766 |
2013-04-30 | SPY | 1.903007 |
2013-05-31 | SPY | 2.333571 |
2013-06-28 | SPY | -1.343432 |
2013-07-31 | SPY | 5.038578 |
如果我们希望创建 SPY 收益的折线图,我们无法选择该SPY
列,因为没有名为 的列SPY
。我们需要通过调用来筛选asset
列是否等于。SPY
filter(asset == "SPY")
asset_returns_long %>% filter(asset == "SPY") %>% head()
现在我们使用运算符将数据从一个函数传递到另一个函数。hchart()
%>%
当我们运行 时,我们会过滤观察结果,然后将它们传递给。括号内的是使用过滤后的数据。这可能看起来有点冗长,但有了这个流程,我们可以快速过滤不同的条件,然后将结果传递给,如果我们想过滤类似的东西而不是(我们稍后会介绍),这会非常方便。asset_returns_long %>% filter(asset == "SPY")
SPY
hchart()
hchart(.)
.
hchart
hchart()
date
asset
但是,我们还没有完成,因为我们需要再次使用 type =“line” 指定图表类型,然后使用 映射我们的美学。为什么我们需要在这里调用,但之前我们不需要这样做?一切都回到数据结构。asset_returns_xts 没有日期列,日期在索引中,highcharter 默认使用该索引。有一个日期列,但 highcharter 无法知道我们想要那个日期列,除非我们明确告诉它。hcaes(x = date, y = returns)
hcaes
asset_returns_long
x-axis
asset_returns_long %>% filter(asset == "SPY") %>% hchart(., type = "line", hcaes(x = date, y = returns))
请注意此图表与上一个折线图之间的一些差异。首先,这里没有导航器或日期选择器。当我们删除时,它们就消失了。此外,y 轴默认位于左侧。我更喜欢这样 - 也许你讨厌它!可以使用 hc_yAxis(opposite = TRUE) 将其改回右侧。为了更好,我们还通过调用 labels = list(format = “{value}%”) 向 y 轴添加一个 % 标签highchart(type = "stock")
asset_returns_long %>% filter(asset == "SPY") %>% hchart(., type = "line", hcaes(x = date, y = returns)) %>% hc_yAxis(opposite = TRUE,labels = list(format = "{value}%"))
我们可以使用完全相同的代码流来创建柱形图,只需更改为。我还希望数据的名称出现在工具提示中,这可以使用 来实现。type = "column"
name = "SPY"
asset_returns_long %>% filter(asset == "SPY") %>% hchart(., type = "column", hcaes(x = date, y = returns),name = "SPY") %>% hc_yAxis(opposite = TRUE,labels = list(format = "{value}%"))
最后,让我们从整洁的长格式数据中创建一个散点图。我们更改为,并再次需要使用指定工具提示格式。type = "scatter"
hc_tooltip(pointFormat = '{point.x:%Y-%m-%d}...)
asset_returns_long %>% filter(asset == "SPY") %>% hchart(., type = "scatter", hcaes(x = date, y = returns),name = "SPY") %>%hc_yAxis(opposite = TRUE,labels = list(format = "{value}%")) %>% hc_tooltip(pointFormat = '{point.x:%Y-%m-%d}{point.y: .4f}%')
好吧,两次构建相同的图表确实需要花费不少功夫。让我们做些不同的事情,看看如何利用我们整洁的长数据来高效地创建更有趣的图表。
假设我们希望将所有 ETF 数据分散到一张图表上,并按组着色。我们可以为每个 ETF返回原始数据,但这会有点繁琐。有了整洁的数据流,我们可以删除然后添加。这会告诉 highcharter 根据其组别为每个 ETF 涂上不同的颜色。请注意它还如何创建图例并在工具提示中包含 ETF 名称。flow and use hc_add_series
filter(asset == "SPY")
hcaes(...group = asset)
asset_returns_long %>% hchart(., type = "scatter", hcaes(x = date, y = returns, group = asset)) %>% hc_yAxis(opposite = TRUE,labels = list(format = "{value}%")) %>% hc_tooltip(pointFormat = '{point.x:%Y-%m-%d}{point.y: .4f}%')
我们可以很快看到,月回报率最低的是2015年8月的EEM。
创建柱状图可能不错,但只用于显示 2017 年的月度收益。这时,筛选的灵活性就派上用场了。我们可以调用 来隔离 2017 年的月份,然后构建柱状图。filter(date >= "2017-01-01" & date <= "2018-01-01")
asset_returns_long %>% filter(date >= "2017-01-01" & date < "2018-01-01") %>% hchart(., type = "column", hcaes(x = date, y = returns, group = asset)) %>% hc_yAxis(opposite = FALSE,labels = list(format = "{value}%")) %>% hc_tooltip(pointFormat = '{point.x: %Y-%m-%d}{point.y:.4f}% ')
请注意,收益如何按日期以列格式自然分组,这有助于按月比较每个 ETF。IJS 似乎是 2017 年波动性最大的,这似乎是 Shiny 应用程序的良好候选者,最终用户可以选择自定义日期期间和一组 ETF 来绘制图表。