F# deedle how to convert frame to list of tuples - f#

say I have a Frame of the following,
type Person =
{ Name:string; Age:int; Comp1:float; Comp2:float }
let peopleRecds =
[ { Name = "Joe"; Age = 51; Comp1=12.1; Comp2 =20.3 }
{ Name = "Tomas"; Age = 28; Comp1=1.1; Comp2 =29.3 }
{ Name = "Eve"; Age = 2; Comp1=2.1; Comp2 =40.3 }
{ Name = "Suzanne"; Age = 15; Comp1=12.4; Comp2 =26.3} ]
let peopleList = Frame.ofRecords peopleRecds
How do i convert peopleList to a list of tuples?

For creating a tuple can use FSharpValue.MakeTuple
Then you need to specify a type or tuple:
open Microsoft.FSharp.Reflection
type Person = { Name:string; Age:int; Comp1:float; Comp2:float }
let peopleRecds =
[ { Name = "Joe"; Age = 51; Comp1=12.1; Comp2 =20.3 }
{ Name = "Tomas"; Age = 28; Comp1=1.1; Comp2 =29.3 }
{ Name = "Eve"; Age = 2; Comp1=2.1; Comp2 =40.3 }
{ Name = "Suzanne"; Age = 15; Comp1=12.4; Comp2 =26.3} ]
let peopleList = Frame.ofRecords peopleRecds
let toListOfTuple (frame:Frame<_,_>) tupleType =
frame.Rows
|> Series.mapValues(Series.values >> Seq.toArray)
|> Series.mapValues(fun x -> FSharpValue.MakeTuple(x, tupleType))
|> Series.values
|> Seq.toList
let tupleType = typeof<(string*int*float*float)>
(peopleList, tupleType)
||> toListOfTuple
|> List.iter(printfn "%A")
Print:
("Joe", 51, 12.1, 20.3)
("Tomas", 28, 1.1, 29.3)
("Eve", 2, 2.1, 40.3)
("Suzanne", 15, 12.4, 26.3)

Related

Eager print in Nix in the repl

The documentation flake-utils has the following example as a doc
eachSystem [ system.x86_64-linux ] (system: { hello = 42; })
# => { hello = { x86_64-linux = 42; }; }
eachSystem allSystems (system: { hello = 42; })
# => {
hello.aarch64-darwin = 42,
hello.aarch64-genode = 42,
hello.aarch64-linux = 42,
...
hello.x86_64-redox = 42,
hello.x86_64-solaris = 42,
hello.x86_64-windows = 42
}
as far as I can tel, one has to
> nix repl
nix-repl> e = builtins.getFlake("github:numtide/flake-utils")
nix-repl> with e.outputs.lib;
eachSystem [ system.x86_64-linux ] (system: { hello = 42; })
to get a result value (one can also do :a e.outputs.lib to "Add attributes from resulting set to scope" and not use the with ..; line )
{ hello = { ... }; }
Is there a way to "eagerly print" the value ?
What you are looking for is :p:
> { a = 3; b = [ 1 2 3 ]; }
{ a = 3; b = [ ... ]; }
> :p { a = 3; b = [ 1 2 3 ]; }
{ a = 3; b = [ 1 2 3 ]; }
>

plotly joins points in wrong order

I have the following df (part)
"Date"
"2022-09-01" "2022-09-02" "2022-09-05" "2022-09-06" "2022-09-07" "2022-09-08" ....
"LogClose"
8.285728 8.274933 8.274933 8.270830 8.289004 8.295593 ....
"wielkoscDD"
0.00000000 -0.01073648 -0.01073648 -0.01478755 0.00000000 0.00000000 ....
I use:
p <- plot_ly(
df,
x = ~Date,
y = ~LogClose,
name = 'zamknięcie',
type = 'scatter',
mode = 'lines',
text = ~paste("zamknięcie :", Zamkniecie),
width = obrazek_szer,
height = obrazek_wyso)
but the second draw is correct
p <- plot_ly(
df,
x = ~Date,
y = ~wielkoscDD,
name = 'drawdown',
type = 'scatter',
mode = 'lines',
text = ~paste("drawdown : ", wielkoscDD),
width = obrazek_szer,
height = obrazek_wyso)
Additionaly on my Mac it works ok - on Windows there is chaos with the 1st chart.
rgds
Grzegorz

Get date value from dictionary

I have a dictionary declared like this:
var result:[Workout] = []
The value in result is following, using print(result):
[Workout {
date = 2019-03-06 22:18:41 +0000;
name = Legday;
exercise = Bbb;
sets = 2;
reps = 1;
kg = 77;
notes = Bb;
}, Workout {
date = 2019-02-24 18:41:07 +0000;
name = bvcj;
exercise = Barbell Bench Press;
sets = 1;
reps = 1;
kg = 87;
notes = Kjj;
}, Workout {
date = 2019-02-22 08:02:23 +0000;
name = Chest;
exercise = Barbell Bench Press;
sets = 3;
reps = 6;
kg = 95;
notes = Ok med spot;
}, Workout {
date = 2019-02-22 08:02:23 +0000;
name = Chest;
exercise = Dips;
sets = 2;
reps = 6;
kg = 40;
notes = Lett, 1 ektra rep på siste sett;
}, Workout {
date = 2019-02-22 08:02:23 +0000;
name = Chest;
exercise = Incline Barbell Bench Press;
sets = 2;
reps = 6;
kg = 72.5;
notes = Tungt;
}, Workout {
date = 2019-02-22 08:02:23 +0000;
name = Chest;
exercise = Triceps Pushdown;
sets = 3;
reps = 12;
kg = 14.5;
notes = Ok;
}, Workout {
date = 2019-02-19 13:38:35 +0000;
name = Legday;
exercise = Squat;
sets = 2;
reps = 2;
kg = 77.5;
notes = Lett;
}, Workout {
date = 2019-02-19 13:38:35 +0000;
name = Legday;
exercise = Leg Press;
sets = 9;
reps = 8;
kg = 100;
notes = Tungt;
}, Workout {
date = 2019-02-18 10:54:34 +0000;
name = Legday;
exercise = Barbell Squat;
sets = 3;
reps = 6;
kg = 75;
notes = Tungt;
}, Workout {
date = 2019-02-18 10:54:34 +0000;
name = Legday;
exercise = Leg Extension;
sets = 10;
reps = 10;
kg = 32;
notes = Lett;
}, Workout {
date = 2019-02-17 21:48:52 +0000;
name = Legday;
exercise = Squat;
sets = 3;
reps = 6;
kg = 60;
notes = Lett;
}, Workout {
date = 2019-02-17 21:48:52 +0000;
name = Legday;
exercise = Tåhev;
sets = 4;
reps = 12;
kg = 40;
notes = Tungt;
}, Workout {
date = 2019-02-17 21:48:52 +0000;
name = Legday;
exercise = Leg Extension;
sets = 3;
reps = 6;
kg = 43.5;
notes = Lett;
}]
I want to get only the date, for each workout. I have tried some different things, and the closest I've got, was using this:
var remoteIndexPath = NSIndexPath(row: 0, section: 0)
func didSelectDayView(_ dayView: DayView, animationDidFinish: Bool) {
let row = result[remoteIndexPath.row]
for i in result.indices { // Prøv dette i stedet for: for i in 0 ..< Results.count {
print(result[remoteIndexPath.row].date)
}
}
The problem is that it only prints out the first value 13 times:
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Optional(2019-03-06 22:18:41 +0000)
Any ideas/tips?
You can try
let res = result.filter { compareDate(date1:$0.date, date2:savedDate) }
print(res)
I think you are asking how to iterate over an array of objects and return the date property?
I don't know what your workout object looks like so I made one up
class Workout {
var date = ""
var name = ""
init(aDate: String, aName: String) {
self.date = aDate
self.name = aName
}
}
var results:[Workout] = []
let w0 = Workout(aDate: "2019-03-06", aName: "Legday")
let w1 = Workout(aDate: "2019-02-24", aName: "bvjc")
let w2 = Workout(aDate: "2019-02-22", aName: "Chest")
results.append(w0)
results.append(w1)
results.append(w2)
let allDates = results.map{ $0.date } //creates an array of just the dates
print(allDates)
and the output is
["2019-03-06", "2019-02-24", "2019-02-22"]

nix function to merge attributes / records recursively and concatenate arrays

Does someone know such function that merges list of records
if all values to merge are records - merge them recursively
if all values to merge are arrays - concatenate arrays
If values can't be merged - the latter value is preferred
Example 1:
recursiveMergeAttrs [
{ a = "x"; c = "m"; list = [1]; }
{ a = "y"; b = "z"; list = [2]; }
]
returns
{ a = "y"; b = "z"; c="m"; list = [1 2] }
Example 2
recursiveMergeAttrs [
{
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/hda";
}
{
boot.loader.grub.device = "";
}
]
returns
{
boot.loader.grub.enable = true;
boot.loader.grub.device = "";
}
P.S.
recursiveUpdate is not working
recursiveMergeAttrs = listOfAttrsets: lib.fold (attrset: acc: lib.recursiveUpdate attrset acc) {} listOfAttrsets
recursiveMergeAttrs [ { a = "x"; c = "m"; list = [1]; } { a = "y"; b = "z"; list = [2]; } ]
returns
{ a = "y"; b = "z"; c = "m"; list = [ 2 ]; }
Did it
{ lib, ... }:
with lib;
/*
Merges list of records, concatenates arrays, if two values can't be merged - the latter is preferred
Example 1:
recursiveMerge [
{ a = "x"; c = "m"; list = [1]; }
{ a = "y"; b = "z"; list = [2]; }
]
returns
{ a = "y"; b = "z"; c="m"; list = [1 2] }
Example 2:
recursiveMerge [
{
a.a = [1];
a.b = 1;
a.c = [1 1];
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/hda";
}
{
a.a = [2];
a.b = 2;
a.c = [1 2];
boot.loader.grub.device = "";
}
]
returns
{
a = {
a = [ 1 2 ];
b = 2;
c = [ 1 2 ];
};
boot = {
loader = {
grub = {
device = "";
enable = true;
};
};
};
}
*/
let
recursiveMerge = attrList:
let f = attrPath:
zipAttrsWith (n: values:
if tail values == []
then head values
else if all isList values
then unique (concatLists values)
else if all isAttrs values
then f (attrPath ++ [n]) values
else last values
);
in f [] attrList;
in
recursiveMerge

F# - Flatten List/Range

I'm new to F# and am wondering how I would go about flattening a list.
Essentially in the database I store a record with a min_age and max_age range (this is a fictitious example for the sake of brevity - i am not agist!). My fields look something like the following:
id,
cost,
savings,
min_age,
max_age
I essentially have an F# class that acts as a one-to-one mapping with this table - i.e. all properties are mapped exactly to the database fields.
What I would like to do is flatten this range. So, instead of a list containing items like this:
saving_id = 1, cost = 100, savings = 20, min_age = 20, max_age = 26
saving_id = 2, cost = 110, savings = 10, min_age = 27, max_age = 31
I would like a list containing items like this:
saving_id = 1, cost = 100, savings = 20, age = 20
saving_id = 1, cost = 100, savings = 20, age = 21
etc.
saving_id = 2, cost = 110, savings = 10, age = 27
saving_id = 2, cost = 110, savings = 10, age = 28
etc.
Is there any in-built mechanism to flatten a list in this manner and/or does anyone know how to achieve this?
Thanks in advance,
JP
You might want to use Seq.collect. It concatenates sequences together, so in your case, you can map a function over your input that splits a single age range record to a sequence of age records and use Seq.collect to glue them together.
For example:
type myRecord =
{ saving_id: int;
cost: int;
savings: int;
min_age: int;
max_age: int }
type resultRecord =
{ saving_id: int;
cost: int;
savings: int;
age: int }
let records =
[ { saving_id = 1; cost = 100; savings = 20; min_age = 20; max_age = 26 }
{ saving_id = 2; cost = 110; savings = 10; min_age = 27; max_age = 31 } ]
let splitRecord (r:myRecord) =
seq { for ageCounter in r.min_age .. r.max_age ->
{ saving_id = r.saving_id;
cost = r.cost;
savings = r.savings;
age = ageCounter }
}
let ageRanges = records |> Seq.collect splitRecord
Edit: you can also use a sequence generator with yield!
let thisAlsoWorks =
seq { for r in records do yield! splitRecord r }
Agreeing with cfern's answer, but was wondering if this might benefit from seeing another "built-in" function used. Here's an alternative version of the splitRecord function that shows the library call for unfolding a sequence. No gain here other than having an example for Seq.unfold.
let splitRecord (r:myRecord) =
Seq.unfold (fun curr_age ->
if curr_age <= r.max_age then
Some({ saving_id = r.saving_id;
cost = r.cost;
savings = r.savings;
age = curr_age } ,
curr_age + 1)
else None)
r.min_age

Resources