R Provider Tutorial

This tutorial demonstrates how to use the R type provider in an F# script. You can also use the R type provider in other scenarios such as apps and libraries.

System requirements

Make sure you have set up your system as specified here.

Referencing the provider

First, make a new F# script (e.g., sample.fsx). In your new script, first load the R type provider from the NuGet package repository.

#r "nuget:RProvider"

For this tutorial, we use open to reference a number of packages including stats, tseries and zoo:

open RProvider
open RProvider.graphics
open RProvider.stats
open RProvider.tseries
open RProvider.zoo

open System
open System.Net.Http

If either of the namespaces above are unrecognized, you need to install the package in R using install.packages("stats").

Pretty-printing R values

Add this line to your script to tell F# interactive how to print out the values of R objects:

fsi.AddPrinter FSIPrinters.rValue

Obtaining data

In this tutorial, we use F# Data to access stock prices from the Yahoo Finance portal. For more information, see the documentation for the CSV type provider.

The following snippet defines a function getStockPrices that returns array with prices for the specified stock and a specified number of days from a stocks API:

// NB The 'demo' key has very limited usage.
let apiKey = "demo"

// URL of a service that generates price data
let url stock = sprintf "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=%s&apikey=%s&datatype=csv" stock apiKey

/// Returns prices (as tuple) of a given stock
let getStockPrices stock count =
    // Download the data and split it into lines
    use wc = new HttpClient()
    let data = wc.GetStringAsync(url stock) |> Async.AwaitTask |> Async.RunSynchronously
    let dataLines = data.Split([| '\n' |], StringSplitOptions.RemoveEmptyEntries)
 
    // Parse lines of the CSV file and take specified
    // number of days using in the oldest to newest order
    seq { for line in dataLines |> Seq.skip 1 do
              let infos = line.Split(',')
              yield float infos.[4] }
    |> Seq.truncate count |> Array.ofSeq |> Array.rev

/// Get opening prices for MSFT for the last 100 days
let msftOpens: float[] = getStockPrices "MSFT" 100

Calling R functions

Now, we're ready to call R functions using the type provider. The following snippet takes msftOpens, calculates logarithm of the values using R.log and then calculates the differences of the resulting vector using R.diff:

// Retrieve stock price time series and compute returns
let msft = msftOpens |> R.log |> R.diff

If you want to see the resulting values, you can call msft.AsVector() in F# Interactive. Next, we use the acf function to display the atuo-correlation and call adf_test to see if the msft returns are stationary/non-unit root:

let a = R.acf(msft)
let adf = R.adf_test(msft) 

After running the first snippet, a window similar to the following should appear (note that it might not appear as a top-most window).

Finally, we can obtain data for multiple different indicators and use the R.pairs function to produce a matrix of scatter plots:

// Build a list of tickers and get diff of logs of prices for each one
let tickers = 
  [ "MSFT"; "AAPL"; "X"; "VXX"; "SPX"; "GLD" ]
let data =
  [ for t in tickers -> 
      printfn "got one!"
      t, getStockPrices t 255 |> R.log |> R.diff ]

// Create an R data frame with the data and call 'R.pairs'
let df = R.data_frame(namedParams data)
R.pairs(df)

As a result, you should see a window showing results similar to these:

namespace RProvider
Multiple items
namespace RProvider

--------------------
type RProvider = inherit TypeProviderForNamespaces new : cfg:TypeProviderConfig -> RProvider

--------------------
new : cfg:CompilerServices.TypeProviderConfig -> RProvider
namespace RProvider.graphics
namespace RProvider.stats
namespace RProvider.tseries
namespace RProvider.zoo
namespace System
namespace System.Net
namespace System.Net.Http
module FSIPrinters from RProvider
<summary> Print functions that may be used in F# interactive to 'pretty-print' R types to the console window. Use in your scripts by passing to `fsi.AddPrinter`. </summary>
val rValue : synexpr:RDotNet.SymbolicExpression -> string
<summary> Print any `SymbolicExpression` using R's built-in `print` function. </summary>
val apiKey : string
val url : stock:string -> string
val stock : string
val sprintf : format:Printf.StringFormat<'T> -> 'T
<summary>Print to a string using the given format.</summary>
<param name="format">The formatter.</param>
<returns>The formatted result.</returns>
val getStockPrices : stock:string -> count:int -> float []
 Returns prices (as tuple) of a given stock
val count : int
val wc : HttpClient
Multiple items
type HttpClient = inherit HttpMessageInvoker new : unit -> unit + 2 overloads member CancelPendingRequests : unit -> unit member DeleteAsync : requestUri: string -> Task<HttpResponseMessage> + 3 overloads member Dispose : disposing: bool -> unit member GetAsync : requestUri: string -> Task<HttpResponseMessage> + 7 overloads member GetByteArrayAsync : requestUri: string -> Task<byte []> + 3 overloads member GetStreamAsync : requestUri: string -> Task<Stream> + 3 overloads member GetStringAsync : requestUri: string -> Task<string> + 3 overloads member PatchAsync : requestUri: string * content: HttpContent -> Task<HttpResponseMessage> + 3 overloads ...
<summary>Provides a class for sending HTTP requests and receiving HTTP responses from a resource identified by a URI.</summary>

--------------------
HttpClient() : HttpClient
HttpClient(handler: HttpMessageHandler) : HttpClient
HttpClient(handler: HttpMessageHandler, disposeHandler: bool) : HttpClient
val data : string
HttpClient.GetStringAsync(requestUri: Uri) : Threading.Tasks.Task<string>
HttpClient.GetStringAsync(requestUri: string) : Threading.Tasks.Task<string>
HttpClient.GetStringAsync(requestUri: Uri, cancellationToken: Threading.CancellationToken) : Threading.Tasks.Task<string>
HttpClient.GetStringAsync(requestUri: string, cancellationToken: Threading.CancellationToken) : Threading.Tasks.Task<string>
Multiple items
type Async = static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit) static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate) static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool> static member AwaitTask : task:Task<'T> -> Async<'T> + 1 overload static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool> static member CancelDefaultToken : unit -> unit static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>> static member Choice : computations:seq<Async<'T option>> -> Async<'T option> static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T> + 3 overloads static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T> ...
<summary>Holds static members for creating and manipulating asynchronous computations.</summary>
<remarks> See also <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/asynchronous-workflows">F# Language Guide - Async Workflows</a>. </remarks>
<category index="1">Async Programming</category>


--------------------
type Async<'T> =
<summary> An asynchronous computation, which, when run, will eventually produce a value of type T, or else raises an exception. </summary>
<remarks> This type has no members. Asynchronous computations are normally specified either by using an async expression or the static methods in the <see cref="T:Microsoft.FSharp.Control.Async" /> type. See also <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/asynchronous-workflows">F# Language Guide - Async Workflows</a>. </remarks>
<namespacedoc><summary> Library functionality for asynchronous programming, events and agents. See also <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/asynchronous-workflows">Asynchronous Programming</a>, <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/members/events">Events</a> and <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/lazy-expressions">Lazy Expressions</a> in the F# Language Guide. </summary></namespacedoc>
<category index="1">Async Programming</category>
static member Async.AwaitTask : task:Threading.Tasks.Task -> Async<unit>
static member Async.AwaitTask : task:Threading.Tasks.Task<'T> -> Async<'T>
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:Threading.CancellationToken -> 'T
val dataLines : string []
String.Split([<ParamArray>] separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: string,?options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: char,?options: StringSplitOptions) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: string, count: int,?options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char, count: int,?options: StringSplitOptions) : string []
type StringSplitOptions = | None = 0 | RemoveEmptyEntries = 1 | TrimEntries = 2
<summary>Specifies options for applicable <see cref="Overload:System.String.Split" /> method overloads, such as whether to omit empty substrings from the returned array or trim whitespace from substrings.</summary>
field StringSplitOptions.RemoveEmptyEntries: StringSplitOptions = 1
<summary><para>Omit array elements that contain an empty string from the result.</para><para>If <see cref="F:System.StringSplitOptions.RemoveEmptyEntries" /> and <see cref="F:System.StringSplitOptions.TrimEntries" /> are specified together, then substrings that consist only of white-space characters are also removed from the result.</para></summary>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
<summary>Builds a sequence using sequence expression syntax</summary>
<param name="sequence">The input sequence.</param>
<returns>The result sequence.</returns>


--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>
<summary>An abbreviation for the CLI type <see cref="T:System.Collections.Generic.IEnumerable`1" /></summary>
<remarks> See the <see cref="T:Microsoft.FSharp.Collections.SeqModule" /> module for further operations related to sequences. See also <a href="https://docs.microsoft.com/dotnet/fsharp/language-reference/sequences">F# Language Guide - Sequences</a>. </remarks>
val line : string
module Seq from Microsoft.FSharp.Collections
<summary>Contains operations for working with values of type <see cref="T:Microsoft.FSharp.Collections.seq`1" />.</summary>
val skip : count:int -> source:seq<'T> -> seq<'T>
<summary>Returns a sequence that skips N elements of the underlying sequence and then yields the remaining elements of the sequence.</summary>
<param name="count">The number of items to skip.</param>
<param name="source">The input sequence.</param>
<returns>The result sequence.</returns>
<exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
<exception cref="T:System.InvalidOperationException">Thrown when count exceeds the number of elements in the sequence.</exception>
val infos : string []
Multiple items
val float : value:'T -> float (requires member op_Explicit)
<summary>Converts the argument to 64-bit float. This is a direct conversion for all primitive numeric types. For strings, the input is converted using <c>Double.Parse()</c> with InvariantCulture settings. Otherwise the operation requires an appropriate static conversion method on the input type.</summary>
<param name="value">The input value.</param>
<returns>The converted float</returns>


--------------------
[<Struct>] type float = Double
<summary>An abbreviation for the CLI type <see cref="T:System.Double" />.</summary>
<category>Basic Types</category>


--------------------
type float<'Measure> = float
<summary>The type of double-precision floating point numbers, annotated with a unit of measure. The unit of measure is erased in compiled code and when values of this type are analyzed using reflection. The type is representationally equivalent to <see cref="T:System.Double" />.</summary>
<category index="6">Basic Types with Units of Measure</category>
val truncate : count:int -> source:seq<'T> -> seq<'T>
<summary>Returns a sequence that when enumerated returns at most N elements.</summary>
<param name="count">The maximum number of items to enumerate.</param>
<param name="source">The input sequence.</param>
<returns>The result sequence.</returns>
<exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
type Array = interface ICollection interface IEnumerable interface IList interface IStructuralComparable interface IStructuralEquatable interface ICloneable new : unit -> unit member Clone : unit -> obj member CopyTo : array: Array * index: int -> unit + 1 overload member GetEnumerator : unit -> IEnumerator ...
<summary>Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the base class for all arrays in the common language runtime.</summary>
val ofSeq : source:seq<'T> -> 'T []
<summary>Builds a new array from the given enumerable object.</summary>
<param name="source">The input sequence.</param>
<returns>The array of elements from the sequence.</returns>
<exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
val rev : array:'T [] -> 'T []
<summary>Returns a new array with the elements in reverse order.</summary>
<param name="array">The input array.</param>
<returns>The reversed array.</returns>
<exception cref="T:System.ArgumentNullException">Thrown when the input array is null.</exception>
val msftOpens : float []
 Get opening prices for MSFT for the last 100 days
val msft : RDotNet.SymbolicExpression
type R = static member ! :?paramArray: obj [] -> SymbolicExpression + 2 overloads static member != :?paramArray: obj [] -> SymbolicExpression + 2 overloads static member !_hexmode :?a: obj -> SymbolicExpression + 2 overloads static member !_octmode :?a: obj -> SymbolicExpression + 2 overloads static member $ :?paramArray: obj [] -> SymbolicExpression + 2 overloads static member $<- :?paramArray: obj [] -> SymbolicExpression + 2 overloads static member $<-_data_frame :?x: obj *?name: obj *?value: obj -> SymbolicExpression + 2 overloads static member $_DLLInfo :?x: obj *?name: obj -> SymbolicExpression + 2 overloads static member $_package__version :?x: obj *?name: obj -> SymbolicExpression + 2 overloads static member %% :?paramArray: obj [] -> SymbolicExpression + 2 overloads ...
Base R functions.
R.log(paramsByName: List<string * obj>) : RDotNet.SymbolicExpression
R.log(paramsByName: Collections.Generic.IDictionary<string,obj>) : RDotNet.SymbolicExpression
R.log(?paramArray: obj []) : RDotNet.SymbolicExpression
Logarithms and Exponentials
R.diff(paramsByName: List<string * obj>) : RDotNet.SymbolicExpression
R.diff(paramsByName: Collections.Generic.IDictionary<string,obj>) : RDotNet.SymbolicExpression
R.diff(?x: obj,?___: obj,?paramArray: obj []) : RDotNet.SymbolicExpression
Lagged Differences
val a : RDotNet.SymbolicExpression
type R = static member AIC :?object: obj *?___: obj *?k: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member ARMAacf :?ar: obj *?ma: obj *?lag_max: obj *?pacf: obj -> SymbolicExpression + 2 overloads static member ARMAtoMA :?ar: obj *?ma: obj *?lag_max: obj -> SymbolicExpression + 2 overloads static member BIC :?object: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member Box_test :?x: obj *?lag: obj *?type: obj *?fitdf: obj -> SymbolicExpression + 2 overloads static member C :?object: obj *?contr: obj *?how_many: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member D :?expr: obj *?name: obj -> SymbolicExpression + 2 overloads static member DF2formula :?x: obj *?env: obj -> SymbolicExpression + 2 overloads static member Gamma :?link: obj -> SymbolicExpression + 2 overloads static member HoltWinters :?x: obj *?alpha: obj *?beta: obj *?gamma: obj *?seasonal: obj *?start_periods: obj *?l_start: obj *?b_start: obj *?s_start: obj *?optim_start: obj *?optim_control: obj -> SymbolicExpression + 2 overloads ...
R statistical functions.
R.acf(paramsByName: List<string * obj>) : RDotNet.SymbolicExpression
R.acf(paramsByName: Collections.Generic.IDictionary<string,obj>) : RDotNet.SymbolicExpression
R.acf(?x: obj,?lag_max: obj,?type: obj,?plot: obj,?na_action: obj,?demean: obj,?___: obj,?paramArray: obj []) : RDotNet.SymbolicExpression
Auto- and Cross- Covariance and -Correlation Function Estimation
val adf : RDotNet.SymbolicExpression
type R = static member adf_test :?x: obj *?alternative: obj *?k: obj -> SymbolicExpression + 2 overloads static member approx_irts :?object: obj *?time: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member arma :?x: obj *?order: obj *?lag: obj *?coef: obj *?include_intercept: obj *?series: obj *?qr_tol: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member as_irts :?object: obj -> SymbolicExpression + 2 overloads static member bds_test :?x: obj *?m: obj *?eps: obj *?trace: obj -> SymbolicExpression + 2 overloads static member daysecond :?object: obj *?tz: obj -> SymbolicExpression + 2 overloads static member garch :?x: obj *?order: obj *?series: obj *?control: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member garch_control :?maxiter: obj *?trace: obj *?start: obj *?grad: obj *?abstol: obj *?reltol: obj *?xtol: obj *?falsetol: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member get_hist_quote :?instrument: obj *?start: obj *?end: obj *?quote: obj *?provider: obj *?method: obj *?origin: obj *?compression: obj *?retclass: obj *?quiet: obj *?drop: obj -> SymbolicExpression + 2 overloads static member irts :?time: obj *?value: obj -> SymbolicExpression + 2 overloads ...
Time series analysis and computational finance.
R.adf_test(paramsByName: List<string * obj>) : RDotNet.SymbolicExpression
R.adf_test(paramsByName: Collections.Generic.IDictionary<string,obj>) : RDotNet.SymbolicExpression
R.adf_test(?x: obj,?alternative: obj,?k: obj) : RDotNet.SymbolicExpression
Augmented Dickey-Fuller Test
val tickers : string list
val data : (string * RDotNet.SymbolicExpression) list
val t : string
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
<summary>Print to <c>stdout</c> using the given format, and add a newline.</summary>
<param name="format">The formatter.</param>
<returns>The formatted result.</returns>
val df : RDotNet.SymbolicExpression
R.data_frame(paramsByName: List<string * obj>) : RDotNet.SymbolicExpression
R.data_frame(paramsByName: Collections.Generic.IDictionary<string,obj>) : RDotNet.SymbolicExpression
R.data_frame(?___: obj,?row_names: obj,?check_rows: obj,?check_names: obj,?fix_empty_names: obj,?stringsAsFactors: obj,?paramArray: obj []) : RDotNet.SymbolicExpression
Data Frames
val namedParams : s:seq<string * 'a> -> Collections.Generic.IDictionary<string,obj>
<summary> Construct a dictionary of named params to pass to an R function. ## Example For example, if you want to call the `R.plot` function with named parameters specifying `x`, `type`, `col` and `ylim`, you can use the following: [ "x", box widgets; "type", box "o"; "col", box "blue"; "ylim", box [0; 25] ] |&gt; namedParams |&gt; R.plot </summary>
type R = static member Axis :?x: obj *?at: obj *?___: obj *?side: obj *?labels: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member abline :?a: obj *?b: obj *?h: obj *?v: obj *?reg: obj *?coef: obj *?untf: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member arrows :?x0: obj *?y0: obj *?x1: obj *?y1: obj *?length: obj *?angle: obj *?code: obj *?col: obj *?lty: obj *?lwd: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member assocplot :?x: obj *?col: obj *?space: obj *?main: obj *?xlab: obj *?ylab: obj -> SymbolicExpression + 2 overloads static member axTicks :?side: obj *?axp: obj *?usr: obj *?log: obj *?nintLog: obj -> SymbolicExpression + 2 overloads static member axis :?side: obj *?at: obj *?labels: obj *?tick: obj *?line: obj *?pos: obj *?outer: obj *?font: obj *?lty: obj *?lwd: obj *?lwd_ticks: obj *?col: obj *?col_ticks: obj *?hadj: obj *?padj: obj *?gap_axis: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member axis_Date :?side: obj *?x: obj *?at: obj *?format: obj *?labels: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member axis_POSIXct :?side: obj *?x: obj *?at: obj *?format: obj *?labels: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member barplot :?height: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads static member barplot_default :?height: obj *?width: obj *?space: obj *?names_arg: obj *?legend_text: obj *?beside: obj *?horiz: obj *?density: obj *?angle: obj *?col: obj *?border: obj *?main: obj *?sub: obj *?xlab: obj *?ylab: obj *?xlim: obj *?ylim: obj *?xpd: obj *?log: obj *?axes: obj *?axisnames: obj *?cex_axis: obj *?cex_names: obj *?inside: obj *?plot: obj *?axis_lty: obj *?offset: obj *?add: obj *?ann: obj *?args_legend: obj *?___: obj *?paramArray: obj [] -> SymbolicExpression + 2 overloads ...
R functions for base graphics.
R.pairs(paramsByName: List<string * obj>) : RDotNet.SymbolicExpression
R.pairs(paramsByName: Collections.Generic.IDictionary<string,obj>) : RDotNet.SymbolicExpression
R.pairs(?x: obj,?___: obj,?paramArray: obj []) : RDotNet.SymbolicExpression
Scatterplot Matrices