loading RProvider in F# - r

I'm still a noob with F#, and I don't understand all the syntax and logic for loading and using packages.
For example, i would like to use (Blue Mountain's) RProvider.
http://bluemountaincapital.github.io/FSharpRProvider/index.html
Using VS2015, in my current solution, I've installed the package with the PM console and Install-Package RProvider
I modified a bit the RProvider.fsx because I've got newer versions of R.NET Community
#nowarn "211"
// Standard NuGet or Paket location
#I "."
#I "lib/net40"
// Standard NuGet locations for R.NET
#I "../R.NET.Community.1.6.4/lib/net40"
#I "../R.NET.Community.FSharp.0.1.9/lib/net40"
// Standard Paket locations for R.NET
#I "../R.NET.Community/lib/net40"
#I "../R.NET.Community.FSharp.1.6.4/lib/net40"
// Try various folders that people might like
#I "bin"
#I "../bin"
#I "../../bin"
#I "lib"
#I "../packages"
// Reference RProvider and RDotNet
#r "RDotNet.dll"
#r "RDotNet.FSharp.dll"
#r "RProvider.dll"
#r "RProvider.Runtime.dll"
open RProvider
do fsi.AddPrinter(fun (synexpr:RDotNet.SymbolicExpression) -> synexpr.Print())
Now my questions are
1) how to load a package (RProvider) from F# interactive ?
well actually i managed to do it this way
For example the RProvider.fsx file is in the path
C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford\packages\RProvider.1.1.15\RProvider.fsx
what i did is
#I #"C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algo Stanford";;
#load "packages\RProvider.1.1.15\RProvider.fsx";;
and it works :-)
but can I avoid writing the whole path ?
2) In VS2015 if I want to include it in a solution...
in the solution explorer i have included the RProvider.fsx file (below AssemblyInfo.fs, App.config and packages.config come after, is this right ?)
and last the program itself Rtype.fs
I'm trying to reproduce the example from
http://bluemountaincapital.github.io/FSharpRProvider/Statistics-QuickStart.html
open System
open *RDotNet* // the namespace or module 'RDotNet' is not defined
open *RProvider*
open *RProvider*.graphics
open RProvider.stats
// let x = System.Environment.CurrentDirectory
// val x : string
printfn "hello world"
Console.ReadKey() |> ignore
// Random number generator
let rng = Random()
let rand () = rng.NextDouble()
// Generate fake X1 and X2
let X1s = [ for i in 0 .. 9 -> 10. * rand () ]
let X2s = [ for i in 0 .. 9 -> 5. * rand () ]
// Build Ys, following the "true" model
let Ys = [ for i in 0 .. 9 -> 5. + 3. * X1s.[i] - 2. * X2s.[i] + rand () ]
let dataset =
namedParams [
"Y", box Ys;
"X1", box X1s;
"X2", box X2s; ]
|> R.data_frame
let result = R.lm(formula = "Y~X1+X2", data = dataset)
let coefficients = result.AsList().["coefficients"].AsNumeric()
let residuals = result.AsList().["residuals"].AsNumeric()
let summary = R.summary(result)
*summary.AsList().["r.squared"].AsNumeric()
R.plot result*
//this expression should have type 'unit' but has type 'NumericVector'...
I'm getting some warnings/errors by Intellisense although the compiler managed a build.
When executing the exe, it looks like the windows screen is busy, i manage to see some graphs, but they look like they have got nothing to do with what Rtype.fs is saying...
thanks for helping !
EDIT

First of all, I would not recommend using a different version of R.NET than the one that RProvider installs automatically as a dependency. The loading is a bit fragile and it might break things.
1) Regarding the path, you should be able to pass relative path to #load, so just dropping the #I from your script should do the trick.
2) When referencing a dependency from a project (rather than from a script file), you need to add a dependency to the project references. In Visual Studio, this is done by right click on the "References" in your project and using "Add Reference". For type providers, you also need to click "Enable" when the reference is loaded.

Related

No extension exist for r:eval

I'm trying to run the RScriptSample present in the samples in the Stream Processor.
I've followed the steps given here.
I have installed R and rJava, and set R_HOME and JRI_HOME accordingly.
#App:name("RScriptSample")
#App:description('Use a R script to process events and produce aggregated outputs based on the provided input variable parameters and expected output attributes.')
define stream weather (time long, temp double);
#sink(type='log')
define stream dataOut (time long, temp double, c long, m double );
#info(name = 'query')
from weather#window.lengthBatch(2)#r:eval("c <- sum(time); m <- sum(temp)", "c long, m double", time, temp)
select * insert into dataOut;
The code does not compile. I'm getting this error in the last line.
No extension exist for r:eval
What am I doing wrong?
Since this extension is under GPL extension, it is not copied to the pack by default. Add the jar to {SP_HOME}/lib folder and try out the sample.
Compatible Version: 4.x.x

Can't load a Haskell dll on Windows

I often create some DLLs with Haskell that I load in R, and this works very well.
But I have some code dealing with the xlsx library, I can compile it to a DLL without issue, but when I load the DLL in R, this totally crashes the R session. However this occurs on Windows only, there's no issue on Linux.
I managed to find a minimal example and there's something weird. This is my minimal example:
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE OverloadedStrings #-}
module TestDLL where
import Codec.Xlsx
import Control.Lens
import qualified Data.ByteString.Lazy as L
import Foreign
import Foreign.C
import Foreign.C.String (peekCString, newCString)
test :: IO ()
test = do
bs <- L.readFile "report.xlsx"
let value = toXlsx bs ^? ixSheet "List1" .
ixCell (3,2) . cellValue . _Just
putStrLn $ "Cell B3 contains " ++ show value
... some elementary functions here ...
If I compile this code to a DLL, loading this DLL in R crashes the R session on Windows. There's no such issue if I remove the test function. However the test function is not even exported (with foreign export) and it is not called by the other functions, isn't it weird ? If I don't export this function and if I don't use it, why the DLL deals with this function ?
And more importantly, why the R session crashes when I load the DLL, and how to fix that ?
Edit
I have a more minimal example now. This works:
test :: IO Xlsx
test = do
bs <- L.readFile "report.xlsx"
return $ toXlsx bs
And this crashes:
test :: IO (Maybe Worksheet)
test = do
bs <- L.readFile "report.xlsx"
return $ toXlsx bs ^? ixSheet "List1"
It looks like Windows has a problem with ^?.
Edit 2
No crash with this equivalent code:
test :: IO (Maybe Worksheet)
test = do
bs <- L.readFile "report.xlsx"
let xlsx = toXlsx bs
let sheets = _xlSheets xlsx
let mapping = DM.fromList sheets
return $ DM.lookup "List1" mapping
Windows has a problem with ^? ixSheet. Now let me try on my real example...
I don't have a solution (edit: I have one, see below) but I can say this is due to the limit of number of exported symbols.
When I compile the code
test :: IO (Maybe Worksheet)
test = do
bs <- L.readFile "report.xlsx"
let xlsx = toXlsx bs
let sheets = _xlSheets xlsx
let mapping = DM.fromList sheets
return $ DM.lookup "List1" mapping
and I inspect the DLL with DependencyWalker, I see there are 48318 exported symbols. That's acceptable.
But for the other code:
test :: IO (Maybe Worksheet)
test = do
bs <- L.readFile "report.xlsx"
return $ toXlsx bs ^? ixSheet "List1"
the generated DLL reaches the maximal number of exported symbols: there are 65535=2^16-1 exported symbols. This DLL is "truncated".
Edit: A possible solution !
A possible solution consists in using a def file. In a file MyDef.def, list the functions you want to export, e.g. funexport and HsStart, like this:
EXPORTS
funexport
HsStart
and add MyDef.def at the end of the command line you use to compile:
ghc -shared foo.hs StartEnd.c -o foo.dll MyDef.def
I have just tested this solution and it works. However this is the first time I test it, so I would not guarantee yet. I'm also surprised that ghc does not automatically do that.

'No converter registered for type Deedle.Frame' using F# R type provider and ggplot2

I'm working on my first attempt to use R's GGPlot2 via the F# R type provider.
Here's my code:
let (++) (plot1:RDotNet.SymbolicExpression) (plot2:RDotNet.SymbolicExpression) =
R.``+``(plot1, plot2)
let ChartGgPlot2 (prices : Prices) =
try
let fileName = makeFile ".png"
let priceSeries = prices.Prices |> Seq.map (fun p -> p.Date, p.Close) |> series
let dataFrame = Deedle.Frame.ofRecords priceSeries
R.png(filename=fileName, height=200, width=300, bg="white") |> ignore
R.ggplot(
namedParams[
"data", box dataFrame;
"mapping", box (
R.aes__string(x="Date", y="Close"))])
++ R.geom__point() |> ignore
R.dev_off() |> ignore
fileName |> Choice.succeed
with
| e -> Choice.fail e.Message
p.Date is a System.DateTime and p.Close is a double.
At runtime I get this exception at the point of calling R.ggplot:
No converter registered for type Deedle.Frame`2[[System.DateTime,
mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089],[System.String, mscorlib,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] or
any of its base types
I've tried the solution suggested suggested here (copying two DLLs): Deedle frame to R but that didn't make a difference.
I should also say that my usage of series and Frame.ofRecords is pretty much guesswork at this point.
Many thanks.
Edit:
It's a compiled .NET 4.6 project with RProvider (1.1.20) and Deedle.RPlugin (1.2.5) added via Nuget.
ggplot2 works correctly from RGui.
Tomas's comment about config files and probing locations wasn't the answer - but it clued me in to what actually was the answer.
I needed to use Nuget to add references to Deedle.RPlugin, not only to the assembly that was doing the R calls to render a chart, but also to my 'main' assembly that references the charting assembly.
I don't know if this is an inherent limitation in the way the build system interacts with the type provider. But for now I'm very happy to have a workaround.
(For teaching purposes it would be great to know if there could be a long term fix.)
Huge thanks to those that replied.
It's quite possible something is off with your FSLab and/or Rprovider install. This for example should work:
#load #"..\..\FSLAB\packages\FsLab\FsLab.fsx"
open System
open Deedle
open FSharp.Charting
open System
open RDotNet
open RProvider
open RProvider.graphics
open RProvider.stats
open RProvider.datasets
open RProvider.ggplot2
type DtPx = {
Dt:System.DateTime
Px:float
}
let rnd = System.Random()
let nextPx() = rnd.NextDouble() - 0.5
let nextDay i = DateTime.Today.AddDays(float i)
let data = List.init 100 (fun i -> {Dt=nextDay i;Px = nextPx()})
let df = Frame.ofRecords data
let mtc = R.mtcars.GetValue<Frame<string, string>>()
let (++) (plot1:RDotNet.SymbolicExpression) (plot2:RDotNet.SymbolicExpression) =
R.``+``(plot1, plot2)
R.ggplot(
namedParams[
"data", box mtc;
"mapping", box (
R.aes__string(x="disp", y="drat"))])
++ R.geom__point()
R.ggplot(
namedParams[
"data", box df;
"mapping", box (
R.aes__string(x="Dt", y="Px"))])
++ R.geom__point()
You can use this in an fsx file, but also in a compiled .exe to save the output to png. In that case you will have to reference DynamicInterop, RDotNet, Rprovider, etc as well.
References:
This is for an empty project nugetting Deedle and RProvider related packages.

Run bash command for currently selected line

I'd like to be able to hit a shortcut like cmd-shift-r and have that automatically run a bash command, say, mix test test/turtle/api/v3_test.exs:72.
In other words: mix test {FILE_ACTIVE}:{FILE_ACTIVE_LINE_NUMBER}
What is the best way to accomplish this? Is there an atom package that takes care of this or something I could write quickly myself?
Thanks!
There is a fairly low-fi way to get this to work using your init.coffee load this by going to File → Init Script... or by choosing Application: Open Your Init Script from the Command Palette.
Add the following to the bottom of your init.coffee:
atom.commands.add 'atom-text-editor',
'custom:execute-this-test': ->
if editor = atom.workspace.getActiveTextEditor()
row = editor.getCursors()[0].getBufferRow() + 1
path = editor.buffer.file.path
{spawn} = require 'child_process'
mix = spawn 'mix', ['test', "#{path}:#{row}"]
mix.stderr.on 'data', (data) ->
atom.notifications.addError data.toString()
mix.stdout.on 'data', (data) ->
atom.notifications.addInfo data.toString()
mix.on 'exit', (code) ->
atom.notifications.addInfo "Exited with Code #{code}"
Save the file with Ctrl-S and reload the text editor with Ctrl-Alt-R.
Once Atom has restarted, find the line in the file you want to execute the code against and open the Command Palette with Ctrl-Shift-P and search for Execute This Test.
You may want to tweak the code to be reduce the amount of output it generates, however the above is probably enough to get you started. If you wanted to optimize the workflow even further you can create a Keybinding.

Why "Reference to undefined global `Moduletest'" in OCaml?

I wrote
let fact x =
let result = ref 1 in
for i = 1 to x do
result := !result * i;
Printf.printf "%d %d %d\n" x i !result;
done;
!result;;
in a file named "Moduletest.ml", and
val fact : int -> int
in a file named "Moduletest.mli".
But, why don't they work?
When I tried to use in ocaml,
Moduletest.fact 3
it told me:
Error: Reference to undefined global `Moduletest'
What's happening?
Thanks.
OCaml toplevel is linked only with a standard library. There're several options on how to make other code visible to it:
copy-pasting
evaluating from the editor
loading files #use directive
making custom toplevel
loading with ocamlfind
Copy-pasting
This self-describing, you just copy code from some source and paste it into toplevel. Don't forget that toplevel won't evaluate your code until you add ;;
Evaluating from the editor
Where the editor is of course Emacs... Well, indeed it can be any other capable editor, like vim for example. This method is an elaboration of the previous, where the editor is actually responsible for copying and pasting the code for you. In Emacs you can evaluate the whole file with C-c C-b command, or you can narrow it to a selected area with C-c C-r, and the most granular is to use C-c C-e, i.e., evaluate an expression. Although it is slightly buggy.
Loading with #use directive.
This directive accepts a filename, and it will essentially copy and paste the code from the file. Notice, that it won't create a file-module for you/ For example, if you have file test.ml with this contents:
(* file test.ml *)
let sum x y = x + y
then loading it with the #use directive, will actually bring to your scope, sum value:
# #use "test.ml";;
# let z = sum 2 2
You mustn't to qualify sum with Test., because no Test module is actually created. #use directive merely copies the contents of the file to the toplevel. Nothing more.
Making custom toplevels
You can create your own toplevel with your code compiled in. It is an advanced theme, so I will skip it.
Loading libraries with ocamlfind
ocamlfind is a tool that allows you to find and load libraries, installed on your system, into your toplevel. By default, toplevel is not linked with any code except standard library. Even, not all parts of the library are actually linked, e.g., Unix module is not available, and needed to be loaded explicitly. There're primitive directives that can load any library, like #load and #include, but they are not for a casual user, especially if you have excellent ocamlfind at your disposal. Before using it, you need to load it, since it is also not available by default. The following command, will load ocamlfind and add few new directives:
# #use "topfind";;
In a process of loading it will show you a little hint on how to use it. The most interesting directive, that is added is #require. It accepts a library name, and loads (i.e., links) its code into toplevel:
# #require "unix";;
This will load a unix library. If you're not sure, about the name of the library you can always view all libraries with a #list command. The #require directive is clever and it will automatically load all dependencies of the library.
If you do not want to type all this directives every time you start OCaml top-level, then you cam create .ocamlinit file in your home directory, and put them there. This file will be loaded automatically on a top-level startup.
I have tested your code and it looks fine. You should "load" it from the OCaml toplevel (launched from the same directory as your .ml and .mli files) in the following way:
# #use "Moduletest.ml";;
val fact : int -> int = <fun>
# fact 4;;
4 1 1
4 2 2
4 3 6
4 4 24
- : int = 24

Resources