Logo Deedle

Data frame features

This page is a comprehensive reference for Frame<'R,'C> operations. If you are new to Deedle, start with the quick start tutorial which introduces loading, filtering, grouping, and missing values using the Titanic data set.

Loading data

CSV files

Frame.ReadCsv loads CSV (and TSV) files. The most common usage is a single path, but it accepts many optional parameters:

let titanic = Frame.ReadCsv(root + "titanic.csv")

// Use a typed index column and sort
let msft = 
  Frame.ReadCsv(root + "stocks/msft.csv") 
  |> Frame.indexRowsDateTime "Date"
  |> Frame.sortRowsByKey

// Semicolon-separated file
let air = Frame.ReadCsv(root + "airquality.csv", separators=";")

// Shorthand: specify index column via type parameter
let msftSimpler = 
  Frame.ReadCsv<DateTime>(root + "stocks/msft.csv", indexCol="Date") 
  |> Frame.sortRowsByKey

Saving CSV files

// Save with semicolon separator
air.SaveCsv(Path.GetTempFileName(), separator=';')

// Include the row key as a column named "Date"
msft.SaveCsv(Path.GetTempFileName(), keyNames=["Date"], separator='\t')

By default SaveCsv omits the row key. Pass includeRowKeys=true or provide keyNames to include it.

From F# records or .NET objects

Frame.ofRecords turns any sequence of records or objects into a frame, using public properties as columns:

type Person = 
  { Name: string; Age: int; Countries: string list }

let peopleRecds = 
  [ { Name = "Joe"; Age = 51; Countries = ["UK"; "US"; "UK"] }
    { Name = "Tomas"; Age = 28; Countries = ["CZ"; "UK"; "US"; "CZ"] }
    { Name = "Eve"; Age = 2; Countries = ["FR"] }
    { Name = "Suzanne"; Age = 15; Countries = ["US"] } ]

let people = 
  Frame.ofRecords peopleRecds 
  |> Frame.indexRowsString "Name"
type Person =
  {
    Name: string
    Age: int
    Countries: string list
  }
val peopleRecds: Person list =
  [{ Name = "Joe"
     Age = 51
     Countries = ["UK"; "US"; "UK"] };
   { Name = "Tomas"
     Age = 28
     Countries = ["CZ"; "UK"; "US"; "CZ"] }; { Name = "Eve"
                                               Age = 2
                                               Countries = ["FR"] };
   { Name = "Suzanne"
     Age = 15
     Countries = ["US"] }]
val people: Frame<string,string> =
  
           Age Countries          
Joe     -> 51  [UK; US; UK]       
Tomas   -> 28  [CZ; UK; US; ... ] 
Eve     -> 2   [FR]               
Suzanne -> 15  [US]

Expanding nested objects

If a column contains complex .NET objects, Frame.expandCols flattens their properties into new columns:

let peopleNested = 
  [ "People" => Series.ofValues peopleRecds ] |> frame

peopleNested |> Frame.expandCols ["People"]
val peopleNested: Frame<int,string> =
  
     People                                             
0 -> { Name = "Joe"
  Age = 51
  Countries = ["UK"; ... 
1 -> { Name = "Tomas"
  Age = 28
  Countries = ["CZ"... 
2 -> { Name = "Eve"
  Age = 2
  Countries = ["FR"] }    
3 -> { Name = "Suzanne"
  Age = 15
  Countries = ["U... 

val it: Frame<int,string> =
  
     People.Name People.Age People.Countries   
0 -> Joe         51         [UK; US; UK]       
1 -> Tomas       28         [CZ; UK; US; ... ] 
2 -> Eve         2          [FR]               
3 -> Suzanne     15         [US]

Getting and setting data

Columns and rows

// Get column as float series (using ?)
people?Age

// Get column with explicit type
people.GetColumn<string list>("Countries")

// All columns as a series of series
people.Columns

Adding and replacing columns

// Add a computed column
people?AgePlusOne <- people?Age |> Series.mapValues ((+) 1.0)

// Add from a list (must match row count)
people?Siblings <- [0; 2; 1; 3]

// Replace an existing column
people.ReplaceColumn("Siblings", [3; 2; 1; 0])

Adding rows

let newRow = 
  [ "Name" => box "Jim"; "Age" => box 51;
    "Countries" => box ["US"]; "Siblings" => box 5 ]
  |> series

people.Merge("Jim", newRow)

Slicing and lookup

Indexing into series

let ages = people?Age

// Single key
ages.["Tomas"]

// Multiple keys
ages.[ ["Tomas"; "Joe"] ]

// Safe lookup (returns None for missing keys)
ages |> Series.tryGet "John"

// Series that may contain missing values for unknown keys
ages |> Series.getAll [ "Tomas"; "John" ]

Iterating observations

// All key-value pairs
ages |> Series.observations

// Including missing values as None
ages |> Series.observationsAll

Slicing ordered series by range

let opens = msft?Open
opens.[DateTime(2013, 1, 1) .. DateTime(2013, 1, 31)]
|> Series.mapKeys (fun k -> k.ToShortDateString())
val opens: Series<DateTime,float> =
  
03/13/1986 -> 25.5  
03/14/1986 -> 28    
03/17/1986 -> 29    
03/18/1986 -> 29.5  
03/19/1986 -> 28.75 
03/20/1986 -> 28.25 
03/21/1986 -> 27.5  
03/24/1986 -> 26.75 
03/25/1986 -> 26    
03/26/1986 -> 26.5  
03/27/1986 -> 27.25 
03/31/1986 -> 27.75 
04/01/1986 -> 27.5  
04/02/1986 -> 27.25 
04/03/1986 -> 27.75 
...        -> ...   
10/18/2013 -> 34.82 
10/21/2013 -> 34.98 
10/22/2013 -> 35.02 
10/23/2013 -> 34.35 
10/24/2013 -> 33.82 
10/25/2013 -> 35.88 
10/28/2013 -> 35.61 
10/29/2013 -> 35.63 
10/30/2013 -> 35.53 
10/31/2013 -> 35.66 
11/01/2013 -> 35.67 
11/04/2013 -> 35.59 
11/05/2013 -> 35.79 
11/06/2013 -> 37.24 
11/07/2013 -> 37.96 

val it: Series<string,float> =
  
01/02/2013 -> 27.25 
01/03/2013 -> 27.63 
01/04/2013 -> 27.27 
01/07/2013 -> 26.77 
01/08/2013 -> 26.75 
01/09/2013 -> 26.72 
01/10/2013 -> 26.65 
01/11/2013 -> 26.49 
01/14/2013 -> 26.9  
01/15/2013 -> 26.83 
01/16/2013 -> 27.15 
01/17/2013 -> 27.19 
01/18/2013 -> 27.1  
01/22/2013 -> 27.3  
01/23/2013 -> 27.2  
01/24/2013 -> 27.7  
01/25/2013 -> 27.58 
01/28/2013 -> 28.01 
01/29/2013 -> 27.82 
01/30/2013 -> 28.01 
01/31/2013 -> 27.79

Grouping and aggregation

The quick start tutorial shows basic Frame.groupRowsByString, Frame.aggregateRowsBy, and Frame.pivotTable. This section covers deeper features: hierarchical keys, Frame.nest/Frame.unnest, and multi-level aggregation.

Hierarchical (multi-level) keys

Grouping produces tuple keys treated as a hierarchical index:

// Group MSFT stock prices by decade
let decades = msft |> Frame.groupRowsUsing (fun k _ -> 
  sprintf "%d0s" (k.Year / 10))

// Mean Close price per decade
decades?Close |> Stats.levelMean fst
val decades: Frame<(string * DateTime),string> =
  
                    Open  High  Low   Close Volume     Adj Close 
1980s 03/13/1986 -> 25.50 29.25 25.50 28.00 1031788800 0.07      
      03/14/1986 -> 28.00 29.50 28.00 29.00 308160000  0.07      
      03/17/1986 -> 29.00 29.75 29.00 29.50 133171200  0.08      
      03/18/1986 -> 29.50 29.75 28.50 28.75 67766400   0.07      
      03/19/1986 -> 28.75 29.00 28.00 28.25 47894400   0.07      
      03/20/1986 -> 28.25 28.25 27.25 27.50 58435200   0.07      
      03/21/1986 -> 27.50 28.00 26.25 26.75 59990400   0.07      
      03/24/1986 -> 26.75 26.75 25.75 26.00 65289600   0.07      
      03/25/1986 -> 26.00 26.50 25.75 26.50 32083200   0.07      
      03/26/1986 -> 26.50 27.50 26.25 27.25 22752000   0.07      
      03/27/1986 -> 27.25 27.75 27.25 27.75 16848000   0.07      
      03/31/1986 -> 27.75 27.75 27.00 27.50 12873600   0.07      
      04/01/1986 -> 27.50 27.50 27.25 27.25 11088000   0.07      
      04/02/1986 -> 27.25 28.00 27.25 27.50 27014400   0.07      
      04/03/1986 -> 27.75 28.50 27.75 27.75 23040000   0.07      
:     :             ...   ...   ...   ...   ...        ...       
2010s 10/18/2013 -> 34.82 34.99 34.33 34.96 41811700   34.96     
      10/21/2013 -> 34.98 35.20 34.91 34.99 27433500   34.99     
      10/22/2013 -> 35.02 35.10 34.52 34.58 40438500   34.58     
      10/23/2013 -> 34.35 34.49 33.67 33.76 58600500   33.76     
      10/24/2013 -> 33.82 34.10 33.57 33.72 53209700   33.72     
      10/25/2013 -> 35.88 36.29 35.47 35.73 113494000  35.73     
      10/28/2013 -> 35.61 35.73 35.27 35.57 38383600   35.57     
      10/29/2013 -> 35.63 35.72 35.26 35.52 31702200   35.52     
      10/30/2013 -> 35.53 35.79 35.43 35.54 36997700   35.54     
      10/31/2013 -> 35.66 35.69 35.34 35.41 41682300   35.41     
      11/01/2013 -> 35.67 35.69 35.39 35.53 40264600   35.53     
      11/04/2013 -> 35.59 35.98 35.55 35.94 28060700   35.94     
      11/05/2013 -> 35.79 36.71 35.77 36.64 51646300   36.64     
      11/06/2013 -> 37.24 38.22 37.06 38.18 88615100   38.18     
      11/07/2013 -> 37.96 38.01 37.43 37.50 60437400   37.50     

val it: Series<string,float> =
  
1980s -> 60.043264033263945 
1990s -> 95.34143196202483  
2000s -> 38.155157057654094 
2010s -> 28.533113402061844
// Means for all numeric columns
decades
|> Frame.getNumericCols
|> Series.mapValues (Stats.levelMean fst)
|> Frame.ofColumns
val it: Frame<string,string> =
  
         Open               High               Low                Close              Volume             Adj Close           
1980s -> 59.946569646569586 61.082629937629896 58.91826403326398  60.043264033263945 70968296.04989605  0.24493762993763055 
1990s -> 95.24579905063263  96.62888449367058  93.89387262658194  95.34143196202483  66713447.7056962   7.927614715189868   
2000s -> 38.16654870775352  38.72730019880724  37.625677932405495 38.155157057654094 70747895.8250497   22.633316103379645  
2010s -> 28.524896907216455 28.779319587628898 28.26515463917527  28.533113402061844 55734837.422680415 27.18783505154637

Multi-level grouping

// Group Titanic by class then port of embarkation
let byClassAndPort = 
  titanic
  |> Frame.groupRowsByInt "Pclass"
  |> Frame.groupRowsByString "Embarked"
  |> Frame.mapRowKeys Pair.flatten3

// Average age per (Embarked, Pclass) group
byClassAndPort?Age
|> Stats.levelMean Pair.get1And2Of3
val byClassAndPort: Frame<(string * int * int),string> =
  
           PassengerId Survived Pclass Name                                               Sex    Age       SibSp Parch Ticket           Fare    Cabin Embarked 
S 3 0   -> 1           False    3      Braund, Mr. Owen Harris                            male   22        1     0     A/5 21171        7.25          S        
S 3 2   -> 3           True     3      Heikkinen, Miss. Laina                             female 26        0     0     STON/O2. 3101282 7.925         S        
S 3 4   -> 5           False    3      Allen, Mr. William Henry                           male   35        0     0     373450           8.05          S        
S 3 7   -> 8           False    3      Palsson, Master. Gosta Leonard                     male   2         3     1     349909           21.075        S        
S 3 8   -> 9           True     3      Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)  female 27        0     2     347742           11.1333       S        
S 3 10  -> 11          True     3      Sandstrom, Miss. Marguerite Rut                    female 4         1     1     PP 9549          16.7    G6    S        
S 3 12  -> 13          False    3      Saundercock, Mr. William Henry                     male   20        0     0     A/5. 2151        8.05          S        
S 3 13  -> 14          False    3      Andersson, Mr. Anders Johan                        male   39        1     5     347082           31.275        S        
S 3 14  -> 15          False    3      Vestrom, Miss. Hulda Amanda Adolfina               female 14        0     0     350406           7.8542        S        
S 3 18  -> 19          False    3      Vander Planke, Mrs. Julius (Emelia Maria Vandem... female 31        1     0     345763           18            S        
S 3 24  -> 25          False    3      Palsson, Miss. Torborg Danira                      female 8         3     1     349909           21.075        S        
S 3 25  -> 26          True     3      Asplund, Mrs. Carl Oscar (Selma Augusta Emilia ... female 38        1     5     347077           31.3875       S        
S 3 29  -> 30          False    3      Todoroff, Mr. Lalio                                male   <missing> 0     0     349216           7.8958        S        
S 3 37  -> 38          False    3      Cann, Mr. Ernest Charles                           male   21        0     0     A./5. 2152       8.05          S        
S 3 38  -> 39          False    3      Vander Planke, Miss. Augusta Maria                 female 18        2     0     345764           18            S        
: : :      ...         ...      ...    ...                                                ...    ...       ...   ...   ...              ...     ...   ...      
C 2 181 -> 182         False    2      Pernot, Mr. Rene                                   male   <missing> 0     0     SC/PARIS 2131    15.05         C        
C 2 292 -> 293         False    2      Levy, Mr. Rene Jacques                             male   36        0     0     SC/Paris 2163    12.875  D     C        
C 2 308 -> 309         False    2      Abelson, Mr. Samuel                                male   30        1     0     P/PP 3381        24            C        
C 2 361 -> 362         False    2      del Carlo, Mr. Sebastiano                          male   29        1     0     SC/PARIS 2167    27.7208       C        
C 2 389 -> 390         True     2      Lehmann, Miss. Bertha                              female 17        0     0     SC 1748          12            C        
C 2 473 -> 474         True     2      Jerwan, Mrs. Amin S (Marie Marthe Thuillard)       female 23        0     0     SC/AH Basle 541  13.7917 D     C        
C 2 547 -> 548         True     2      Padro y Manent, Mr. Julian                         male   <missing> 0     0     SC/PARIS 2146    13.8625       C        
C 2 608 -> 609         True     2      Laroche, Mrs. Joseph (Juliette Marie Louise Laf... female 22        1     2     SC/Paris 2123    41.5792       C        
C 2 685 -> 686         False    2      Laroche, Mr. Joseph Philippe Lemercier             male   25        1     2     SC/Paris 2123    41.5792       C        
C 2 817 -> 818         False    2      Mallet, Mr. Albert                                 male   31        1     1     S.C./PARIS 2079  37.0042       C        
C 2 827 -> 828         True     2      Mallet, Master. Andre                              male   1         0     2     S.C./PARIS 2079  37.0042       C        
C 2 866 -> 867         True     2      Duran y More, Miss. Asuncion                       female 27        1     0     SC/PARIS 2149    13.8583       C        
C 2 874 -> 875         True     2      Abelson, Mrs. Samuel (Hannah Wizosky)              female 28        1     0     P/PP 3381        24            C        
  1 61  -> 62          True     1      Icard, Miss. Amelie                                female 38        0     0     113572           80      B28            
  1 829 -> 830         True     1      Stone, Mrs. George Nelson (Martha Evelyn)          female 62        0     0     113572           80      B28            

val it: Series<(string * int),float> =
  
S 3 -> 25.69655172413793  
S 1 -> 38.15203703703704  
S 2 -> 30.38673076923077  
Q 3 -> 25.9375            
Q 1 -> 38.5               
Q 2 -> 43.5               
C 3 -> 20.741951219512195 
C 1 -> 38.027027027027025 
C 2 -> 22.766666666666666 
  1 -> 50
// Survival counts per group
byClassAndPort.GetColumn<bool>("Survived")
|> Series.applyLevel Pair.get1And2Of3 (Series.values >> Seq.countBy id >> series)
|> Frame.ofRows
val it: Frame<(string * int),bool> =
  
       False     True 
S 3 -> 286       67   
S 1 -> 53        74   
S 2 -> 88        76   
Q 3 -> 45        27   
Q 1 -> 1         1    
Q 2 -> 1         2    
C 3 -> 41        25   
C 1 -> 26        59   
C 2 -> 8         9    
  1 -> <missing> 2

Nesting and unnesting

Frame.nest splits a grouped frame into a series of sub-frames; Frame.unnest reverses this:

let bySex = titanic |> Frame.groupRowsByString "Sex"
let nested = bySex |> Frame.nest      // Series of frames
let flat = nested |> Frame.unnest     // Back to single frame

Grouping series

let travels = people.GetColumn<string list>("Countries")

// Country visit frequency per person, as a frame
travels
|> Series.mapValues (Seq.countBy id >> series)
|> Frame.ofRows
|> Frame.fillMissingWith 0
val travels: Series<string,string list> =
  
Joe     -> [UK; US; UK]       
Tomas   -> [CZ; UK; US; ... ] 
Eve     -> [FR]               
Suzanne -> [US]               

val it: Frame<string,string> =
  
           UK US CZ FR 
Joe     -> 2  1  0  0  
Tomas   -> 1  1  2  0  
Eve     -> 0  0  0  1  
Suzanne -> 0  1  0  0

aggregateRowsBy

Frame.aggregateRowsBy is Deedle's equivalent of SQL GROUP BY … SELECT aggregate(col):

titanic
|> Frame.aggregateRowsBy ["Pclass"; "Sex"] ["Fare"] Stats.mean
val it: Frame<int,string> =
  
     Pclass Sex    Fare               
0 -> 3      male   12.661632564841513 
1 -> 1      female 106.12579787234041 
2 -> 3      female 16.118809722222224 
3 -> 1      male   67.22612704918033  
4 -> 2      female 21.97012105263158  
5 -> 2      male   19.74178240740741
titanic
|> Frame.aggregateRowsBy ["Pclass"] ["Age"] Stats.mean
val it: Frame<int,string> =
  
     Pclass Age                
0 -> 3      25.14061971830986  
1 -> 1      38.233440860215055 
2 -> 2      29.87763005780347

Pivot tables

Cross-tabulate two categorical variables with an aggregation function:

// Passenger counts by Sex × Survived
titanic 
|> Frame.pivotTable 
    (fun k r -> r.GetAs<string>("Sex")) 
    (fun k r -> r.GetAs<bool>("Survived")) 
    Frame.countRows 
val it: Frame<string,bool> =
  
          False True 
male   -> 468   109  
female -> 81    233
// Mean age by Sex × Survived
titanic 
|> Frame.pivotTable 
    (fun k r -> r.GetAs<string>("Sex")) 
    (fun k r -> r.GetAs<bool>("Survived")) 
    (fun frame -> frame?Age |> Stats.mean)
|> round
val it: Frame<string,bool> =
  
          False True 
male   -> 32    27   
female -> 25    29

Handling missing values

The quick start covers fillMissingWith, fillMissing, and dropMissing. This section shows how missing values arise and the more advanced fillMissingUsing strategy.

How missing values arise

Double.NaN, null, and empty Nullable<T> are all treated as missing:

Series.ofValues [ Double.NaN; 1.0; 3.14 ]
val it: Series<int,float> = 
0 -> <missing> 
1 -> 1         
2 -> 3.14
[ Nullable(1); Nullable(); Nullable(3) ] |> Series.ofValues
val it: Series<int,Nullable<int>> =
  
0 -> 1         
1 -> <missing> 
2 -> 3

Custom fill with interpolation

Series.fillMissingUsing calls a function for each missing key, enabling strategies like linear interpolation:

let ozone = air?Ozone

ozone |> Series.fillMissingUsing (fun k -> 
  let prev = ozone.TryGet(k, Lookup.ExactOrSmaller)
  let next = ozone.TryGet(k, Lookup.ExactOrGreater)
  match prev, next with 
  | OptionalValue.Present(p), OptionalValue.Present(n) -> (p + n) / 2.0
  | OptionalValue.Present(v), _ 
  | _, OptionalValue.Present(v) -> v
  | _ -> 0.0)

For the full missing-value reference (sentinel types, all fill strategies, interaction with joins), see Handling missing values.

namespace System
namespace System.IO
namespace Deedle
val fsi: FSharp.Compiler.Interactive.InteractiveSession
member FSharp.Compiler.Interactive.InteractiveSession.AddPrinter: ('T -> string) -> unit
val o: obj
type obj = Object
val iface: Type
Object.GetType() : Type
val fmt: Reflection.MethodInfo
Type.GetMethod(name: string) : Reflection.MethodInfo
   (+0 other overloads)
Type.GetMethod(name: string, types: Type array) : Reflection.MethodInfo
   (+0 other overloads)
Type.GetMethod(name: string, bindingAttr: Reflection.BindingFlags) : Reflection.MethodInfo
   (+0 other overloads)
Type.GetMethod(name: string, types: Type array, modifiers: Reflection.ParameterModifier array) : Reflection.MethodInfo
   (+0 other overloads)
Type.GetMethod(name: string, bindingAttr: Reflection.BindingFlags, types: Type array) : Reflection.MethodInfo
   (+0 other overloads)
Type.GetMethod(name: string, genericParameterCount: int, types: Type array) : Reflection.MethodInfo
   (+0 other overloads)
Type.GetMethod(name: string, genericParameterCount: int, types: Type array, modifiers: Reflection.ParameterModifier array) : Reflection.MethodInfo
   (+0 other overloads)
Type.GetMethod(name: string, genericParameterCount: int, bindingAttr: Reflection.BindingFlags, types: Type array) : Reflection.MethodInfo
   (+0 other overloads)
Type.GetMethod(name: string, bindingAttr: Reflection.BindingFlags, binder: Reflection.Binder, types: Type array, modifiers: Reflection.ParameterModifier array) : Reflection.MethodInfo
   (+0 other overloads)
Type.GetMethod(name: string, bindingAttr: Reflection.BindingFlags, binder: Reflection.Binder, callConvention: Reflection.CallingConventions, types: Type array, modifiers: Reflection.ParameterModifier array) : Reflection.MethodInfo
   (+0 other overloads)
Reflection.MethodBase.Invoke(obj: obj, parameters: obj array) : obj
Reflection.MethodBase.Invoke(obj: obj, invokeAttr: Reflection.BindingFlags, binder: Reflection.Binder, parameters: obj array, culture: Globalization.CultureInfo) : obj
Multiple items
val string: value: 'T -> string

--------------------
type string = String
val root: string
val titanic: Frame<int,string>
Multiple items
module Frame from Deedle
<summary> The `Frame` module provides an F#-friendly API for working with data frames. The module follows the usual desing for collection-processing in F#, so the functions work well with the pipelining operator (`|&gt;`). For example, given a frame with two columns representing prices, we can use `Frame.pctChange` to calculate daily returns like this: let df = frame [ "MSFT" =&gt; prices1; "AAPL" =&gt; prices2 ] let rets = df |&gt; Frame.pctChange 1 rets |&gt; Stats.mean Note that the `Stats.mean` operation is overloaded and works both on series (returning a number) and on frames (returning a series). You can also use `Frame.diff` if you need absolute differences rather than relative changes. The functions in this module are designed to be used from F#. For a C#-friendly API, see the `FrameExtensions` type. For working with individual series, see the `Series` module. The functions in the `Frame` module are grouped in a number of categories and documented below. Accessing frame data and lookup ------------------------------- Functions in this category provide access to the values in the fame. You can also add and remove columns from a frame (which both return a new value). - `addCol`, `replaceCol` and `dropCol` can be used to create a new data frame with a new column, by replacing an existing column with a new one, or by dropping an existing column - `cols` and `rows` return the columns or rows of a frame as a series containing objects; `getCols` and `getRows` return a generic series and cast the values to the type inferred from the context (columns or rows of incompatible types are skipped); `getNumericCols` returns columns of a type convertible to `float` for convenience. - You can get a specific row or column using `get[Col|Row]` or `lookup[Col|Row]` functions. The `lookup` variant lets you specify lookup behavior for key matching (e.g. find the nearest smaller key than the specified value). There are also `[try]get` and `[try]Lookup` functions that return optional values and functions returning entire observations (key together with the series). - `sliceCols` and `sliceRows` return a sub-frame containing only the specified columns or rows. Finally, `toArray2D` returns the frame data as a 2D array. Grouping, windowing and chunking -------------------------------- The basic grouping functions in this category can be used to group the rows of a data frame by a specified projection or column to create a frame with hierarchical index such as <c>Frame&lt;'K1 * 'K2, 'C&gt;</c>. The functions always aggregate rows, so if you want to group columns, you need to use `Frame.transpose` first. The function `groupRowsBy` groups rows by the value of a specified column. Use `groupRowsBy[Int|Float|String...]` if you want to specify the type of the column in an easier way than using type inference; `groupRowsUsing` groups rows using the specified _projection function_ and `groupRowsByIndex` projects the grouping key just from the row index. More advanced functions include: `aggregateRowsBy` which groups the rows by a specified sequence of columns and aggregates each group into a single value; `pivotTable` implements the pivoting operation [as documented in the tutorials](../frame.html#pivot). The `melt` and `unmelt` functions turn the data frame into a single data frame containing columns `Row`, `Column` and `Value` containing the data of the original frame; `unmelt` can be used to turn this representation back into an original frame. The `stack` and `unstack` functions implement pandas-style reshape operations. `stack` converts `Frame&lt;'R,'C&gt;` to a long-format `Frame&lt;'R*'C, string&gt;` where each cell becomes a row keyed by `(rowKey, colKey)` with a single `"Value"` column. `unstack` promotes the inner row-key level to column keys, producing `Frame&lt;'R1, 'C*'R2&gt;` from `Frame&lt;'R1*'R2,'C&gt;`. A simple windowing functions that are exposed for an entire frame operations are `window` and `windowInto`. For more complex windowing operations, you currently have to use `mapRows` or `mapCols` and apply windowing on individual series. Sorting and index manipulation ------------------------------ A frame is indexed by row keys and column keys. Both of these indices can be sorted (by the keys). A frame that is sorted allows a number of additional operations (such as lookup using the `Lookp.ExactOrSmaller` lookup behavior). The functions in this category provide ways for manipulating the indices. It is expected that most operations are done on rows and so more functions are available in a row-wise way. A frame can alwyas be transposed using `Frame.transpose`. Index operations: The existing row/column keys can be replaced by a sequence of new keys using the `indexColsWith` and `indexRowsWith` functions. Row keys can also be replaced by ordinal numbers using `indexRowsOrdinally`. The function `indexRows` uses the specified column of the original frame as the index. It removes the column from the resulting frame (to avoid this, use overloaded `IndexRows` method). This function infers the type of row keys from the context, so it is usually more convenient to use `indexRows[Date|String|Int|...]` functions. Finally, if you want to calculate the index value based on multiple columns of the row, you can use `indexRowsUsing`. Sorting frame rows: Frame rows can be sorted according to the value of a specified column using the `sortRows` function; `sortRowsBy` takes a projection function which lets you transform the value of a column (e.g. to project a part of the value). The functions `sortRowsByKey` and `sortColsByKey` sort the rows or columns using the default ordering on the key values. The result is a frame with ordered index. Expanding columns: When the frame contains a series with complex .NET objects such as F# records or C# classes, it can be useful to "expand" the column. This operation looks at the type of the objects, gets all properties of the objects (recursively) and generates multiple series representing the properties as columns. The function `expandCols` expands the specified columns while `expandAllCols` applies the expansion to all columns of the data frame. Frame transformations --------------------- Functions in this category perform standard transformations on data frames including projections, filtering, taking some sub-frame of the frame, aggregating values using scanning and so on. Projection and filtering functions such as `[map|filter][Cols|Rows]` call the specified function with the column or row key and an <c>ObjectSeries&lt;'K&gt;</c> representing the column or row. You can use functions ending with `Values` (such as `mapRowValues`) when you do not require the row key, but only the row series; `mapRowKeys` and `mapColKeys` can be used to transform the keys. You can use `reduceValues` to apply a custom reduction to values of columns. Other aggregations are available in the `Stats` module. You can also get a row with the greaterst or smallest value of a given column using `[min|max]RowBy`. The functions `take[Last]` and `skip[Last]` can be used to take a sub-frame of the original source frame by skipping a specified number of rows. Note that this does not require an ordered frame and it ignores the index - for index-based lookup use slicing, such as `df.Rows.[lo .. hi]`, instead. Finally the `shift` function can be used to obtain a frame with values shifted by the specified offset. This can be used e.g. to get previous value for each key using `Frame.shift 1 df`. The `diff` function calculates difference from previous value using `df - (Frame.shift offs df)`. Processing frames with exceptions --------------------------------- The functions in this group can be used to write computations over frames that may fail. They use the type <c>tryval&lt;'T&gt;</c> which is defined as a discriminated union with two cases: Success containing a value, or Error containing an exception. Using <c>tryval&lt;'T&gt;</c> as a value in a data frame is not generally recommended, because the type of values cannot be tracked in the type. For this reason, it is better to use <c>tryval&lt;'T&gt;</c> with individual series. However, `tryValues` and `fillErrorsWith` functions can be used to get values, or fill failed values inside an entire data frame. The `tryMapRows` function is more useful. It can be used to write a transformation that applies a computation (which may fail) to each row of a data frame. The resulting series is of type <c>Series&lt;'R, tryval&lt;'T&gt;&gt;</c> and can be processed using the <c>Series</c> module functions. Missing values -------------- This group of functions provides a way of working with missing values in a data frame. The category provides the following functions that can be used to fill missing values: * `fillMissingWith` fills missing values with a specified constant * `fillMissingUsing` calls a specified function for every missing value * `fillMissing` and variants propagates values from previous/later keys We use the terms _sparse_ and _dense_ to denote series that contain some missing values or do not contain any missing values, respectively. The functions `denseCols` and `denseRows` return a series that contains only dense columns or rows and all sparse rows or columns are replaced with a missing value. The `dropSparseCols` and `dropSparseRows` functions drop these missing values and return a frame with no missing values. Joining, merging and zipping ---------------------------- The simplest way to join two frames is to use the `join` operation which can be used to perform left, right, outer or inner join of two frames. When the row keys of the frames do not match exactly, you can use `joinAlign` which takes an additional parameter that specifies how to find matching key in left/right join (e.g. by taking the nearest smaller available key). Frames that do not contian overlapping values can be combined using `merge` (when combining just two frames) or using `mergeAll` (for larger number of frames). Tha latter is optimized to work well for a large number of data frames. Finally, frames with overlapping values can be combined using `zip`. It takes a function that is used to combine the overlapping values. A `zipAlign` function provides a variant with more flexible row key matching (as in `joinAlign`) Hierarchical index operations ----------------------------- A data frame has a hierarchical row index if the row index is formed by a tuple, such as <c>Frame&lt;'R1 * 'R2, 'C&gt;</c>. Frames of this kind are returned, for example, by the grouping functions such as <c>Frame.groupRowsBy</c>. The functions in this category provide ways for working with data frames that have hierarchical row keys. The functions <c>applyLevel</c> and <c>reduceLevel</c> can be used to reduce values according to one of the levels. The <c>applyLevel</c> function takes a reduction of type <c>Series&lt;'K, 'T&gt; -&gt; 'T</c> while <c>reduceLevel</c> reduces individual values using a function of type <c>'T -&gt; 'T -&gt; 'T</c>. The functions <c>nest</c> and <c>unnest</c> can be used to convert between frames with hierarchical indices (<c>Frame&lt;'K1 * 'K2, 'C&gt;</c>) and series of frames that represent individual groups (<c>Series&lt;'K1, Frame&lt;'K2, 'C&gt;&gt;</c>). The <c>nestBy</c> function can be used to perform group by operation and return the result as a series of frems. </summary>
<category>Frame and series operations</category>


--------------------
type Frame = static member ReadCsv: location: string * hasHeaders: Nullable<bool> * inferTypes: Nullable<bool> * inferRows: Nullable<int> * schema: string * separators: string * culture: string * maxRows: Nullable<int> * missingValues: string array * preferOptions: bool * encoding: Encoding -> Frame<int,string> + 1 overload static member ReadReader: reader: IDataReader -> Frame<int,string> static member CustomExpanders: Dictionary<Type,Func<obj,(string * Type * obj) seq>> static member NonExpandableInterfaces: ResizeArray<Type> static member NonExpandableTypes: HashSet<Type>
<summary> Provides static methods for creating frames, reading frame data from CSV files and database (via IDataReader). The type also provides global configuration for reflection-based expansion. </summary>
<category>Frame and series operations</category>


--------------------
type Frame<'TRowKey,'TColumnKey (requires equality and equality)> = interface IDynamicMetaObjectProvider interface INotifyCollectionChanged interface IFrameFormattable interface IFsiFormattable interface IFrame new: rowIndex: IIndex<'TRowKey> * columnIndex: IIndex<'TColumnKey> * data: IVector<IVector> * indexBuilder: IIndexBuilder * vectorBuilder: IVectorBuilder -> Frame<'TRowKey,'TColumnKey> + 1 overload member AddColumn: column: 'TColumnKey * series: 'V seq -> unit + 3 overloads member AggregateRowsBy: groupBy: 'TColumnKey seq * aggBy: 'TColumnKey seq * aggFunc: Func<Series<'TRowKey,'a>,'b> -> Frame<int,'TColumnKey> member Clone: unit -> Frame<'TRowKey,'TColumnKey> member ColumnApply: f: Func<Series<'TRowKey,'T>,ISeries<'TRowKey>> -> Frame<'TRowKey,'TColumnKey> + 1 overload ...
<summary> A frame is the key Deedle data structure (together with series). It represents a data table (think spreadsheet or CSV file) with multiple rows and columns. The frame consists of row index, column index and data. The indices are used for efficient lookup when accessing data by the row key `'TRowKey` or by the column key `'TColumnKey`. Deedle frames are optimized for the scenario when all values in a given column are of the same type (but types of different columns can differ). </summary>
<remarks><para>Joining, zipping and appending:</para><para> More info </para></remarks>
<category>Core frame and series types</category>


--------------------
new: names: 'TColumnKey seq * columns: ISeries<'TRowKey> seq -> Frame<'TRowKey,'TColumnKey>
new: rowIndex: Indices.IIndex<'TRowKey> * columnIndex: Indices.IIndex<'TColumnKey> * data: IVector<IVector> * indexBuilder: Indices.IIndexBuilder * vectorBuilder: Vectors.IVectorBuilder -> Frame<'TRowKey,'TColumnKey>
static member Frame.ReadCsv: reader: TextReader * ?hasHeaders: bool * ?inferTypes: bool * ?inferRows: int * ?schema: string * ?separators: string * ?culture: string * ?maxRows: int * ?missingValues: string array * ?preferOptions: bool * ?typeResolver: (string -> string option) -> Frame<int,string>
static member Frame.ReadCsv: stream: Stream * hasHeaders: Nullable<bool> * inferTypes: Nullable<bool> * inferRows: Nullable<int> * schema: string * separators: string * culture: string * maxRows: Nullable<int> * missingValues: string array * preferOptions: Nullable<bool> * encoding: Text.Encoding -> Frame<int,string>
static member Frame.ReadCsv: location: string * hasHeaders: Nullable<bool> * inferTypes: Nullable<bool> * inferRows: Nullable<int> * schema: string * separators: string * culture: string * maxRows: Nullable<int> * missingValues: string array * preferOptions: bool * encoding: Text.Encoding -> Frame<int,string>
static member Frame.ReadCsv: path: string * ?hasHeaders: bool * ?inferTypes: bool * ?inferRows: int * ?schema: string * ?separators: string * ?culture: string * ?maxRows: int * ?missingValues: string array * ?preferOptions: bool * ?typeResolver: (string -> string option) * ?encoding: Text.Encoding -> Frame<int,string>
static member Frame.ReadCsv: stream: Stream * ?hasHeaders: bool * ?inferTypes: bool * ?inferRows: int * ?schema: string * ?separators: string * ?culture: string * ?maxRows: int * ?missingValues: string array * ?preferOptions: bool * ?typeResolver: (string -> string option) * ?encoding: Text.Encoding -> Frame<int,string>
static member Frame.ReadCsv: path: string * indexCol: string * ?hasHeaders: bool * ?inferTypes: bool * ?inferRows: int * ?schema: string * ?separators: string * ?culture: string * ?maxRows: int * ?missingValues: string array * ?preferOptions: bool * ?typeResolver: (string -> string option) * ?encoding: Text.Encoding -> Frame<'R,string> (requires equality)
val msft: Frame<DateTime,string>
val indexRowsDateTime: column: 'C -> frame: Frame<'R1,'C> -> Frame<DateTime,'C> (requires equality and equality)
<summary> Returns a data frame whose rows are indexed based on the specified column of the original data frame. This function casts (or converts) the column key to values of type `DateTime` (a generic variant that may require some type annotation is `Frame.indexRows`) The specified column is removed from the resulting frame. </summary>
<param name="frame">Source data frame whose row index is to be replaced.</param>
<param name="column">The name of a column in the original data frame that will be used for the new index. Note that the values in the column need to be unique.</param>
<category>Sorting and index manipulation</category>
val sortRowsByKey: frame: Frame<'R,'C> -> Frame<'R,'C> (requires equality and equality)
<summary> Returns a data frame that contains the same data as the input, but whose rows are an ordered series. This allows using operations that are only available on indexed series such as alignment and inexact lookup. &lt;category&gt;Sorting and index manipulation&lt;/category&gt; </summary>
val air: Frame<int,string>
val msftSimpler: Frame<DateTime,string>
Multiple items
type DateTime = new: date: DateOnly * time: TimeOnly -> unit + 16 overloads member Add: value: TimeSpan -> DateTime member AddDays: value: float -> DateTime member AddHours: value: float -> DateTime member AddMicroseconds: value: float -> DateTime member AddMilliseconds: value: float -> DateTime member AddMinutes: value: float -> DateTime member AddMonths: months: int -> DateTime member AddSeconds: value: float -> DateTime member AddTicks: value: int64 -> DateTime ...
<summary>Represents an instant in time, typically expressed as a date and time of day.</summary>

--------------------
DateTime ()
   (+0 other overloads)
DateTime(ticks: int64) : DateTime
   (+0 other overloads)
DateTime(date: DateOnly, time: TimeOnly) : DateTime
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : DateTime
   (+0 other overloads)
DateTime(date: DateOnly, time: TimeOnly, kind: DateTimeKind) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : DateTime
   (+0 other overloads)
member Frame.SaveCsv: path: string * keyNames: string seq -> unit
static member FrameExtensions.SaveCsv: frame: Frame<'R,'C> * path: string * keyNames: string seq * separator: char * culture: Globalization.CultureInfo -> unit (requires equality and equality)
static member FrameExtensions.SaveCsv: frame: Frame<'R,'C> * writer: TextWriter * includeRowKeys: bool * keyNames: string seq * separator: char * culture: Globalization.CultureInfo -> unit (requires equality and equality)
static member FrameExtensions.SaveCsv: frame: Frame<'R,'C> * path: string * includeRowKeys: bool * keyNames: string seq * separator: char * culture: Globalization.CultureInfo -> unit (requires equality and equality)
member Frame.SaveCsv: writer: TextWriter * ?includeRowKeys: bool * ?keyNames: string seq * ?separator: char * ?culture: Globalization.CultureInfo -> unit
member Frame.SaveCsv: path: string * ?includeRowKeys: bool * ?keyNames: string seq * ?separator: char * ?culture: Globalization.CultureInfo -> unit
type Path = static member ChangeExtension: path: string * extension: string -> string static member Combine: path1: string * path2: string -> string + 4 overloads static member EndsInDirectorySeparator: path: ReadOnlySpan<char> -> bool + 1 overload static member Exists: path: string -> bool static member GetDirectoryName: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload static member GetExtension: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload static member GetFileName: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload static member GetFileNameWithoutExtension: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload static member GetFullPath: path: string -> string + 1 overload static member GetInvalidFileNameChars: unit -> char array ...
<summary>Performs operations on <see cref="T:System.String" /> instances that contain file or directory path information. These operations are performed in a cross-platform manner.</summary>
Path.GetTempFileName() : string
type Person = { Name: string Age: int Countries: string list }
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
type 'T list = List<'T>
val peopleRecds: Person list
val people: Frame<string,string>
static member Frame.ofRecords: series: Series<'K,'R> -> Frame<'K,string> (requires equality)
static member Frame.ofRecords: values: 'T seq -> Frame<int,string>
static member Frame.ofRecords: values: Collections.IEnumerable * indexCol: string -> Frame<'R,string> (requires equality)
val indexRowsString: column: 'C -> frame: Frame<'R1,'C> -> Frame<string,'C> (requires equality and equality)
<summary> Returns a data frame whose rows are indexed based on the specified column of the original data frame. This function casts (or converts) the column key to values of type `string` (a generic variant that may require some type annotation is `Frame.indexRows`) The specified column is removed from the resulting frame. </summary>
<param name="frame">Source data frame whose row index is to be replaced.</param>
<param name="column">The name of a column in the original data frame that will be used for the new index. Note that the values in the column need to be unique.</param>
<category>Sorting and index manipulation</category>
val peopleNested: Frame<int,string>
Multiple items
module Series from Deedle
<summary> The `Series` module provides an F#-friendly API for working with data and time series. The API follows the usual design for collection-processing in F#, so the functions work well with the pipelining (<c>|&gt;</c>) operator. For example, given a series with ages, we can use `Series.filterValues` to filter outliers and then `Stats.mean` to calculate the mean: ages |&gt; Series.filterValues (fun v -&gt; v &gt; 0.0 &amp;&amp; v &lt; 120.0) |&gt; Stats.mean The module provides comprehensive set of functions for working with series. The same API is also exposed using C#-friendly extension methods. In C#, the above snippet could be written as: [lang=csharp] ages .Where(kvp =&gt; kvp.Value &gt; 0.0 &amp;&amp; kvp.Value &lt; 120.0) .Mean() For more information about similar frame-manipulation functions, see the `Frame` module. For more information about C#-friendly extensions, see `SeriesExtensions`. The functions in the `Series` module are grouped in a number of categories and documented below. Accessing series data and lookup -------------------------------- Functions in this category provide access to the values in the series. - The term _observation_ is used for a key value pair in the series. - When working with a sorted series, it is possible to perform lookup using keys that are not present in the series - you can specify to search for the previous or next available value using _lookup behavior_. - Functions such as `get` and `getAll` have their counterparts `lookup` and `lookupAll` that let you specify lookup behavior. - For most of the functions that may fail, there is a `try[Foo]` variant that returns `None` instead of failing. - Functions with a name ending with `At` perform lookup based on the absolute integer offset (and ignore the keys of the series) Series transformations ---------------------- Functions in this category perform standard transformations on series including projections, filtering, taking some sub-series of the series, aggregating values using scanning and so on. Projection and filtering functions generally skip over missing values, but there are variants `filterAll` and `mapAll` that let you handle missing values explicitly. Keys can be transformed using `mapKeys`. When you do not need to consider the keys, and only care about values, use `filterValues` and `mapValues` (which is also aliased as the `$` operator). Series supports standard set of folding functions including `reduce` and `fold` (to reduce series values into a single value) as well as the `scan[All]` function, which can be used to fold values of a series into a series of intermeidate folding results. The functions `take[Last]` and `skip[Last]` can be used to take a sub-series of the original source series by skipping a specified number of elements. Note that this does not require an ordered series and it ignores the index - for index-based lookup use slicing, such as `series.[lo .. hi]`, instead. Finally the `shift` function can be used to obtain a series with values shifted by the specified offset. This can be used e.g. to get previous value for each key using `Series.shift 1 ts`. The `diff` function calculates difference from previous value using `ts - (Series.shift offs ts)`. Processing series with exceptions --------------------------------- The functions in this group can be used to write computations over series that may fail. They use the type <c>tryval&lt;'T&gt;</c> which is defined as a discriminated union with two cases: Success containing a value, or Error containing an exception. The function `tryMap` lets you create <c>Series&lt;'K, tryval&lt;'T&gt;&gt;</c> by mapping over values of an original series. You can then extract values using `tryValues`, which throws `AggregateException` if there were any errors. Functions `tryErrors` and `trySuccesses` give series containing only errors and successes. You can fill failed values with a constant using `fillErrorsWith`. Hierarchical index operations ----------------------------- When the key of a series is tuple, the elements of the tuple can be treated as multiple levels of a index. For example <c>Series&lt;'K1 * 'K2, 'V&gt;</c> has two levels with keys of types <c>'K1</c> and <c>'K2</c> respectively. The functions in this cateogry provide a way for aggregating values in the series at one of the levels. For example, given a series `input` indexed by two-element tuple, you can calculate mean for different first-level values as follows: input |&gt; applyLevel fst Stats.mean Note that the `Stats` module provides helpers for typical statistical operations, so the above could be written just as `input |&gt; Stats.levelMean fst`. Grouping, windowing and chunking -------------------------------- This category includes functions that group data from a series in some way. Two key concepts here are _window_ and _chunk_. Window refers to (overlapping) sliding windows over the input series while chunk refers to non-overlapping blocks of the series. The boundary behavior can be specified using the `Boundary` flags. The value `Skip` means that boundaries (incomplete windows or chunks) should be skipped. The value `AtBeginning` and `AtEnding` can be used to define at which side should the boundary be returned (or skipped). For chunking, `AtBeginning ||| Skip` makes sense and it means that the incomplete chunk at the beginning should be skipped (aligning the last chunk with the end). The behavior may be specified in a number of ways (which is reflected in the name): - `dist` - using an absolute distance between the keys - `while` - using a condition on the first and last key - `size` - by specifying the absolute size of the window/chunk The functions ending with `Into` take a function to be applied to the window/chunk. The functions `window`, `windowInto` and `chunk`, `chunkInto` are simplified versions that take a size. There is also `pairwise` function for sliding window of size two. Missing values -------------- This group of functions provides a way of working with missing values in a series. The `dropMissing` function drops all keys for which there are no values in the series. The `withMissingFrom` function lets you copy missing values from another series. The remaining functions provide different mechanism for filling the missing values. * `fillMissingWith` fills missing values with a specified constant * `fillMissingUsing` calls a specified function for every missing value * `fillMissing` and variants propagates values from previous/later keys Sorting and index manipulation ------------------------------ A series that is sorted by keys allows a number of additional operations (such as lookup using the `Lookp.ExactOrSmaller` lookup behavior). However, it is also possible to sort series based on the values - although the functions for manipulation with series do not guarantee that the order will be preserved. To sort series by keys, use `sortByKey`. Other sorting functions let you sort the series using a specified comparer function (`sortWith`), using a projection function (`sortBy`) and using the default comparison (`sort`). In addition, you can also replace the keys of a series with other keys using `indexWith` or with integers using `indexOrdinally`. To pick and reorder series values using to match a list of keys use `realign`. Sampling, resampling and advanced lookup ---------------------------------------- Given a (typically) time series sampling or resampling makes it possible to get time series with representative values at lower or uniform frequency. We use the following terminology: - `lookup` and `sample` functions find values at specified key; if a key is not available, they can look for value associated with the nearest smaller or the nearest greater key. - `resample` function aggregate values values into chunks based on a specified collection of keys (e.g. explicitly provided times), or based on some relation between keys (e.g. date times having the same date). - `resampleUniform` is similar to resampling, but we specify keys by providing functions that generate a uniform sequence of keys (e.g. days), the operation also fills value for days that have no corresponding observations in the input sequence. Joining, merging and zipping ---------------------------- Given two series, there are two ways to combine the values. If the keys in the series are not overlapping (or you want to throw away values from one or the other series), then you can use `merge` or `mergeUsing`. To merge more than 2 series efficiently, use the `mergeAll` function, which has been optimized for large number of series. If you want to align two series, you can use the _zipping_ operation. This aligns two series based on their keys and gives you tuples of values. The default behavior (`zip`) uses outer join and exact matching. For ordered series, you can specify other forms of key lookups (e.g. find the greatest smaller key) using `zipAlign`. functions ending with `Into` are generally easier to use as they call a specified function to turn the tuple (of possibly missing values) into a new value. For more complicated behaviors, it is often convenient to use joins on frames instead of working with series. Create two frames with single columns and then use the join operation. The result will be a frame with two columns (which is easier to use than series of tuples). </summary>
<category>Frame and series operations</category>


--------------------
type Series = static member ofNullables: values: Nullable<'a> seq -> Series<int,'a> (requires default constructor and value type and 'a :> ValueType) static member ofObservations: observations: ('a * 'b) seq -> Series<'a,'b> (requires equality) static member ofOptionalObservations: observations: ('K * 'a option) seq -> Series<'K,'a> (requires equality) static member ofValues: values: 'a seq -> Series<int,'a>

--------------------
type Series<'K,'V (requires equality)> = interface ISeriesFormattable interface IFsiFormattable interface ISeries<'K> new: index: IIndex<'K> * vector: IVector<'V> * vectorBuilder: IVectorBuilder * indexBuilder: IIndexBuilder -> Series<'K,'V> + 3 overloads member After: lowerExclusive: 'K -> Series<'K,'V> member Aggregate: aggregation: Aggregation<'K> * keySelector: Func<DataSegment<Series<'K,'V>>,'TNewKey> * valueSelector: Func<DataSegment<Series<'K,'V>>,OptionalValue<'R>> -> Series<'TNewKey,'R> (requires equality) + 1 overload member AsyncMaterialize: unit -> Async<Series<'K,'V>> member Before: upperExclusive: 'K -> Series<'K,'V> member Between: lowerInclusive: 'K * upperInclusive: 'K -> Series<'K,'V> member Compare: another: Series<'K,'V> -> Series<'K,Diff<'V>> ...
<summary> The type <c>Series&lt;K, V&gt;</c> represents a data series consisting of values `V` indexed by keys `K`. The keys of a series may or may not be ordered </summary>
<category>Core frame and series types</category>


--------------------
new: pairs: Collections.Generic.KeyValuePair<'K,'V> seq -> Series<'K,'V>
new: keys: 'K seq * values: 'V seq -> Series<'K,'V>
new: keys: 'K array * values: 'V array -> Series<'K,'V>
new: index: Indices.IIndex<'K> * vector: IVector<'V> * vectorBuilder: Vectors.IVectorBuilder * indexBuilder: Indices.IIndexBuilder -> Series<'K,'V>
static member Series.ofValues: values: 'a seq -> Series<int,'a>
val frame: columns: ('a * #ISeries<'c>) seq -> Frame<'c,'a> (requires equality and equality)
<summary> A function for constructing data frame from a sequence of name - column pairs. This provides a nicer syntactic sugar for `Frame.ofColumns`. </summary>
<example> To create a simple frame with two columns, you can write: <code> frame [ "A" =&gt; series [ 1 =&gt; 30.0; 2 =&gt; 35.0 ] "B" =&gt; series [ 1 =&gt; 30.0; 3 =&gt; 40.0 ] ] </code></example>
<category>Frame construction</category>
val expandCols: names: string seq -> frame: Frame<'R,string> -> Frame<'R,string> (requires equality)
<summary> Creates a new data frame where the specified columns are expanded based on runtime structure of the objects they store. A column can be expanded if it is <c>Series&lt;string, T&gt;</c> or <c>IDictionary&lt;K, V&gt;</c> or if it is any .NET object with readable properties. </summary>
<param name="names">Names of columns in the original data frame to be expanded</param>
<param name="frame">Input data frame whose columns will be expanded</param>
<remarks><example> Given a data frame with a series that contains tuples, you can expand the tuple members and get a frame with columns `S.Item1` and `S.Item2`: <code> let df = frame [ "S" =&gt; series [ 1 =&gt; (1, "One"); 2 =&gt; (2, "Two") ] ] df |&gt; Frame.expandCols ["S"] </code></example></remarks>
<category>Sorting and index manipulation</category>
member Frame.GetColumn<'R> : column: 'TColumnKey -> Series<'TRowKey,'R>
member Frame.GetColumn<'R> : column: 'TColumnKey * lookup: Lookup -> Series<'TRowKey,'R>
property Frame.Columns: ColumnSeries<string,string> with get
<category>Accessors and slicing</category>
val mapValues: f: ('T -> 'R) -> series: Series<'K,'T> -> Series<'K,'R> (requires equality)
<summary> Returns a new series whose values are the results of applying the given function to values of the original series. This function skips over missing values and call the function with just values. It is also aliased using the `$` operator so you can write `series $ func` for `series |&gt; Series.mapValues func`. </summary>
<category>Series transformations</category>
member Frame.ReplaceColumn: column: 'TColumnKey * data: 'V seq -> unit
member Frame.ReplaceColumn: column: 'TColumnKey * series: ISeries<'TRowKey> -> unit
member Frame.ReplaceColumn: column: 'TColumnKey * data: 'V seq * lookup: Lookup -> unit
member Frame.ReplaceColumn: column: 'TColumnKey * series: ISeries<'TRowKey> * lookup: Lookup -> unit
val newRow: Series<string,objnull>
val box: value: 'T -> objnull
val series: observations: ('a * 'b) seq -> Series<'a,'b> (requires equality)
<summary> Create a series from a sequence of key-value pairs that represent the observations of the series. This function can be used together with the `=&gt;` operator to create key-value pairs. </summary>
<example> // Creates a series with squares of numbers let sqs = series [ 1 =&gt; 1.0; 2 =&gt; 4.0; 3 =&gt; 9.0 ] </example>
member Frame.Merge: otherFrames: Frame<'TRowKey,'TColumnKey> array -> Frame<'TRowKey,'TColumnKey>
member Frame.Merge: otherFrames: Frame<'TRowKey,'TColumnKey> seq -> Frame<'TRowKey,'TColumnKey>
member Frame.Merge: otherFrame: Frame<'TRowKey,'TColumnKey> -> Frame<'TRowKey,'TColumnKey>
static member FrameExtensions.Merge: frame: Frame<'TRowKey,'TColumnKey> * rowKey: 'TRowKey * row: ISeries<'TColumnKey> -> Frame<'TRowKey,'TColumnKey> (requires equality and equality)
val ages: Series<string,float>
val tryGet: key: 'K -> series: Series<'K,'T> -> 'T option (requires equality)
<summary> Get the value for the specified key. Returns `None` when the key does not exist or the value is missing. Uses exact lookup semantics for key lookup - use `tryLookup` for more options </summary>
<category>Accessing series data and lookup</category>
val getAll: keys: 'K seq -> series: Series<'K,'T> -> Series<'K,'T> (requires equality)
<summary> Create a new series that contains values for all provided keys. Uses exact lookup semantics for key lookup - use `lookupAll` for more options </summary>
<param name="keys">A sequence of keys that will form the keys of the retunred sequence</param>
<param name="series">The input series</param>
<category>Accessing series data and lookup</category>
val observations: series: Series<'K,'T> -> ('K * 'T) seq (requires equality)
<summary> Return observations with available values. The operation skips over all keys with missing values (such as values created from `null`, `Double.NaN`, or those that are missing due to outer join etc.). </summary>
<category>Accessing series data and lookup</category>
val observationsAll: series: Series<'K,'T> -> ('K * 'T option) seq (requires equality)
<summary> Returns all keys from the sequence, together with the associated (optional) values. </summary>
<category>Accessing series data and lookup</category>
val opens: Series<DateTime,float>
val mapKeys: f: ('K -> 'R) -> series: Series<'K,'T> -> Series<'R,'T> (requires equality and equality)
<summary> Returns a new series whose keys are the results of applying the given function to keys of the original series. </summary>
<category>Series transformations</category>
val k: DateTime
DateTime.ToShortDateString() : string
val decades: Frame<(string * DateTime),string>
val groupRowsUsing: selector: ('R -> ObjectSeries<'C> -> 'K) -> frame: Frame<'R,'C> -> Frame<('K * 'R),'C> (requires equality and equality and equality)
<summary> Group rows of a data frame using the specified `selector`. The selector is called with a row key and object series representing the row and should return a new key. The result is a frame with multi-level index, where the first level is formed by the newly created keys. </summary>
<category>Grouping, windowing and chunking</category>
val sprintf: format: Printf.StringFormat<'T> -> 'T
property DateTime.Year: int with get
<summary>Gets the year component of the date represented by this instance.</summary>
<returns>The year, between 1 and 9999.</returns>
type Stats = static member corr: series1: Series<'K,'V1> -> series2: Series<'K,'V2> -> float (requires equality) static member corrFrame: frame: Frame<'R,'C> -> Frame<'C,'C> (requires equality and equality) static member count: series: Series<'K,'V> -> int (requires equality) + 1 overload static member cov: series1: Series<'K,'V1> -> series2: Series<'K,'V2> -> float (requires equality) static member covFrame: frame: Frame<'R,'C> -> Frame<'C,'C> (requires equality and equality) static member describe: series: Series<'K,'V> -> Series<string,float> (requires equality and equality) + 1 overload static member expandingCount: series: Series<'K,'V> -> Series<'K,float> (requires equality) static member expandingKurt: series: Series<'K,'V> -> Series<'K,float> (requires equality) static member expandingMax: series: Series<'K,'V> -> Series<'K,float> (requires equality) static member expandingMean: series: Series<'K,'V> -> Series<'K,float> (requires equality) ...
static member Stats.levelMean: level: ('K -> 'L) -> series: Series<'K,'V> -> Series<'L,float> (requires equality and equality)
val fst: tuple: ('T1 * 'T2) -> 'T1
val getNumericCols: frame: Frame<'R,'C> -> Series<'C,Series<'R,float>> (requires equality and equality)
<summary> Returns a series of columns of the data frame indexed by the column keys, which contains those series whose values are convertible to float, and with missing values where the conversion fails. </summary>
<category>Accessing frame data and lookup</category>
static member Frame.ofColumns: cols: Series<'C,#ISeries<'R>> -> Frame<'R,'C> (requires equality and equality)
static member Frame.ofColumns: cols: ('C * #ISeries<'R>) seq -> Frame<'R,'C> (requires equality and equality)
val byClassAndPort: Frame<(string * int * int),string>
val groupRowsByInt: column: 'C -> frame: Frame<'R,'C> -> Frame<(int * 'R),'C> (requires equality and equality)
<summary> Groups the rows of a frame by a specified column in the same way as `groupRowsBy`. This function assumes that the values of the specified column are of type `int`. &lt;category&gt;Grouping, windowing and chunking&lt;/category&gt; </summary>
val groupRowsByString: column: 'C -> frame: Frame<'R,'C> -> Frame<(string * 'R),'C> (requires equality and equality)
<summary> Groups the rows of a frame by a specified column in the same way as `groupRowsBy`. This function assumes that the values of the specified column are of type `string`. &lt;category&gt;Grouping, windowing and chunking&lt;/category&gt; </summary>
val mapRowKeys: f: ('R1 -> 'R2) -> frame: Frame<'R1,'C> -> Frame<'R2,'C> (requires equality and equality and equality)
<summary> Builds a new data frame whose row keys are the results of applying the specified function on the row keys of the original data frame. </summary>
<param name="frame">Input data frame to be transformed</param>
<param name="f">Function of one argument that defines the row key mapping</param>
<category>Frame transformations</category>
module Pair from Deedle
<summary> Module with helper functions for extracting values from hierarchical tuples </summary>
<category>Primitive types and values</category>
val flatten3: v1: 'a * ('b * 'c) -> 'a * 'b * 'c
<summary> Flatten a two-level nested tuple into a flat tuple of 3 elements </summary>
val get1And2Of3: v1: 'a * v2: 'b * 'c -> 'a * 'b
<summary> Returns the first and the second value of a three-level hierarchical tuple </summary>
type bool = Boolean
val applyLevel: level: ('K1 -> 'K2) -> op: (Series<'K1,'V> -> 'R) -> series: Series<'K1,'V> -> Series<'K2,'R> (requires equality and equality)
<summary> Groups the elements of the input series in groups based on the keys produced by `level` and then aggregates series representing each group using the specified function `op`. The result is a new series containing the aggregates of each group. This operation is designed to be used with [hierarchical indexing](../frame.html#indexing). </summary>
<param name="series">An input series to be aggregated</param>
<param name="op">A function that takes a series and produces an aggregated result</param>
<param name="level">A delegate that returns a new group key, based on the key in the input series</param>
<category>Hierarchical index operations</category>
val values: series: Series<'K,'T> -> 'T seq (requires equality)
<summary> Returns the (non-missing) values of the series as a sequence </summary>
<category>Accessing series data and lookup</category>
module Seq from Microsoft.FSharp.Collections
val countBy: projection: ('T -> 'Key) -> source: 'T seq -> ('Key * int) seq (requires equality)
val id: x: 'T -> 'T
static member Frame.ofRows: rows: ('R * #ISeries<'C>) seq -> Frame<'R,'C> (requires equality and equality)
static member Frame.ofRows: rows: Series<'R,#ISeries<'C>> -> Frame<'R,'C> (requires equality and equality)
val bySex: Frame<(string * int),string>
val nested: Series<string,Frame<int,string>>
val nest: frame: Frame<('R1 * 'R2),'C> -> Series<'R1,Frame<'R2,'C>> (requires equality and equality and equality)
<summary> Given a frame with two-level row index, returns a series indexed by the first part of the key, containing frames representing individual groups. This function can be used if you want to perform a transformation individually on each group (e.g. using `Series.mapValues` after calling `Frame.nest`). </summary>
<category>Hierarchical index operations</category>
val flat: Frame<(string * int),string>
val unnest: series: Series<'R1,Frame<'R2,'C>> -> Frame<('R1 * 'R2),'C> (requires equality and equality and equality)
<summary> Given a series of frames, returns a new data frame with two-level hierarchical row index, using the series keys as the first component. This function is the dual of `Frame.nest`. &lt;category&gt;Hierarchical index operations&lt;/category&gt; </summary>
val travels: Series<string,string list>
val fillMissingWith: value: 'T -> frame: Frame<'R,'C> -> Frame<'R,'C> (requires equality and equality)
<summary> Fill missing values of a given type in the frame with a constant value. The fill value is applied to columns whose element type matches the fill value type (using safe numeric widening). This includes both cases where the column type can be widened to the fill value type (e.g. decimal columns filled with a float value) and cases where the fill value can be widened to the column type (e.g. an integer fill value filling float columns). Columns whose element type is incompatible with the fill value type are left unchanged. </summary>
<param name="frame">An input data frame that is to be filled</param>
<param name="value">A constant value that is used to fill all missing values</param>
<category>Missing values</category>
val aggregateRowsBy: groupBy: 'C seq -> aggBy: 'C seq -> aggFunc: (Series<'R,'V1> -> 'V2) -> frame: Frame<'R,'C> -> Frame<int,'C> (requires equality and equality)
<summary> Returns a data frame whose rows are grouped by `groupBy` and whose columns specified in `aggBy` are aggregated according to `aggFunc`. </summary>
<param name="groupBy">sequence of columns to group by</param>
<param name="aggBy">sequence of columns to apply aggFunc to</param>
<param name="aggFunc">invoked in order to aggregate values</param>
<param name="frame">The input data frame to be aggregated</param>
<category>Grouping, windowing and chunking</category>
static member Stats.mean: frame: Frame<'R,'C> -> Series<'C,float> (requires equality and equality)
static member Stats.mean: series: Series<'K,'V> -> float (requires equality)
val pivotTable: rowGrp: ('R -> ObjectSeries<'C> -> 'RNew) -> colGrp: ('R -> ObjectSeries<'C> -> 'CNew) -> op: (Frame<'R,'C> -> 'T) -> frame: Frame<'R,'C> -> Frame<'RNew,'CNew> (requires equality and equality and equality and equality)
<summary> Creates a new data frame resulting from a 'pivot' operation. Consider a denormalized data frame representing a table: column labels are field names &amp; table values are observations of those fields. pivotTable buckets the rows along two axes, according to the results of the functions `rowGrp` and `colGrp`; and then computes a value for the frame of rows that land in each bucket. </summary>
<param name="rowGrp">A function from rowkey &amp; row to group value for the resulting row index</param>
<param name="colGrp">A function from rowkey &amp; row to group value for the resulting col index</param>
<param name="op">A function computing a value from the corresponding bucket frame</param>
<param name="frame">The input data frame to pivot</param>
<category>Grouping, windowing and chunking</category>
val k: int
val r: ObjectSeries<string>
member ObjectSeries.GetAs<'R> : column: 'K -> 'R
member ObjectSeries.GetAs: column: 'K * fallback: 'R -> 'R
val countRows: frame: Frame<'R,'C> -> int (requires equality and equality)
<summary> Returns the total number of row keys in the specified frame. This returns the total length of the row series, including keys for which there is no value available. </summary>
<category>Accessing frame data and lookup</category>
val frame: Frame<int,string>
val round: value: 'T -> 'T (requires member Round)
type Double = member CompareTo: value: float -> int + 1 overload member Equals: obj: float -> bool + 1 overload member GetHashCode: unit -> int member GetTypeCode: unit -> TypeCode member ToString: unit -> string + 3 overloads member TryFormat: utf8Destination: Span<byte> * bytesWritten: byref<int> * ?format: ReadOnlySpan<char> * ?provider: IFormatProvider -> bool + 1 overload static member (<) : left: float * right: float -> bool static member (<=) : left: float * right: float -> bool static member (<>) : left: float * right: float -> bool static member (=) : left: float * right: float -> bool ...
<summary>Represents a double-precision floating-point number.</summary>
field Double.NaN: float = NaN
Multiple items
type Nullable = static member Compare<'T (requires default constructor and value type and 'T :> ValueType)> : n1: Nullable<'T> * n2: Nullable<'T> -> int static member Equals<'T (requires default constructor and value type and 'T :> ValueType)> : n1: Nullable<'T> * n2: Nullable<'T> -> bool static member GetUnderlyingType: nullableType: Type -> Type static member GetValueRefOrDefaultRef<'T (requires default constructor and value type and 'T :> ValueType)> : nullable: inref<Nullable<'T>> -> inref<'T>
<summary>Supports a value type that can be assigned <see langword="null" />. This class cannot be inherited.</summary>

--------------------
type Nullable<'T (requires default constructor and value type and 'T :> ValueType)> = new: value: 'T -> unit member Equals: other: obj -> bool member GetHashCode: unit -> int member GetValueOrDefault: unit -> 'T + 1 overload member ToString: unit -> string static member op_Explicit: value: Nullable<'T> -> 'T static member op_Implicit: value: 'T -> Nullable<'T> member HasValue: bool member Value: 'T
<summary>Represents a value type that can be assigned <see langword="null" />.</summary>
<typeparam name="T">The underlying value type of the <see cref="T:System.Nullable`1" /> generic type.</typeparam>


--------------------
Nullable ()
Nullable(value: 'T) : Nullable<'T>
val ozone: Series<int,float>
val fillMissingUsing: f: ('K -> 'T) -> series: Series<'K,'T> -> Series<'K,'T> (requires equality)
<summary> Fill missing values in the series using the specified function. The specified function is called with all keys for which the series does not contain value and the result of the call is used in place of the missing value. </summary>
<param name="series">An input series that is to be filled</param>
<param name="f">A function that takes key `K` and generates a value to be used in a place where the original series contains a missing value.</param>
<remarks> This function can be used to implement more complex interpolation. For example see [handling missing values in the tutorial](../frame.html#missing) </remarks>
<category>Missing values</category>
val prev: OptionalValue<float>
member Series.TryGet: key: 'K -> OptionalValue<'V>
member Series.TryGet: key: 'K * lookup: Lookup -> OptionalValue<'V>
type Lookup = | Exact = 1 | ExactOrGreater = 3 | ExactOrSmaller = 5 | Greater = 2 | Smaller = 4
<summary> Represents different behaviors of key lookup in series. For unordered series, the only available option is `Lookup.Exact` which finds the exact key - methods fail or return missing value if the key is not available in the index. For ordered series `Lookup.Greater` finds the first greater key (e.g. later date) with a value. `Lookup.Smaller` searches for the first smaller key. The options `Lookup.ExactOrGreater` and `Lookup.ExactOrSmaller` finds the exact key (if it is present) and otherwise search for the nearest larger or smaller key, respectively. </summary>
<category>Parameters and results of various operations</category>
Lookup.ExactOrSmaller: Lookup = 5
<summary> Lookup a value associated with the specified key or with the nearest smaller key that has a value available. Fails (or returns missing value) only when the specified key is smaller than all available keys. </summary>
val next: OptionalValue<float>
Lookup.ExactOrGreater: Lookup = 3
<summary> Lookup a value associated with the specified key or with the nearest greater key that has a value available. Fails (or returns missing value) only when the specified key is greater than all available keys. </summary>
Multiple items
module OptionalValue from Deedle
<summary> Provides various helper functions for using the <c>OptionalValue&lt;T&gt;</c> type from F# (The functions are similar to those in the standard <c>Option</c> module). </summary>
<category>Primitive types and values</category>


--------------------
type OptionalValue = class end
<summary> Non-generic type that makes it easier to create <c>OptionalValue&lt;T&gt;</c> values from C# by benefiting the type inference for generic method invocations. </summary>
<category>Primitive types and values</category>


--------------------
type OptionalValue<'T> = new: value: 'T -> OptionalValue<'T> override Equals: y: obj -> bool override GetHashCode: unit -> int override ToString: unit -> string member HasValue: bool member Value: 'T member ValueOrDefault: 'T static member Missing: OptionalValue<'T>
<summary> Value type that represents a potentially missing value. This is similar to <c>System.Nullable&lt;T&gt;</c>, but does not restrict the contained value to be a value type, so it can be used for storing values of any types. When obtained from <c>DataFrame&lt;R, C&gt;</c> or <c>Series&lt;K, T&gt;</c>, the <c>Value</c> will never be <c>Double.NaN</c> or <c>null</c> (but this is not, in general, checked when constructing the value). The type is only used in C#-friendly API. F# operations generally use expose standard F# <c>option&lt;T&gt;</c> type instead. However, there the <c>OptionalValue</c> module contains helper functions for using this type from F# as well as <c>Missing</c> and <c>Present</c> active patterns. </summary>
<category>Primitive types and values</category>


--------------------
OptionalValue ()
new: value: 'T -> OptionalValue<'T>
active recognizer Present: 'T opt -> Choice<unit,'T>
<summary> Complete active pattern that can be used to pattern match on `OptionalValue&lt;T&gt;`. For example: let optVal = OptionalValue(42) match optVal with | OptionalValue.Missing -&gt; printfn "Empty" | OptionalValue.Present(v) -&gt; printfn "Contains %d" v </summary>
val p: float
val n: float
val v: float

Type something to start searching.