Charting and Comparing Prices in F# - Chart.Combine will not produce graph - f#

I'm working through the charting and comparing prices tutorial on tryfsharp.org and my Chart.Combine function in Fsharp.Charting library will not work, but, other charts, such as Chart.Line will work! Code below.
// Helper function returns dates & closing prices from 2012
let recentPrices symbol =
let data = stockData symbol (DateTime(2012,1,1)) DateTime.Now
[ for row in data.Data -> row.Date.DayOfYear, row.Close ]
Chart.Line(recentPrices "AAPL", Name="Apple") //These two guys work when I try to plot them.
Chart.Line(recentPrices "MSFT", Name="Microsoft")
Chart.Combine( // This guy will not plot. Syntax found here: http://fsharp.github.io/FSharp.Charting/PointAndLineCharts.html
[ Chart.Line(recentPrices "AAPL", Name="Apple")
Chart.Line(recentPrices "MSFT", Name="Microsoft")])

I'd suggest you substituting your data generator function with something simpler and achieving correct plotting with this mockup first. For example, the following script:
#load #"<your path here>\Fsharp.Charting.fsx"
open System
open FSharp.Charting
let rand = System.Random
let recentPricesMock symbol =
[for i in 1..12 -> DateTime(2012,i,1),rand.Next(100)]
Chart.Combine (
[ Chart.Line(recentPricesMock "AAPL", Name="Apple")
Chart.Line(recentPricesMock "MSFT", Name="Microsoft")])
must plot combined mockup chart without any problems, as it does on my local box. From here you may drill down for the cause of original problem comparing your recentPrices with recentPricesMock.
EDIT: after getting to the full problematic source code I can point out two problems there that, as I was expecting, are in your choice of data rather, than in charting per se:
First, your definition of recentPrices converts dates into sequential day of year (row.Date.DayOfYear), so transition from 2012 into 2013 messes up your data and, consequently, charts. If you want to preserve your current functionality then it makes sense to redefine recentPrices as below
let recentPrices symbol =
let data = stockData symbol (DateTime(2012,1,1)) DateTime.Now
[ for row in data.Data -> row.Date, row.Close ]
Second, you chose a pair of stocks that doesn't scale well being combined on the single chart (AAPL in high hundreds $$, while MSFT in low tens $$), which adds to repetition of data points from first problem. After changing in your code AAPL to YHOO in addition to the recentPrices definition change described above
Chart.Combine ([
Chart.Line(recentPrices "YHOO", Name="Yahoo")
Chart.Line(recentPrices "MSFT", Name="Microsoft")
])
yields a beautiful smooth chart combo:

Related

`knitr_out, `file_out` and `vis_drake_graph` usage in R:drake

I'm trying to understand how to use knitr_out, file_out and vis_drake_graph properly in drake.
I have two questions.
Q1: Usage of knitr_out and file_out to create markdown reports
While a code like this works correctly for one of my smaller projects:
make_hyp_data_aggregated_report <- function() {
render(
input = knitr_in("rmd/hyptest-is-data-being-aggregated.Rmd"),
output_file = file_out("~/projectname/reports/01-hyp-test.html"),
quiet = TRUE
)
}
plan <- drake_plan(
...
...
hyp_data_aggregated_report = make_hyp_data_aggregated_report()
...
...
)
Exactly similar code in my large project (with ~10+ reports) doesn't work exactly right. i.e., while the reports get built, the knitr_in objects don't get displayed as the blue squares in the graph using drake::vis_drake_graph() in my large project.
Both projects use the drake::loadd(....) within the markdown to get the objects from cache.
Is there some code in vis_drake_graph that removes these squares once the graph gets busy?
Q2: file_out objects in vis_drake_graph
Is there a way to display the file_out objects themselves as circles/squares in vis_drake_graph?
Q3: packages showing up in vis_drake_graph
Is there a way to avoid vis_drake_graph from printing the packages explicitly? (Basically anything with the ::)
Q1
Every literal file path needs its own knitr_in() or file_out(). If you have one function with one knitr_in(), even if you use the function multiple times, that still only counts as one file path. I recommend writing these keywords at the plan level, e.g.
plan <- drake_plan(
r1 = render(knitr_in("report1.Rmd"), output_file = file_out("report1.html")),
r2 = render(knitr_in("report2.Rmd"), output_file = file_out("report2.html")),
r3 = render(knitr_in("report3.Rmd"), output_file = file_out("report3.html"))
)
Q2
They should appear unless you set show_output_files = FALSE in vis_drake_graph().
Q3
No, but if it's any consolation, I do regret the decision to track namespaced functions and objects at all in drake. drake's approach is fundamentally suboptimal for tracking packages, and I plan to get rid of it if there ever comes time for a round of breaking changes. Otherwise, there is no way to get rid of it except vis_drake_graph(targets_only = TRUE), which also gets rid of all the imports in the graph.

Format built-in types for pretty printing in Deedle

I understand that in order to pretty print things like discriminated unions in Deedle, you have to override ToString(). But what about built in types, like float?
Specifically, I want floats in one column to be displayed as percentages, or at the very least, to not have a million digits past the decimal.
Is there a way to do this?
There is no built-in support for doing this - it sounds like a useful addition, so if you want to contribute this to Deedle, please open an issue to discuss this! We'd be happy to accepta pull request that adds this feature.
As a workaround, I think your best chance is to transform the data in the frame before printing. Something like this should do the trick:
let df = frame [ "A" => series [ 1 => 0.001 ] ]
df |> Frame.map (fun r c (v:float) ->
if c = "A" then box (sprintf "%f%%" (v*100.0)) else box v)
This creates a new frame where all float values of a column named A are transformed using the formatting function sprintf "%f%%" (v*100.0) and the rest is left unchanged.

Number formatting in WebSharper Google Visualization

I have a question concerning WebSharper's Google Visualization library. I was trying to format the data when the mouse hovers over countries in a Geo Chart.
However, there is the following definition for Legend on https://github.com/intellifactory/websharper.google.visualization/blob/master/IntelliFactory.WebSharper.Google.Visualization/Base.fs
type Legend [<Inline "{}">] () =
[<DefaultValue>]
val mutable position : LegendPosition
[<DefaultValue>]
val mutable alignment : LegendAlignment
[<DefaultValue>]
val mutable textStyle : TextStyle
This does not take into account the numberFormat which is used in such charts as GeoChart
https://developers.google.com/chart/interactive/docs/gallery/geochart
Is there a way to circumvent this (to format tooltips/legends) ?
Many thanks
A general workaround: the x?y <- z dynamic assignment can be used in WebSharper code to get x.y = z in the JavaScript translation. So in your case, for example legend?numberFormat <- ".##".
You can also expand the legend type with a helper method for this:
type Legend with
[<JavaScript; Inline>]
member this.WithNumberFormat(format: string) =
this?numberFormat <- format
this
Or you can create a JavaScript object expression by New [ "numberformat" => ".##" ] to use as the Legend object.
WebSharper's Google.Visualization typed bindings are a bit outdated. We will get around to review it completely someday, but feel free to create a pull request if you encounter any missing API functionality.

f# deedle filter data frame based on a list

I wanted to filter a Deedle dataframe based on a list of values how would I go about doing this?
I had an idea to use the following code below:
let d= df1|>filterRowValues(fun row -> row.GetAs<float>("ts") = timex)
However the issue with this is that it is only based on one variable, I then thought of combining this with a for loop and an append function:
for i in 0.. recd.length -1 do
df2.Append(df1|>filterRowValues(fun row -> row.GetAs<float>("ts") = recd.[i]))
This does not work either however and there must be a better way of doing this without using a for loop. In R I could for instance using an %in%.
You can use the F# set type to create a set of the values that you are interested. In the filtering, you can then check whether the set contains the actual value for the row.
For example, say that you have recd of type seq<float>. Then you should be able to write:
let recdSet = set recd
let d = df1 |> Frame.filterRowValues (fun row ->
recdSet.Contains(row.GetAs<float>("ts"))
Some other things that might be useful:
You can replace row.GetAs<float>("ts") with just row?ts (which always returns float and works only when you have a fixed name, like "ts", but it makes the code nicer)
Comparing float values might not be the best thing to do (because of floating point imprecisions, this might not always work as expected).

Writing F# code to parse "2 + 2" into code

Extremely just-started-yesterday new to F#.
What I want: To write code that parses the string "2 + 2" into (using as an example code from the tutorial project) Expr.Add(Expr.Num 2, Expr.Num 2) for evaluation. Some help to at least point me in the right direction or tell me it's too complex for my first F# project. (This is how I learn things: By bashing my head against stuff that's hard)
What I have: My best guess at code to extract the numbers. Probably horribly off base. Also, a lack of clue.
let script = "2 + 2";
let rec scriptParse xs =
match xs with
| [] -> (double)0
| y::ys -> (double)y
let split = (script.Split([|' '|]))
let f x = (split[x]) // "This code is not a function and cannot be applied."
let list = [ for x in 0..script.Length -> f x ]
let result = scriptParse
Thanks.
The immediate issue that you're running into is that split is an array of strings. To access an element of this array, the syntax is split.[x], not split[x] (which would apply split to the singleton list [x], assuming it were a function).
Here are a few other issues:
Your definition of list is probably wrong: x ranges up to the length of script, not the length of the array split. If you want to convert an array or other sequence to a list you can just use List.ofSeq or Seq.toList instead of an explicit list comprehension [...].
Your "casts" to double are a bit odd - that's not the right syntax for performing conversions in F#, although it will work in this case. double is a function, so the parentheses are unnecessary and what you are doing is really calling double 0 and double y. You should just use 0.0 for the first case, and in the second case, it's unclear what you are converting from.
In general, it would probably be better to do a bit more design up front to decide what your overall strategy will be, since it's not clear to me that you'll be able to piece together a working parser based on your current approach. There are several well known techniques for writing a parser - are you trying to use a particular approach?

Resources