{"size": 175140, "ext": "scrbl", "max_stars_repo_path": "racketframes/documentation/dataframe.scrbl", "max_stars_repo_name": "bommysk/RacketFrames", "max_stars_repo_stars_event_min_datetime": "2018-06-21T19:07:04.000Z", "max_stars_repo_stars_event_max_datetime": "2018-09-06T08:58:56.000Z", "max_issues_repo_path": "racketframes/documentation/dataframe.scrbl", "max_issues_repo_name": "bommysk/RacketFrames", "max_issues_repo_issues_event_min_datetime": "2018-07-02T04:44:29.000Z", "max_issues_repo_issues_event_max_datetime": "2019-12-12T15:30:55.000Z", "max_forks_repo_path": "racketframes/documentation/dataframe.scrbl", "max_forks_repo_name": "bommysk/RacketFrames", "max_forks_repo_forks_event_min_datetime": "2018-06-21T19:06:45.000Z", "max_forks_repo_forks_event_max_datetime": "2018-06-21T19:06:45.000Z"}
{"max_stars_count": 8, "max_issues_count": 2, "max_forks_count": 1, "avg_line_length": 30.4697286013, "max_line_length": 336, "alphanum_fraction": 0.6549274866}
#lang scribble/manual
@(require scribble/core)
@(require racket/runtime-path)

@require[(for-label racket/contract)]

@title[#:tag "top" #:version "1.0" #:style 'toc-hidden]{RacketFrames}

@author["Shubham Kahal"]

@verbatim{================================================================================}

@"\U2192" A DataFrame implementation in the spirit of Python Pandas and R DataFrames.

A DataFrame is a two-dimensional tabular data structure used to hold data in tables with
labeled rows and columns. It offers fast read access and manipulation of relatively large data sets
limited by available RAM. The package also provides functions for loading and saving data from DataFrames
as well as several utilities for statistical calculations, plotting, join operations, data compression
and missing value handling.

In these data centric times, analytical libraries have been developed in a variety
domains to work with large and complex data. Languages like Python and R or even the command line can be
used to accomplish analysis tasks, but RacketFrames is especially good if you are 1)
using Racket already 2) may need to integrate your solution with other Racket applications
in the future or 3) enjoy functional programming.

@verbatim{================================================================================}

@larger{@bold{Getting Started}}

A DataFrame is a two-dimensional tabular data structure that aligns data in rows and columns. The RacketFrames
implementation consists of three principal components: Indexes, Series, and DataFrames. The Series data structure
is a one-dimensional labelled array serving as a column in the DataFrame. The columns and rows are efficiently
accessed using the Indexes generated fron the given data. 

@(define-runtime-path small-dataframe-png "small_dataframe.png")
@image[small-dataframe-png]

@verbatim{================================================================================}

The @bold{Index} is an additional derived structure constructed using the primary data and a sequence of hashable keys which label
each element and provide constant time read/write access. The index is generated by reading the given data array and hashable keys
in parallel and constructing a hashtable, mapping key -> (Listof Index) modeling the 1:1 mapping from the Index key to the 0..n indexes of
the data vector. RacketFrames allows the user to provide their own Index or have the library generate a simple numeric index
0..n-1 (where n is the length of the given data vector) automatically. This efficient mapping results in fast constant time index operations,
repeat indexed value flexibility and minimizes data repetition. Indexes don't affect the contents of the DataFrame, only the performance of
the operations. Although Indexes have a generation cost, they are needed for fast operations and data organization. Series have one Index and
DataFrames index both columns and rows. All Series of a DataFrame must have an identical Index with missing Index values replaced with null
resulting in a uniform C X R table.

@"\U2192" RacketFrames supports five index types implemented with the same structure but differing data-types.

Label Index - SIndex. (Label Index) is a suitable choice for most cases, even when the index data type is not known.

Integer Index - IIndex.

Float Index - FIndex.

Datetime Index - DTIndex for time series indexing using RacketFrame datetime operations.

Date Index - DIndex for time series indexing using the native typed Racket Date package.

A HashTable was used for fast read and write and to minimize repeated data.
Indexes can contain non-unique keys which are hashed to a list of non-negative integers
that refer to the index in the series data vector to which the index belongs.
Unlike the primary key of a SQL table, a DataFrame's index does not have to be unique.

A hashtable with specific type mapped to a list of non-negative integers.
@codeblock|{
(define-type SIndex (HashTable Label (Listof Index)))
(define-type IIndex (HashTable Fixnum (Listof Index)))
(define-type FIndex (HashTable Flonum (Listof Index)))
(define-type DTIndex (HashTable Datetime (Listof Index)))
(define-type DIndex (HashTable Date (Listof Index)))
}|

The mapping to list of indexes allows for duplicate index values.
Wrapped in struct.
@codeblock|{
(struct LabelIndex ([index : SIndex]) #:mutable)
(struct FixnumIndex ([index : IIndex]) #:mutable)
(struct FlonumIndex ([index : FIndex]) #:mutable)
(struct DatetimeIndex ([index : DTIndex]) #:mutable)
(struct DateIndex ([index : DIndex]) #:mutable)

(define-type RFIndex (U LabelIndex FixnumIndex FlonumIndex DatetimeIndex DateIndex))

(define-predicate RFIndex? RFIndex)

; Null value place holder.
(struct RFNoData () #:transparent)
}|

The four index types supported by RacketFrames is referenced by the RFIndex type.

You can construct an Index with the build-index-from-seq. If we take a look at the
generated hash we can see how this index would provide an ideal mapping to a data vector
of the same length.
@codeblock|{ (LabelIndex-index (assert (build-index-from-seq (list 'a 'a 'b 'a 'a 'a 'c 'b)) LabelIndex?)) }|
> '#hash((a . (0 1 3 4 5)) (b . (2 7)) (c . (6)))

@verbatim{================================================================================}

@"\U2192" A @bold{Series} is a struct consisting of a data vector of type identical to Series type and an Index for fast data access.
To save the user trouble with type checking and library details, convenience methods are provided to initialize and
interact with Series. With a labeled sequence of Series akin to columns of a table, we can construct a DataFrame.

RacketFrames supports six Series types.

GenSeries - Generic Series consisting of Any type of data.

NSeries - Floating Point Series consisting of Flonum data stored in the FlVector.

ISeries - Integer Series consisting of Integers.

CSeries - Categorical Series consisting of Symbols.

BSeries - Boolean Series consisting of #t or #f.

DatetimeSeries - Datetime Series consisting of the custom RacketFrames Datetime struct.

DateSeries - Datetime Series consisting of the native Racket date struct.

@verbatim{================================================================================}

@bold{DataFrames} are a table like structure which consist of one or more labeled series of equal length.
The representation of a labeled Series is a Column
@codeblock|{ (define-type Column (Pair Label Series)) }|
and constructing a list of Column gives us the main building blocks of a DataFrame.
@codeblock|{ (define-type Columns (Listof Column)) }|
It also has named attributes labeling the rows via the Series indexes providing efficient 2-D read operations
through use of indexes and the capability to scale to millions of rows. Additionally, it allows aggregation
and other functions on rows and columns and the ability to clean and filter data to derive insights. A DataFrame
can be constructed with Racket objects or can be initialized by loading data from delimited files and SQLLite Databases.

Given a list of Columns we can construct the DataFrame struct. Where the LabelIndex indexes into the series vector
for fast Column access.
@codeblock|{ (struct: DataFrame LabelIndex ([series : (Vectorof Series)])) }|

@verbatim{================================================================================}

Import library.
@codeblock|{
(require RacketFrames)
}|
@bold{Initialize DataFrame.}

We can explicity define the Columns structure to initialize from
or we can use the friendlier hashtable representation mapping the
column name to a data sequence:

@codeblock|{(Sequenceof Label (Sequenceof Any))}|

@codeblock|{
(define data-frame-from-hash (new-data-frame (hash 'a (list 1 2 3) 'b (list 3 5 6)  'c (list 3.4 5.5 6.7) 'd (list 'fizz 'buzz 'baz))))

(show-data-frame-description (data-frame-description data-frame-from-hash))

(define data-frame-from-hash-vector (new-data-frame (hash 'a '#(1 2 3) 'b '#(3 5 6) 'c '#(3.4 5.5 6.7))))

(show-data-frame-description (data-frame-description data-frame-from-hash-vector))
}|

@verbatim|{
DataFrame::(Cols: 4, Rows: 3)
  - d: CategoricalSeries
  - a: IntegerSeries
  - b: IntegerSeries
  - c: NumericSeries
DataFrame::(Cols: 3, Rows: 3)
  - a: IntegerSeries
  - b: IntegerSeries
  - c: NumericSeries
}|

Define columns.
@codeblock|{
(define columns-mix
  (list
     (cons 'integer-col (new-ISeries (fxvector 1 2 3 4)
         #:index (build-index-from-list (list 'a 'b 'c 'd))))
     (cons 'categorical-col (new-CSeries (vector 'hello 'world 'fizz 'buzz)
         #:index (build-index-from-list (list 'a 'b 'c 'd))))))
}|
Initialize DataFrame.
@codeblock|{
; create new data-frame-mix from columns
(define data-frame-mix (new-data-frame columns-mix))

; write data-frame-mix to stdout
(data-data-frame-write-delim data-frame-mix)
}|

@tabular[#:sep @hspace[1] #:row-properties '(bottom-border)
(list (list @bold{integer-col} @bold{categorical-col})
(list "1" "hello")
(list "2" "world")
(list "3" "fizz")
(list "4" "buzz"))]

More pleasant syntax for defining columns.
@codeblock|{
; series constructors
(define int-series (new-series (list 1 2 3 4 5 6)))
(define gen-series (new-series (vector 'a 1 2 'c 'd 5.6)))

(series-iref int-series 3)
(series-print int-series)

(series-iref gen-series 5)
(series-print gen-series)

(define int-series-with-index (new-series (list 1 2 3 4 5 6) #:index (list 'a 'b 'c 'd 'e 'f)))
(define gen-series-with-index (new-series (vector 'a 1 2 'c 'd 5.6) #:index (list 6 5 4 3 2 1)))

(series-index-ref int-series-with-index 'e)
(series-print int-series-with-index)

(series-index-ref gen-series-with-index 5)
(series-print gen-series-with-index)

(define columns-from-series
  (list
   (cons 'integer-col int-series)
   (cons 'gen-col gen-series)
   (cons 'integer-series-with-index-col int-series-with-index)
   (cons 'gen-series-with-index-col gen-series-with-index))
 )
}|

Initialize DataFrame.
@codeblock|{
; create new data-frame-mix from columns
(define data-frame-columns-from-series (new-data-frame columns-from-series))

; write data-frame-mix to stdout
(data-frame-write-delim data-frame-columns-from-series)
}|

@tabular[#:sep @hspace[1] #:row-properties '(bottom-border)
(list (list @bold{integer-col} @bold{gen-col} @bold{integer-series-with-index-col} @bold{gen-series-with-index-col})
(list "1" "a" "1" "a")
(list "2" "1" "2" "1")
(list "3" "2" "3" "2")
(list "4" "c" "4" "c")
(list "5" "d" "5" "d")
(list "6" "5.6" "6" "5.6"))]

Initialize DataFrame from CSV file.

@(define-runtime-path salary-date-csv-png "salary_date_csv.png")
@image[salary-date-csv-png]

@codeblock|{
; no schema
(define salary-data-frame-csv-no-schema (load-csv-file "../sample-csv/salary_date.csv" #:schema #f))

(data-frame-head salary-data-frame-csv-no-schema)
}|

@tabular[#:sep @hspace[1] #:row-properties '(bottom-border)
(list (list @bold{first} @bold{last} @bold{age} @bold{dollar} @bold{phone} @bold{join_date})
(list "Evan" "Lloyd"  "19" "$3839.78"  "(771) 255-1133"  "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))") 
(list "Etta" "Griffith" "50" "$8158.60" "(523) 731-6388" "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))") 
(list "William" "Conner" "50" "$9966.70" "(759) 504-6619"  "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))") 
(list "Rhoda" "Guerrero" "20" "$6480.10" "(467) 431-4273"  "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))") 
(list "Kyle" "Klein" "59" "$6106.13"  "(760) 829-2093"  "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))") 
(list "Benjamin" "Patton" "59" "$3925.51" "(488) 673-5745" "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))") 
(list "Georgie" "Hansen" "51" "$8809.92" "(579) 706-4402" "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))") 
(list "Gregory" "Bowen" "36" "$5176.21" "(533) 506-3845"  "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))") 
(list "Cornelia" "Peterson" "46" "$3626.31" "(861) 316-5672"  "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))") 
(list "Samuel" "Cole" "37" "$7677.20" "(760) 406-6331" "(Datetime (Date 2018 5 19) (Time 0 0 0 0 0))"))]

@bold|{DataFrame Column Names}|
@codeblock|{
(data-frame-names salary-data-frame-csv-no-schema)
}|

@verbatim|{
'(first last age dollar phone join_date)
}|

@bold|{DataFrame Dimensions}| - Rows X Columns
@codeblock|{
(data-frame-dim salary-data-frame-csv-no-schema)
}|

@verbatim|{
(Dim 200 6)}|

@bold|{DataFrame Description}| - dimensions and Series types.
@codeblock|{
(show-data-frame-description (data-frame-description salary-data-frame-csv-no-schema))
}|

@verbatim|{
DataFrame::(Cols: 6, Rows: 200)
  - first: CategoricalSeries
  - last: CategoricalSeries
  - age: IntegerSeries
  - dollar: CategoricalSeries
  - phone: CategoricalSeries
  - join_date: DatetimeSeries}|

@bold|{DataFrame Remove Columns}|
@codeblock|{
(data-frame-head (data-frame-remove salary-data-frame-csv-no-schema (list 'first 'age)))
}|

@verbatim|{
     last           dollar           phone         join_date    
Lloyd           $3839.78        (771) 255-1133  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Griffith        $8158.60        (523) 731-6388  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Conner          $9966.70        (759) 504-6619  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Guerrero        $6480.10        (467) 431-4273  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Klein           $6106.13        (760) 829-2093  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Patton          $3925.51        (488) 673-5745  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Hansen          $8809.92        (579) 706-4402  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Bowen           $5176.21        (533) 506-3845  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Peterson        $3626.31        (861) 316-5672  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Cole            $7677.20        (760) 406-6331  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0))
}|

@bold|{DataFrame Project}| - Output a DataFrame with only the specified columns.
@codeblock|{
(data-frame-head (data-frame-project salary-data-frame-csv-no-schema (list 'first 'last 'dollar)))
}|

@verbatim|{
first           last           dollar      
Evan            Lloyd           $3839.78        
Etta            Griffith        $8158.60        
William         Conner          $9966.70        
Rhoda           Guerrero        $6480.10        
Kyle            Klein           $6106.13        
Benjamin        Patton          $3925.51        
Georgie         Hansen          $8809.92        
Gregory         Bowen           $5176.21        
Cornelia        Peterson        $3626.31        
Samuel          Cole            $7677.20
}|

@bold|{DataFrame Replace}| - Provide a Column to replace the Column with the identical label. In the example below, replace
the salary column with a new CSeries.
@codeblock|{
(data-frame-head (data-frame-replace salary-data-frame-csv-no-schema (cons 'salary (new-CSeries (make-vector 200 '$0.00)))))
}|

@verbatim|{
     first           last             age           dollar           phone         join_date    
Evan            Lloyd                        19 $3839.78        (771) 255-1133  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Etta            Griffith                     50 $8158.60        (523) 731-6388  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
William         Conner                       50 $9966.70        (759) 504-6619  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Rhoda           Guerrero                     20 $6480.10        (467) 431-4273  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Kyle            Klein                        59 $6106.13        (760) 829-2093  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Benjamin        Patton                       59 $3925.51        (488) 673-5745  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Georgie         Hansen                       51 $8809.92        (579) 706-4402  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Gregory         Bowen                        36 $5176.21        (533) 506-3845  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Cornelia        Peterson                     46 $3626.31        (861) 316-5672  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Samuel          Cole                         37 $7677.20        (760) 406-6331  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0))
}|

Replace non-existent Column. No-operation.
@codeblock|{
(data-frame-head (data-frame-replace salary-data-frame-csv-no-schema (cons 'dollar (new-CSeries (make-vector 200 '$0.00)))))
}|

@verbatim|{
     first           last             age           dollar           phone         join_date    
Evan            Lloyd                        19 $0.00           (771) 255-1133  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Etta            Griffith                     50 $0.00           (523) 731-6388  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
William         Conner                       50 $0.00           (759) 504-6619  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Rhoda           Guerrero                     20 $0.00           (467) 431-4273  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Kyle            Klein                        59 $0.00           (760) 829-2093  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Benjamin        Patton                       59 $0.00           (488) 673-5745  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Georgie         Hansen                       51 $0.00           (579) 706-4402  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Gregory         Bowen                        36 $0.00           (533) 506-3845  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Cornelia        Peterson                     46 $0.00           (861) 316-5672  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) 
Samuel          Cole                         37 $0.00           (760) 406-6331  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0))
}|

@bold|{DataFrame Extend}| - Extend the DataFrame by adding columns.
@codeblock|{
(data-frame-head (data-frame-extend salary-data-frame-csv-no-schema (cons 'state (new-CSeries (make-vector 200 'CA)))))
}|

@verbatim|{
     first           last             age           dollar           phone         join_date         state      
Evan            Lloyd                        19 $3839.78        (771) 255-1133  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA              
Etta            Griffith                     50 $8158.60        (523) 731-6388  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA              
William         Conner                       50 $9966.70        (759) 504-6619  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA              
Rhoda           Guerrero                     20 $6480.10        (467) 431-4273  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA              
Kyle            Klein                        59 $6106.13        (760) 829-2093  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA              
Benjamin        Patton                       59 $3925.51        (488) 673-5745  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA              
Georgie         Hansen                       51 $8809.92        (579) 706-4402  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA              
Gregory         Bowen                        36 $5176.21        (533) 506-3845  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA              
Cornelia        Peterson                     46 $3626.31        (861) 316-5672  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA              
Samuel          Cole                         37 $7677.20        (760) 406-6331  (Datetime (Date 2018 5 19) (Time 0 0 0 0 0)) CA
}|

@verbatim{================================================================================}

@bold{Table of Contents}

@table-of-contents[]

@; ======================================================================
@section[#:tag "Series"]{Series}

@itemlist[

 @item{One-dimensional ndarray with axis labels including time series.

Labels need not be unique but must be a hashable type. The object supports both integer- and label-based indexing and provides a host of methods for performing operations involving the index. Statistical methods from ndarray have been overridden to automatically exclude missing data (currently represented as NaN).

Operations between Series (+, -, /, , *) align values based on their associated index values– they need not be the same length. The result index will be the sorted union of the two indexes.
}

]

@subsection[#:style 'toc]{Integer Series}

@"\U2190" Integer Series is abbreviated to ISeries in RacketFrames.

@codeblock|{
(provide
 (struct-out ISeries)
 ISeries-index RFFixnum RFFixnum? (rename-out [GroupHash iseries-grouphash] [DEFAULT_NULL_VALUE ISERIES_DEFAULT_NULL_VALUE]))

(define-type RFFixnum (U Fixnum RFNoData))
(define-predicate RFFixnum? RFFixnum)
(define DEFAULT_NULL_VALUE : Fixnum 0)
;; Integer series optimized with use of Fixnum.
(struct ISeries ([index : (Option RFIndex)]
                 [data : (Vectorof RFFixnum)]
                 ; when the null-value is not a fixnum?, the fixnum-null-value is set to 0
                 [null-value : RFNULL]
                 ; needed for type checking purposes and to do proper arithmetic operations in numeric series
                 [fixnum-null-value : Fixnum]
                 ; encode data by element count to optimze memory storage and read/write operations
                 ; when data vector lacks variety
                 [encoded : Boolean]
                 [data-count-encoded : (Option (Listof (Pairof Any Real)))])
  #:mutable
  #:transparent)
}|

@local-table-of-contents[]

@subsubsection[#:tag "new-ISeries"]{new-ISeries}
@defproc[(new-ISeries (arg0 (U FxVector (Vectorof Fixnum) (Sequenceof Fixnum) (Sequenceof RFFixnum))) (arg1 (#:index (Option (U (Sequenceof IndexDataType) RFIndex)))) (arg2 (#:fill-null RFNULL)) (arg3 (#:sort Boolean)) (arg4 (#:encode Boolean))) ISeries]{
...
}

@subsubsection[#:tag "set-ISeries-index"]{set-ISeries-index}
@defproc[(set-ISeries-index (arg0 ISeries) (arg1 (U (Sequenceof IndexDataType) RFIndex))) ISeries]{
...
}

@subsubsection[#:tag "set-ISeries-null-value"]{set-ISeries-null-value}
@defproc[(set-ISeries-null-value (arg0 ISeries) (arg1 RFNULL)) ISeries]{
...
}

@subsubsection[#:tag "set-ISeries-fixnum-null-value-inplace"]{set-ISeries-fixnum-null-value-inplace}
@defproc[(set-ISeries-fixnum-null-value-inplace (arg0 ISeries) (arg1 Fixnum)) Void]{
...
}

@subsubsection[#:tag "iseries-iref"]{iseries-iref}
@defproc[(iseries-iref (arg0 ISeries) (arg1 (Listof Index))) (Listof RFFixnum)]{
...
}

@subsubsection[#:tag "iseries-loc-boolean"]{iseries-loc-boolean}
@defproc[(iseries-loc-boolean (arg0 ISeries) (arg1 (Listof Boolean))) (U RFFixnum ISeries)]{
...
}

@subsubsection[#:tag "iseries-loc"]{iseries-loc}
@defproc[(iseries-loc (arg0 ISeries) (arg1 (U Label (Listof Label) (Listof Boolean)))) (U RFFixnum ISeries)]{
...
}

@subsubsection[#:tag "iseries-loc-multi-index"]{iseries-loc-multi-index}
@defproc[(iseries-loc-multi-index (arg0 ISeries) (arg1 (U (Listof String) ListofListofString))) (U RFFixnum ISeries)]{
...
}

@subsubsection[#:tag "iseries-iloc"]{iseries-iloc}
@defproc[(iseries-iloc (arg0 ISeries) (arg1 (U Index (Listof Index)))) (U RFFixnum ISeries)]{
...
}

@subsubsection[#:tag "iseries-iloc-range"]{iseries-iloc-range}
@defproc[(iseries-iloc-range (arg0 ISeries) (arg1 Index) (arg2 Index)) ISeries]{
...
}

@subsubsection[#:tag "iseries-index-ref"]{iseries-index-ref}
@defproc[(iseries-index-ref (arg0 ISeries) (arg1 IndexDataType)) (Listof RFFixnum)]{
...
}

@subsubsection[#:tag "iseries-range"]{iseries-range}
@defproc[(iseries-range (arg0 ISeries) (arg1 Index) (arg2 Index)) (Vectorof RFFixnum)]{
...
}

@subsubsection[#:tag "iseries-length"]{iseries-length}
@defproc[(iseries-length (arg0 ISeries)) Index]{
...
}

@subsubsection[#:tag "iseries-referencer"]{iseries-referencer}
@defproc[(iseries-referencer (arg0 ISeries)) (Index -> RFFixnum)]{
...
}

@subsubsection[#:tag "iseries-data"]{iseries-data}
@defproc[(iseries-data (arg0 ISeries)) (Vectorof RFFixnum)]{
...
}

@subsubsection[#:tag "in-iseries"]{in-iseries}
@defproc[(in-iseries (arg0 RFFixnum) (arg1 ISeries)) Boolean]{
...
}

@subsubsection[#:tag "iseries-index"]{iseries-index}
@defproc[(iseries-index (arg0 ISeries)) (U False RFIndex)]{
...
}

@subsubsection[#:tag "iseries-null-value"]{iseries-null-value}
@defproc[(iseries-null-value (arg0 ISeries)) Fixnum]{
...
}

@subsubsection[#:tag "iseries-custom-null-value"]{iseries-custom-null-value}
@defproc[(iseries-custom-null-value (arg0 ISeries)) RFNULL]{
...
}

@subsubsection[#:tag "iseries-value-is-null?"]{iseries-value-is-null?}
@defproc[(iseries-value-is-null? (arg0 ISeries) (arg1 Fixnum)) Boolean]{
...
}

@subsubsection[#:tag "iseries-groupby"]{iseries-groupby}
@defproc[(iseries-groupby (arg0 ISeries) (arg1 (#:by-value Boolean))) GroupHash]{
...
}

@subsubsection[#:tag "apply-agg-iseries"]{apply-agg-iseries}
@defproc[(apply-agg-iseries (arg0 Symbol) (arg1 GroupHash)) GenSeries]{
...
}

@subsubsection[#:tag "map/is"]{map/is}
@defproc[(map/is (arg0 ISeries) (arg1 (Fixnum -> Fixnum))) ISeries]{
...
}

@subsubsection[#:tag "bop/is"]{bop/is}
@defproc[(bop/is (arg0 ISeries) (arg1 ISeries) (arg2 (Fixnum Fixnum -> Fixnum))) ISeries]{
...
}

@subsubsection[#:tag "comp/is"]{comp/is}
@defproc[(comp/is (arg0 ISeries) (arg1 ISeries) (arg2 (Fixnum Fixnum -> Boolean))) BSeries]{
...
}

@subsubsection[#:tag "+/is"]{+/is}
@defproc[(+/is (arg0 ISeries) (arg1 ISeries)) ISeries]{
...
}

@subsubsection[#:tag "-/is"]{-/is}
@defproc[(-/is (arg0 ISeries) (arg1 ISeries)) ISeries]{
...
}

@subsubsection[#:tag "*/is"]{*/is}
@defproc[(*/is (arg0 ISeries) (arg1 ISeries)) ISeries]{
...
}

@subsubsection[#:tag "//is"]{//is}
@defproc[(//is (arg0 ISeries) (arg1 ISeries)) ISeries]{
...
}

@subsubsection[#:tag "%/is"]{%/is}
@defproc[(%/is (arg0 ISeries) (arg1 ISeries)) ISeries]{
...
}

@subsubsection[#:tag "r/is"]{r/is}
@defproc[(r/is (arg0 ISeries) (arg1 ISeries)) ISeries]{
...
}

@subsubsection[#:tag "+./is"]{+./is}
@defproc[(+./is (arg0 ISeries) (arg1 Fixnum)) ISeries]{
...
}

@subsubsection[#:tag "-./is"]{-./is}
@defproc[(-./is (arg0 ISeries) (arg1 Fixnum)) ISeries]{
...
}

@subsubsection[#:tag "*./is"]{*./is}
@defproc[(*./is (arg0 ISeries) (arg1 Fixnum)) ISeries]{
...
}

@subsubsection[#:tag "/./is"]{/./is}
@defproc[(/./is (arg0 ISeries) (arg1 Fixnum)) ISeries]{
...
}

@subsubsection[#:tag "%./is"]{%./is}
@defproc[(%./is (arg0 ISeries) (arg1 Fixnum)) ISeries]{
...
}

@subsubsection[#:tag "r./is"]{r./is}
@defproc[(r./is (arg0 ISeries) (arg1 Fixnum)) ISeries]{
...
}

@subsubsection[#:tag ">/is"]{>/is}
@defproc[(>/is (arg0 ISeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag "</is"]{</is}
@defproc[(</is (arg0 ISeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag ">=/is"]{>=/is}
@defproc[(>=/is (arg0 ISeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag "<=/is"]{<=/is}
@defproc[(<=/is (arg0 ISeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag "=/is"]{=/is}
@defproc[(=/is (arg0 ISeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag "!=/is"]{!=/is}
@defproc[(!=/is (arg0 ISeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag ">./is"]{>./is}
@defproc[(>./is (arg0 ISeries) (arg1 Fixnum)) BSeries]{
...
}

@subsubsection[#:tag "<./is"]{<./is}
@defproc[(<./is (arg0 ISeries) (arg1 Fixnum)) BSeries]{
...
}

@subsubsection[#:tag ">=./is"]{>=./is}
@defproc[(>=./is (arg0 ISeries) (arg1 Fixnum)) BSeries]{
...
}

@subsubsection[#:tag "<=./is"]{<=./is}
@defproc[(<=./is (arg0 ISeries) (arg1 Fixnum)) BSeries]{
...
}

@subsubsection[#:tag "=./is"]{=./is}
@defproc[(=./is (arg0 ISeries) (arg1 Fixnum)) BSeries]{
...
}

@subsubsection[#:tag "!=./is"]{!=./is}
@defproc[(!=./is (arg0 ISeries) (arg1 Fixnum)) BSeries]{
...
}

@subsubsection[#:tag "apply-agg-is"]{apply-agg-is}
@defproc[(apply-agg-is (arg0 Symbol) (arg1 ISeries)) GenericType]{
...
}

@subsubsection[#:tag "apply-stat-is"]{apply-stat-is}
@defproc[(apply-stat-is (arg0 Symbol) (arg1 ISeries)) Real]{
...
}

@subsubsection[#:tag "iseries-print"]{iseries-print}
@defproc[(iseries-print (arg0 ISeries) (arg1 (#:output-port Output-Port))) Void]{
...
}

@subsubsection[#:tag "iseries-filter"]{iseries-filter}
@defproc[(iseries-filter (arg0 ISeries) (arg1 (RFFixnum -> Boolean))) ISeries]{
...
}

@subsubsection[#:tag "iseries-filter-not"]{iseries-filter-not}
@defproc[(iseries-filter-not (arg0 ISeries) (arg1 (RFFixnum -> Boolean))) ISeries]{
...
}

@subsubsection[#:tag "fxvector->list"]{fxvector->list}
@defproc[(fxvector->list (arg0 FxVector) (arg1 Fixnum)) (Listof Fixnum)]{
...
}

@subsubsection[#:tag "list->fxvector"]{list->fxvector}
@defproc[(list->fxvector (arg0 (Listof Fixnum))) FxVector]{
...
}

@subsubsection[#:tag "iseries-notna"]{iseries-notna}
@defproc[(iseries-notna (arg0 ISeries)) ISeries]{
...
}

@subsubsection[#:tag "iseries-isna"]{iseries-isna}
@defproc[(iseries-isna (arg0 ISeries)) ISeries]{
...
}

@subsubsection[#:tag "make-RFFixnum-vector"]{make-RFFixnum-vector}
@defproc[(make-RFFixnum-vector (arg0 (U (Sequenceof Fixnum) (Sequenceof RFFixnum)))) (Vectorof RFFixnum)]{
...
}

@subsubsection[#:tag "derive-fixnum-value"]{derive-fixnum-value}
@defproc[(derive-fixnum-value (arg0 ISeries) (arg1 RFFixnum)) Fixnum]{
...
}

@subsubsection[#:tag "Integer Series Builder"]{Integer Series Builder}
@codeblock|{
(struct-out ISeriesBuilder)

(struct: ISeriesBuilder ([index  : Index]
			 [data : (Vectorof RFFixnum)]) #:mutable)
}|

@subsubsection[#:tag "new-ISeriesBuilder"]{new-ISeriesBuilder}
@defproc[(new-ISeriesBuilder (arg0 (U Void Index))) ISeriesBuilder]{
...
}

@subsubsection[#:tag "append-ISeriesBuilder"]{append-ISeriesBuilder}
@defproc[(append-ISeriesBuilder (arg0 ISeriesBuilder) (arg1 (U RFFixnum String))) Void]{
...
}

@subsubsection[#:tag "complete-ISeriesBuilder"]{complete-ISeriesBuilder}
@defproc[(complete-ISeriesBuilder (arg0 ISeriesBuilder)) ISeries]{
...
}

@subsubsection[#:tag "Example Usage"]{Example Usage}
@defproc[#:link-target? #f
 (new-ISeries [data (Vectorof Fixnum)] [label (Option (U (Listof Label) SIndex))])
ISeries?]{
Returns a new ISeries.
}

@codeblock|{
    (define series-integer (new-ISeries (fxvector 1 2 3 4)
                #:index (build-index-from-list (list 'a 'b 'c 'd))))
  }|

@defproc[#:link-target? #f
 (iseries-iref [iseries ISeries] [idx Index])
Fixnum?]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (iseries-iref series-integer 0) ; 1

  (iseries-iref series-integer 1) ; 2
  }|

@defproc[#:link-target? #f
 (iseries-label-ref [iseries ISeries] [label Label])
Fixnum?]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (iseries-label-ref series-integer 'd) ; 4

  (iseries-label-ref series-integer 'c) ; 3
  }|

@defproc[#:link-target? #f
 (iseries-range [iseries ISeries] [pos Index])
(Vectorof Fixnum)]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (list 1 2 3 4)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (iseries-range series-integer 2) ; (vector 1 2)
  }|

@defproc[#:link-target? #f
 (iseries-length [iseries ISeries])
Index]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (iseries-length series-integer) ; 4
  }|

@defproc[#:link-target? #f
 (iseries-referencer [iseries ISeries])
(Index -> Fixnum)]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (list 1 2 3 4)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  ((iseries-referencer series-integer) 0) ; 1

  ((iseries-referencer series-integer) 1) ; 2
  }|

@defproc[#:link-target? #f
 (iseries-data [iseries ISeries])
(Vectorof Fixnum)]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (iseries-data series-integer) ; (vector 1 2 3 4)
  }|

@defproc[#:link-target? #f
 (map/is [iseries ISeries] [fn (Fixnum -> Fixnum)])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (: fixnum-vector (Vectorof Fixnum))
  (define fixnum-vector (vector 1 2 3 4))
  (define series-integer (new-ISeries fixnum-vector
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (iseries-data (map/is series-integer (λ: ((x : Fixnum)) (unsafe-fx+ x 1)))) ; (vector 2 3 4 5)
  }|

@defproc[#:link-target? #f
 (bop/is [iseries ISeries] [iseries-2 ISeries] [fn (Fixnum Fixnum -> Fixnum)])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (define series-integer-2 (new-ISeries (fxvector 5 6 7 8)))

  (iseries-data (bop/is series-integer series-integer-2 (λ: ((x : Fixnum) (y : Fixnum)) (unsafe-fx+ x y)))) ; (ISeries 6 8 10 12)
  }|

@defproc[#:link-target? #f
 (comp/is [iseries ISeries] [iseries-2 ISeries] [fn (Fixnum Fixnum -> Boolean)])
BSeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (define series-integer-2 (new-ISeries (fxvector 5 6 7 8)))

  (iseries-data (comp/is series-integer series-integer-2 (λ: ((x : Fixnum) (y : Fixnum)) (unsafe-fx> x y)))) ; (BSeries #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (+/is [iseries ISeries] [iseries-2 ISeries])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (define series-integer-2 (new-ISeries (list 5 6 7 8)))

  (iseries-data (+/is series-integer series-integer-2)) ; (vector 6 8 10 12)
  }|

@defproc[#:link-target? #f
 (+/is [iseries ISeries] [iseries-2 ISeries])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (list 1 2 3 4)))

  (define series-integer-2 (new-ISeries (list 5 6 7 8)))

  (iseries-data (-/is series-integer series-integer-2)) ; (vector -4 -4 -4 -4)
  }|

@defproc[#:link-target? #f
 (*/is [iseries ISeries] [iseries-2 ISeries])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (define series-integer-2 (new-ISeries (fxvector 5 6 7 8)))

  (iseries-data (*/is series-integer series-integer-2)) ; (vector 5 12 21 32)
  }|

@defproc[#:link-target? #f
 (//is [iseries ISeries] [iseries-2 ISeries])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (list 1 2 3 4)))

  (define series-integer-2 (new-ISeries (list 5 6 7 8)))

  (iseries-data (//is series-integer series-integer-2)) ; (vector 0 0 0 0)
  }|

@defproc[#:link-target? #f
 (%/is [iseries ISeries] [iseries-2 ISeries])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (list 1 2 3 4)))

  (define series-integer-2 (new-ISeries (list 5 6 7 8)))

  (iseries-data (%/is series-integer series-integer-2)) ; (vector 1 2 3 4)
  }|

@defproc[#:link-target? #f
 (r/is [iseries ISeries] [iseries-2 ISeries])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (list 1 2 3 4)))

  (define series-integer-2 (new-ISeries (list 5 6 7 8)))

  (iseries-data (r/is series-integer series-integer-2)) ; (vector 1 2 3 4)
  }|

@defproc[#:link-target? #f
 (+./is [iseries ISeries] [num Fixnum])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (list 1 2 3 4)))

  (iseries-data (+./is series-integer 2)) ; (vector 3 4 5 6)
  }|

@defproc[#:link-target? #f
 (-./is [iseries ISeries] [num Fixnum])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (iseries-data (-./is series-integer 2)) ; (vector -1 0 1 2)
  }|

@defproc[#:link-target? #f
 (*./is [iseries ISeries] [num Fixnum])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (iseries-data (*./is series-integer 2)) ; (vector 2 3 6 8)
  }|

@defproc[#:link-target? #f
 (/./is [iseries ISeries] [num Fixnum])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (iseries-data (/./is series-integer 2)) ; (vector 0 1 1 2)
  }|

@defproc[#:link-target? #f
 (%./is [iseries ISeries] [num Fixnum])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (iseries-data (%./is series-integer 2)) ; (vector 1 0 1 0)
  }|

@defproc[#:link-target? #f
 (r./is [iseries ISeries] [num Fixnum])
ISeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (iseries-data (r./is series-integer 2)) ; (vector 1 0 1 0)
  }|

@defproc[#:link-target? #f
 (>/is [iseries ISeries] [iseries-2 ISeries])
BSeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (define series-integer-2 (new-ISeries (fxvector 5 6 7 8)))

  (bseries-data (>/is series-integer series-integer-2)) ; (vector #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (</is [iseries ISeries] [iseries-2 ISeries])
BSeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (define series-integer-2 (new-ISeries (fxvector 5 6 7 8)))

  (bseries-data (</is series-integer series-integer-2)) ; (vector #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (>=/is [iseries ISeries] [iseries-2 ISeries])
BSeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (list 1 2 3 4)))

  (define series-integer-2 (new-ISeries (list 5 6 7 8)))

  (bseries-data (>=/is series-integer series-integer-2)) ; (vector #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (<=/is [iseries ISeries] [iseries-2 ISeries])
BSeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (define series-integer-2 (new-ISeries (fxvector 5 6 7 8)))

  (bseries-data (<=/is series-integer series-integer-2)) ; (vector #t #t #t #t)
  }|

@defproc[#:link-target? #f
 (=/is [iseries ISeries] [iseries-2 ISeries])
BSeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (define series-integer-2 (new-ISeries (fxvector 5 6 7 8)))

  (bseries-data (=/is series-integer series-integer-2)) ; (vector #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (!=/is [iseries ISeries] [iseries-2 ISeries])
BSeries]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (define series-integer-2 (new-ISeries (fxvector 5 6 7 8)))

  (bseries-data (!=/is series-integer series-integer-2)) ; (vector #t #t #t #t)
  }|

@defproc[#:link-target? #f
 (apply-agg-is [func Symbol] [iseries ISeries])
Real]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (apply-agg-is 'sum series-integer) ; 10

  (apply-agg-is 'mean series-integer) ; 10/4

  (apply-agg-is 'count series-integer) ; 4

  (apply-agg-is 'min series-integer) ; 1

  (apply-agg-is 'max series-integer) ; 4
  }|

@defproc[#:link-target? #f
 (apply-stat-is [func Symbol] [iseries ISeries])
Real]{
Returns the Fixnum value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-ISeries (fxvector 1 2 3 4)))

  (apply-stat-is 'variance series-integer) ; 5/4

  (apply-stat-is 'stddev series-integer) ; 1.118033988749895

  (apply-stat-is 'skewness series-integer) ; 0.0
  }|

@subsection[#:style 'toc]{Numeric Series}

@"\U2190" Numeric Series is abbreviated to NSeries in RacketFrames.

@codeblock|{
(provide 
 (struct-out NSeries)
 NSeries-index (rename-out [GroupHash nseries-grouphash] [DEFAULT_NULL_VALUE NSERIES_DEFAULT_NULL_VALUE]))

(struct: Summary ([mean : Flonum]
                  [variance : Flonum]
                  [min : Flonum]
                  [max : Flonum]
                  [count : Natural]
                  [nans : Natural]))

(define DEFAULT_NULL_VALUE : Flonum +nan.0)

;; An NSeries is an optimized Series for computation over vectors of Flonum
;; i.e., NSeries should be faster then (Series Flonum)
(struct: NSeries ([index : (Option RFIndex)]
                  [data : FlVector]
                  ; when the null-value is not a fixnum?, the fixnum-null-value is set to 0
                  [null-value : RFNULL]
                  ; needed for type checking purposes and to do proper arithmetic operations in numeric series
                  [flonum-null-value : Flonum]
                  ; encode data by element count to optimze memory storage and read/write operations
                  ; when data vector lacks variety
                  [encoded : Boolean]
                  [data-count-encoded : (Option (Listof (Pairof Any Real)))])
  #:mutable
  #:transparent)

; When working with very large values that occur frequently,
; it can be more performant to use the ISeries-Nominals form
; which will only keep one copy of the Fixnum and maintain a
; a light weight vector of index to reference to the nominals.
; categorical series are constructed in nominal form by default,
; but with other series types it is not
(struct: NSeries-Nominals
  ([index : (Option RFIndex)]
   [data : (Vectorof Index)]
   [nominals : FlVector]
   [null-value : RFNULL])
  #:mutable
  #:transparent) 
}|

@local-table-of-contents[]

@subsubsection[#:tag "new-NSeries"]{new-NSeries}
@defproc[(new-NSeries (arg0 (U (Sequenceof Flonum) FlVector)) (arg1 (#:index (Option (U (Sequenceof IndexDataType) RFIndex)))) (arg2 (#:fill-null RFNULL)) (arg3 (#:sort Boolean)) (arg4 (#:encode Boolean))) NSeries]{
...
}

@subsubsection[#:tag "set-NSeries-index"]{set-NSeries-index}
@defproc[(set-NSeries-index (arg0 NSeries) (arg1 (U (Listof IndexDataType) RFIndex))) NSeries]{
...
}

@subsubsection[#:tag "set-NSeries-null-value"]{set-NSeries-null-value}
@defproc[(set-NSeries-null-value (arg0 NSeries) (arg1 RFNULL)) NSeries]{
...
}

@subsubsection[#:tag "nseries-custom-null-value"]{nseries-custom-null-value}
@defproc[(nseries-custom-null-value (arg0 NSeries)) RFNULL]{
...
}

@subsubsection[#:tag "nseries-null-value"]{nseries-null-value}
@defproc[(nseries-null-value (arg0 NSeries)) Flonum]{
...
}

@subsubsection[#:tag "set-NSeries-flonum-null-value-inplace"]{set-NSeries-flonum-null-value-inplace}
@defproc[(set-NSeries-flonum-null-value-inplace (arg0 NSeries) (arg1 Flonum)) Void]{
...
}

@subsubsection[#:tag "nseries-iref"]{nseries-iref}
@defproc[(nseries-iref (arg0 NSeries) (arg1 (Listof Index))) (Listof Flonum)]{
...
}

@subsubsection[#:tag "nseries-loc-boolean"]{nseries-loc-boolean}
@defproc[(nseries-loc-boolean (arg0 NSeries) (arg1 (Listof Boolean))) (U Flonum NSeries)]{
...
}

@subsubsection[#:tag "nseries-loc"]{nseries-loc}
@defproc[(nseries-loc (arg0 NSeries) (arg1 (U Label (Listof Label) (Listof Boolean)))) (U Flonum NSeries)]{
...
}

@subsubsection[#:tag "nseries-loc-multi-index"]{nseries-loc-multi-index}
@defproc[(nseries-loc-multi-index (arg0 NSeries) (arg1 (U (Listof String) ListofListofString))) (U Flonum NSeries)]{
...
}

@subsubsection[#:tag "nseries-iloc"]{nseries-iloc}
@defproc[(nseries-iloc (arg0 NSeries) (arg1 (U Index (Listof Index)))) (U Flonum NSeries)]{
...
}

@subsubsection[#:tag "nseries-iloc-range"]{nseries-iloc-range}
@defproc[(nseries-iloc-range (arg0 NSeries) (arg1 Index) (arg2 Index)) NSeries]{
...
}

@subsubsection[#:tag "nseries-index-ref"]{nseries-index-ref}
@defproc[(nseries-index-ref (arg0 NSeries) (arg1 IndexDataType)) (Listof Flonum)]{
...
}

@subsubsection[#:tag "nseries-range"]{nseries-range}
@defproc[(nseries-range (arg0 NSeries) (arg1 Index)) FlVector]{
...
}

@subsubsection[#:tag "nseries-referencer"]{nseries-referencer}
@defproc[(nseries-referencer (arg0 NSeries)) (Index -> Flonum)]{
...
}

@subsubsection[#:tag "nseries-length"]{nseries-length}
@defproc[(nseries-length (arg0 NSeries)) Index]{
...
}

@subsubsection[#:tag "nseries-data"]{nseries-data}
@defproc[(nseries-data (arg0 NSeries)) FlVector]{
...
}

@subsubsection[#:tag "in-nseries"]{in-nseries}
@defproc[(in-nseries (arg0 Flonum) (arg1 NSeries)) Boolean]{
...
}

@subsubsection[#:tag "nseries-groupby"]{nseries-groupby}
@defproc[(nseries-groupby (arg0 NSeries) (arg1 (#:by-value Boolean))) GroupHash]{
...
}

@subsubsection[#:tag "apply-agg-nseries"]{apply-agg-nseries}
@defproc[(apply-agg-nseries (arg0 Symbol) (arg1 GroupHash)) GenSeries]{
...
}

@subsubsection[#:tag "nseries-index"]{nseries-index}
@defproc[(nseries-index (arg0 NSeries)) (U False RFIndex)]{
...
}

@subsubsection[#:tag "map/ns"]{map/ns}
@defproc[(map/ns (arg0 NSeries) (arg1 (Flonum -> Flonum))) NSeries]{
...
}

@subsubsection[#:tag "bop/ns"]{bop/ns}
@defproc[(bop/ns (arg0 NSeries) (arg1 NSeries) (arg2 (Flonum Flonum -> Flonum))) NSeries]{
...
}

@subsubsection[#:tag "+/ns"]{+/ns}
@defproc[(+/ns (arg0 NSeries) (arg1 NSeries)) NSeries]{
...
}

@subsubsection[#:tag "-/ns"]{-/ns}
@defproc[(-/ns (arg0 NSeries) (arg1 NSeries)) NSeries]{
...
}

@subsubsection[#:tag "*/ns"]{*/ns}
@defproc[(*/ns (arg0 NSeries) (arg1 NSeries)) NSeries]{
...
}

@subsubsection[#:tag "//ns"]{//ns}
@defproc[(//ns (arg0 NSeries) (arg1 NSeries)) NSeries]{
...
}

@subsubsection[#:tag ">/ns"]{>/ns}
@defproc[(>/ns (arg0 NSeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "</ns"]{</ns}
@defproc[(</ns (arg0 NSeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag ">=/ns"]{>=/ns}
@defproc[(>=/ns (arg0 NSeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "<=/ns"]{<=/ns}
@defproc[(<=/ns (arg0 NSeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "=/ns"]{=/ns}
@defproc[(=/ns (arg0 NSeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "!=/ns"]{!=/ns}
@defproc[(!=/ns (arg0 NSeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "+./ns"]{+./ns}
@defproc[(+./ns (arg0 NSeries) (arg1 Flonum)) NSeries]{
...
}

@subsubsection[#:tag "-./ns"]{-./ns}
@defproc[(-./ns (arg0 NSeries) (arg1 Flonum)) NSeries]{
...
}

@subsubsection[#:tag "*./ns"]{*./ns}
@defproc[(*./ns (arg0 NSeries) (arg1 Flonum)) NSeries]{
...
}

@subsubsection[#:tag "/./ns"]{/./ns}
@defproc[(/./ns (arg0 NSeries) (arg1 Flonum)) NSeries]{
...
}

@subsubsection[#:tag "+/ns/is"]{+/ns/is}
@defproc[(+/ns/is (arg0 NSeries) (arg1 ISeries)) NSeries]{
...
}

@subsubsection[#:tag "-/ns/is"]{-/ns/is}
@defproc[(-/ns/is (arg0 NSeries) (arg1 ISeries)) NSeries]{
...
}

@subsubsection[#:tag "*/ns/is"]{*/ns/is}
@defproc[(*/ns/is (arg0 NSeries) (arg1 ISeries)) NSeries]{
...
}

@subsubsection[#:tag "//ns/is"]{//ns/is}
@defproc[(//ns/is (arg0 NSeries) (arg1 ISeries)) NSeries]{
...
}

@subsubsection[#:tag "+/is/ns"]{+/is/ns}
@defproc[(+/is/ns (arg0 ISeries) (arg1 NSeries)) NSeries]{
...
}

@subsubsection[#:tag "-/is/ns"]{-/is/ns}
@defproc[(-/is/ns (arg0 ISeries) (arg1 NSeries)) NSeries]{
...
}

@subsubsection[#:tag "*/is/ns"]{*/is/ns}
@defproc[(*/is/ns (arg0 ISeries) (arg1 NSeries)) NSeries]{
...
}

@subsubsection[#:tag "//is/ns"]{//is/ns}
@defproc[(//is/ns (arg0 ISeries) (arg1 NSeries)) NSeries]{
...
}

@subsubsection[#:tag ">/ns/is"]{>/ns/is}
@defproc[(>/ns/is (arg0 NSeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag "</ns/is"]{</ns/is}
@defproc[(</ns/is (arg0 NSeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag ">=/ns/is"]{>=/ns/is}
@defproc[(>=/ns/is (arg0 NSeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag "<=/ns/is"]{<=/ns/is}
@defproc[(<=/ns/is (arg0 NSeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag "=/ns/is"]{=/ns/is}
@defproc[(=/ns/is (arg0 NSeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag "!=/ns/is"]{!=/ns/is}
@defproc[(!=/ns/is (arg0 NSeries) (arg1 ISeries)) BSeries]{
...
}

@subsubsection[#:tag ">/is/ns"]{>/is/ns}
@defproc[(>/is/ns (arg0 ISeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "</is/ns"]{</is/ns}
@defproc[(</is/ns (arg0 ISeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag ">=/is/ns"]{>=/is/ns}
@defproc[(>=/is/ns (arg0 ISeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "<=/is/ns"]{<=/is/ns}
@defproc[(<=/is/ns (arg0 ISeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "=/is/ns"]{=/is/ns}
@defproc[(=/is/ns (arg0 ISeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "!=/is/ns"]{!=/is/ns}
@defproc[(!=/is/ns (arg0 ISeries) (arg1 NSeries)) BSeries]{
...
}

@subsubsection[#:tag "apply-agg-ns"]{apply-agg-ns}
@defproc[(apply-agg-ns (arg0 Symbol) (arg1 NSeries)) GenericType]{
...
}

@subsubsection[#:tag "apply-stat-ns"]{apply-stat-ns}
@defproc[(apply-stat-ns (arg0 Symbol) (arg1 NSeries)) Real]{
...
}

@subsubsection[#:tag "flvector->list"]{flvector->list}
@defproc[(flvector->list (arg0 FlVector) (arg1 (#:index Fixnum))) (Listof Flonum)]{
...
}

@subsubsection[#:tag "flvector->vector"]{flvector->vector}
@defproc[(flvector->vector (arg0 FlVector) (arg1 (#:index Fixnum))) (Vectorof Flonum)]{
...
}

@subsubsection[#:tag "list->flvector"]{list->flvector}
@defproc[(list->flvector (arg0 (Listof Flonum))) FlVector]{
...
}

@subsubsection[#:tag "nseries-print"]{nseries-print}
@defproc[(nseries-print (arg0 NSeries) (arg1 (#:output-port Output-Port))) Void]{
...
}

@subsubsection[#:tag "flvector-print"]{flvector-print}
@defproc[(flvector-print (arg0 FlVector)) Void]{
...
}

@subsubsection[#:tag "generate-NSeries"]{generate-NSeries}
@defproc[(generate-NSeries (arg0 Float) (arg1 Float) (arg2 (#:by Float))) NSeries]{
...
}

@subsubsection[#:tag "Numeric Series Builder"]{Numeric Series Builder}
@codeblock|{
(struct-out NSeriesBuilder)

(struct: NSeriesBuilder ([index  : Index]
			 [data : (Vectorof Flonum)]) #:mutable)
}|

@subsubsection[#:tag "new-NSeriesBuilder"]{new-NSeriesBuilder}
@defproc[(new-NSeriesBuilder (arg0 (U Void Index))) NSeriesBuilder]{
...
}

@subsubsection[#:tag "append-NSeriesBuilder"]{append-NSeriesBuilder}
@defproc[(append-NSeriesBuilder (arg0 NSeriesBuilder) (arg1 (U Flonum String))) Void]{
...
}

@subsubsection[#:tag "complete-NSeriesBuilder"]{complete-NSeriesBuilder}
@defproc[(complete-NSeriesBuilder (arg0 NSeriesBuilder)) NSeries]{
...
}

@subsubsection[#:style 'toc #:tag "Example Usage"]{Example Usage}
@defproc[#:link-target? #f
 (new-NSeries [data (Vectorof Float)] [label (Option (U (Lnstof Label) SIndex))])
NSeries?]{
Returns a new NSeries.
}

@codeblock|{
    (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))
  }|

@defproc[#:link-target? #f
 (nseries-iref [nseries NSeries] [idx Index])
Float?]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
 
(define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))
                                      
(nseries-iref series-float 0) ; 1.5

(nseries-iref series-float 1) ; 2.4
  }|

@defproc[#:link-target? #f
 (nseries-label-ref [nseries NSeries] [label Label])
Float?]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (nseries-label-ref series-float 'd) ; 4.1
  
  (nseries-label-ref series-float 'c) ; 3.6
  }|

@defproc[#:link-target? #f
 (nseries-range [nseries NSeries] [pos Index])
(Vectorof Float)]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (nseries-range series-float 2) ; (flvector 1.5 2.4)
  }|

@defproc[#:link-target? #f
 (nseries-length [nseries NSeries])
Index]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (nseries-length series-float) ; 4
  }|

@defproc[#:link-target? #f
 (nseries-referencer [nseries NSeries])
(Index -> Float)]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  ((nseries-referencer series-float) 0) ; 1.5

  ((nseries-referencer series-float) 1) ; 2.4
  }|

@defproc[#:link-target? #f
 (nseries-data [nseries NSeries])
(Vectorof Float)]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (nseries-data series-foat) ; (flvector 1.5 2.4 3.6 4.1)ap
  }|

@defproc[#:link-target? #f
 (map/ns [nseries NSeries] [fn (Float -> Float)])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (nseries-data (map/ns series-float (λ: ((x : Float)) (fl+ x 1.0)))) ; (flvector 2.5 3.4 4.6 5.1)
  }|

@defproc[#:link-target? #f
 (bop/ns [nseries NSeries] [nseries-2 NSeries] [fn (Float Float -> Float)])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (nseries-data (bop/ns series-integer series-integer-2 (λ: ((x : Float) (y : Float)) (unsafe-fx+ x y)))) ; (new-NSeries 6 8 10 12)
  }|

@defproc[#:link-target? #f
 (comp/ns [nseries NSeries] [nseries-2 NSeries] [fn (Float Float -> Boolean)])
BSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (nseries-data (comp/ns series-integer series-integer-2 (λ: ((x : Float) (y : Float)) (unsafe-fx> x y)))) ; (BSeries #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (+/ns [nseries NSeries] [nseries-2 NSeries])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (define series-float-2 (new-NSeries (flvector 5.0 6.0 7.0 8.0)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (nseries-data (+/ns series-float series-float-2)) ; (flvector 6.5 8.4 10.6 12.1))
  }|

@defproc[#:link-target? #f
 (+/ns [nseries NSeries] [nseries-2 NSeries])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (define series-float-2 (new-NSeries (flvector 5.0 6.0 7.0 8.0)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (nseries-data (-/ns series-float series-float-2)) ; (flvector -3.5 -3.6 -3.4 -3.9000000000000004)
  }|

@defproc[#:link-target? #f
 (*/ns [nseries NSeries] [nseries-2 NSeries])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (define series-float-2 (new-NSeries (flvector 5.0 6.0 7.0 8.0)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (nseries-data (*/ns series-float series-float-2)) ; (flvector 7.5 14.399999999999999 25.2 32.8)
  }|

@defproc[#:link-target? #f
 (//ns [nseries NSeries] [nseries-2 NSeries])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-float (new-NSeries (flvector 1.5 2.4 3.6 4.1)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (define series-float-2 (new-NSeries (flvector 5.0 6.0 7.0 8.0)
                                      #:index (build-index-from-list (list 'a 'b 'c 'd))))

  (nseries-data (//ns series-float series-float-2)) ; (flvector 0.3 0.39999999999999997 0.5142857142857143 0.5125)
  }|

@defproc[#:link-target? #f
 (%/ns [nseries NSeries] [nseries-2 NSeries])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (nseries-data (%/ns series-integer series-integer-2)) ; (vector 1 2 3 4)
  }|

@defproc[#:link-target? #f
 (r/ns [nseries NSeries] [nseries-2 NSeries])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (nseries-data (r/ns series-integer series-integer-2)) ; (vector 1 2 3 4)
  }|

@defproc[#:link-target? #f
 (+./ns [nseries NSeries] [num Float])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (nseries-data (+./ns series-integer 2)) ; (vector 3 4 5 6)
  }|

@defproc[#:link-target? #f
 (-./ns [nseries NSeries] [num Float])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (nseries-data (-./ns series-integer 2)) ; (vector -1 0 1 2)
  }|

@defproc[#:link-target? #f
 (*./ns [nseries NSeries] [num Float])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (nseries-data (*./ns series-integer 2)) ; (vector 2 3 6 8)
  }|

@defproc[#:link-target? #f
 (/./ns [nseries NSeries] [num Float])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (nseries-data (/./ns series-integer 2)) ; (vector 0 1 1 2)
  }|

@defproc[#:link-target? #f
 (%./ns [nseries NSeries] [num Float])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (nseries-data (%./ns series-integer 2)) ; (vector 1 0 1 0)
  }|

@defproc[#:link-target? #f
 (r./ns [nseries NSeries] [num Float])
NSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (nseries-data (r./ns series-integer 2)) ; (vector 1 0 1 0)
  }|

@defproc[#:link-target? #f
 (>/ns [nseries NSeries] [nseries-2 NSeries])
BSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (bseries-data (>/ns series-integer series-integer-2)) ; (vector #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (</ns [nseries NSeries] [nseries-2 NSeries])
BSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (bseries-data (</ns series-integer series-integer-2)) ; (vector #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (>=/ns [nseries NSeries] [nseries-2 NSeries])
BSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (bseries-data (>=/ns series-integer series-integer-2)) ; (vector #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (<=/ns [nseries NSeries] [nseries-2 NSeries])
BSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (bseries-data (<=/ns series-integer series-integer-2)) ; (vector #t #t #t #t)
  }|

@defproc[#:link-target? #f
 (=/ns [nseries NSeries] [nseries-2 NSeries])
BSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (bseries-data (=/ns series-integer series-integer-2)) ; (vector #f #f #f #f)
  }|

@defproc[#:link-target? #f
 (!=/ns [nseries NSeries] [nseries-2 NSeries])
BSeries]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (define series-integer-2 (new-NSeries (vector 5 6 7 8)))

  (bseries-data (!=/ns series-integer series-integer-2)) ; (vector #t #t #t #t)
  }|

@defproc[#:link-target? #f
 (apply-agg-ns [func Symbol] [nseries NSeries])
Real]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (apply-agg-ns 'sum series-integer) ; 10

  (apply-agg-ns 'mean series-integer) ; 10/4

  (apply-agg-ns 'count series-integer) ; 4

  (apply-agg-ns 'min series-integer) ; 1

  (apply-agg-ns 'max series-integer) ; 4
  }|

@defproc[#:link-target? #f
 (apply-stat-ns [func Symbol] [nseries NSeries])
Real]{
Returns the Float value at the specified index in the series.
}

@codeblock|{
  (define series-integer (new-NSeries (vector 1 2 3 4)))

  (apply-stat-ns 'variance series-integer) ; 5/4

  (apply-stat-ns 'stddev series-integer) ; 1.118033988749895

  (apply-stat-ns 'skewness series-integer) ; 0.0
  }|


@subsection[#:style 'toc]{Categorical Series}

@"\U2190" Categorical Series is abbreviated to CSeries in RacketFrames.

@codeblock|{
(define DEFAULT_NULL_VALUE : Label '||)
(struct: CSeries ([index : (Option RFIndex)]
                  [data : (Vectorof Index)]
                  [nominals : (Vectorof Label)]
                  ; when the null-value is not a symbol?, the label-null-value is set to 'null
                  [null-value : RFNULL]
                  ; needed for type checking purposes and to do proper symbol operations
                  [label-null-value : Label])
  #:mutable
  #:transparent)
  }|

@local-table-of-contents[]

@subsubsection[#:tag "new-CSeries"]{new-CSeries}
@defproc[(new-CSeries (arg0 (Sequenceof Label)) (arg1 (#:index (Option (U (Sequenceof IndexDataType) RFIndex)))) (arg2 (#:fill-null RFNULL))) CSeries]{
...
}

@subsubsection[#:tag "set-CSeries-index"]{set-CSeries-index}
@defproc[(set-CSeries-index (arg0 CSeries) (arg1 (U (Listof IndexDataType) RFIndex))) CSeries]{
...
}

@subsubsection[#:tag "set-CSeries-null-value"]{set-CSeries-null-value}
@defproc[(set-CSeries-null-value (arg0 CSeries) (arg1 RFNULL)) CSeries]{
...
}

@subsubsection[#:tag "set-CSeries-label-null-value-inplace"]{set-CSeries-label-null-value-inplace}
@defproc[(set-CSeries-label-null-value-inplace (arg0 CSeries) (arg1 Label)) Void]{
...
}

@subsubsection[#:tag "cseries-length"]{cseries-length}
@defproc[(cseries-length (arg0 CSeries)) Index]{
...
}

@subsubsection[#:tag "cseries-iref"]{cseries-iref}
@defproc[(cseries-iref (arg0 CSeries) (arg1 (Listof Index))) (Listof Label)]{
...
}

@subsubsection[#:tag "cseries-range"]{cseries-range}
@defproc[(cseries-range (arg0 CSeries) (arg1 Index)) (Vectorof Label)]{
...
}

@subsubsection[#:tag "cseries-data"]{cseries-data}
@defproc[(cseries-data (arg0 CSeries)) (Vectorof Label)]{
...
}

@subsubsection[#:tag "cseries-nominal-data"]{cseries-nominal-data}
@defproc[(cseries-nominal-data (arg0 CSeries)) (Vectorof Label)]{
...
}

@subsubsection[#:tag "cseries-index"]{cseries-index}
@defproc[(cseries-index (arg0 CSeries)) (U False RFIndex)]{
...
}

@subsubsection[#:tag "cseries-null-value"]{cseries-null-value}
@defproc[(cseries-null-value (arg0 CSeries)) Label]{
...
}

@subsubsection[#:tag "cseries-custom-null-value"]{cseries-custom-null-value}
@defproc[(cseries-custom-null-value (arg0 CSeries)) RFNULL]{
...
}

@subsubsection[#:tag "in-cseries"]{in-cseries}
@defproc[(in-cseries (arg0 Label) (arg1 CSeries)) Boolean]{
...
}

@subsubsection[#:tag "cseries-value-is-null?"]{cseries-value-is-null?}
@defproc[(cseries-value-is-null? (arg0 CSeries) (arg1 Label)) Boolean]{
...
}

@subsubsection[#:tag "cseries-referencer"]{cseries-referencer}
@defproc[(cseries-referencer (arg0 CSeries)) (Index -> Label)]{
...
}

@subsubsection[#:tag "cseries-iloc"]{cseries-iloc}
@defproc[(cseries-iloc (arg0 CSeries) (arg1 (U Index (Listof Index)))) (U Label CSeries)]{
...
}

@subsubsection[#:tag "cseries-groupby"]{cseries-groupby}
@defproc[(cseries-groupby (arg0 CSeries) (arg1 (#:by-value Boolean))) GroupHash]{
...
}

@subsubsection[#:tag "cseries-index-ref"]{cseries-index-ref}
@defproc[(cseries-index-ref (arg0 CSeries) (arg1 IndexDataType)) (Listof Label)]{
...
}

@subsubsection[#:tag "cseries-print"]{cseries-print}
@defproc[(cseries-print (arg0 CSeries) (arg1 (#:output-port Output-Port))) Void]{
...
}

@subsubsection[#:tag "cseries-loc-boolean"]{cseries-loc-boolean}
@defproc[(cseries-loc-boolean (arg0 CSeries) (arg1 (Listof Boolean))) (U Label CSeries)]{
...
}

@subsubsection[#:tag "cseries-loc"]{cseries-loc}
@defproc[(cseries-loc (arg0 CSeries) (arg1 (U Label (Listof Label) (Listof Boolean)))) (U Label CSeries)]{
...
}

@subsubsection[#:tag "cseries-loc-multi-index"]{cseries-loc-multi-index}
@defproc[(cseries-loc-multi-index (arg0 CSeries) (arg1 (U (Listof String) ListofListofString))) (U Label CSeries)]{
...
}

@subsubsection[#:tag "cseries-head"]{cseries-head}
@defproc[(cseries-head (arg0 CSeries) (arg1 (#:rows Index))) CSeries]{
...
}

@subsubsection[#:tag "cseries-head-display"]{cseries-head-display}
@defproc[(cseries-head-display (arg0 CSeries) (arg1 (#:rows Index))) Void]{
...
}

@subsubsection[#:tag "cseries-unique"]{cseries-unique}
@defproc[(cseries-unique (arg0 CSeries)) CSeries]{
...
}

@subsubsection[#:tag "cseries-append"]{cseries-append}
@defproc[(cseries-append (arg0 CSeries) (arg1 CSeries)) CSeries]{
...
}

@subsubsection[#:tag "Categorical Series Builder"]{Categorical Series Builder}
@codeblock|{
(struct-out CSeriesBuilder)

(struct: CSeriesBuilder ([index  : Index]
			 [data : (Vectorof Symbol)]) #:mutable)
}|

@subsubsection[#:tag "new-CSeriesBuilder"]{new-CSeriesBuilder}
@defproc[(new-CSeriesBuilder (arg0 (U Void Index))) CSeriesBuilder]{
...
}

@subsubsection[#:tag "append-CSeriesBuilder"]{append-CSeriesBuilder}
@defproc[(append-CSeriesBuilder (arg0 CSeriesBuilder) (arg1 (U Symbol String))) Void]{
...
}

@subsubsection[#:tag "complete-CSeriesBuilder"]{complete-CSeriesBuilder}
@defproc[(complete-CSeriesBuilder (arg0 CSeriesBuilder)) CSeries]{
...
}

@subsection[#:style 'toc]{Boolean Series}
@"\U2190" Boolean Series is abbreviated to BSeries in RacketFrames.

@codeblock|{
(struct-out BSeries)

;; Boolean series.
(struct BSeries ([index : (Option RFIndex)]
                 [data : (Vectorof Boolean)]
                 [null-value : Boolean])  
  #:mutable
  #:transparent)
}|

@local-table-of-contents[]

@subsubsection[#:tag "new-BSeries"]{new-BSeries}
@defproc[(new-BSeries (arg0 (U (Sequenceof Boolean) (Vectorof Boolean))) (arg1 (#:index (Option (U (Sequenceof IndexDataType) RFIndex)))) (arg2 (#:fill-null Boolean))) BSeries]{
...
}

@subsubsection[#:tag "set-BSeries-index"]{set-BSeries-index}
@defproc[(set-BSeries-index (arg0 BSeries) (arg1 (U (Listof IndexDataType) RFIndex))) BSeries]{
...
}

@subsubsection[#:tag "set-BSeries-null-value"]{set-BSeries-null-value}
@defproc[(set-BSeries-null-value (arg0 BSeries) (arg1 Boolean)) BSeries]{
...
}

@subsubsection[#:tag "bseries-null-value"]{bseries-null-value}
@defproc[(bseries-null-value (arg0 BSeries)) Boolean]{
...
}

@subsubsection[#:tag "bseries-iref"]{bseries-iref}
@defproc[(bseries-iref (arg0 BSeries) (arg1 (Listof Index))) (Listof Boolean)]{
...
}

@subsubsection[#:tag "bseries-index-ref"]{bseries-index-ref}
@defproc[(bseries-index-ref (arg0 BSeries) (arg1 IndexDataType)) (Listof Boolean)]{
...
}

@subsubsection[#:tag "bseries-range"]{bseries-range}
@defproc[(bseries-range (arg0 BSeries) (arg1 Index) (arg2 Index)) (Vectorof Boolean)]{
...
}

@subsubsection[#:tag "bseries-length"]{bseries-length}
@defproc[(bseries-length (arg0 BSeries)) Index]{
...
}

@subsubsection[#:tag "bseries-referencer"]{bseries-referencer}
@defproc[(bseries-referencer (arg0 BSeries)) (Index -> Boolean)]{
...
}

@subsubsection[#:tag "bseries-data"]{bseries-data}
@defproc[(bseries-data (arg0 BSeries)) (Vectorof Boolean)]{
...
}

@subsubsection[#:tag "bseries-index"]{bseries-index}
@defproc[(bseries-index (arg0 BSeries)) (U False RFIndex)]{
...
}

@subsubsection[#:tag "in-bseries"]{in-bseries}
@defproc[(in-bseries (arg0 Boolean) (arg1 BSeries)) Boolean]{
...
}

@subsubsection[#:tag "bseries-groupby"]{bseries-groupby}
@defproc[(bseries-groupby (arg0 BSeries) (arg1 (#:by-value Boolean))) GroupHash]{
...
}

@subsubsection[#:tag "map/bs"]{map/bs}
@defproc[(map/bs (arg0 BSeries) (arg1 (Boolean -> Boolean))) BSeries]{
...
}

@subsubsection[#:tag "bseries-loc-boolean"]{bseries-loc-boolean}
@defproc[(bseries-loc-boolean (arg0 BSeries) (arg1 (Listof Boolean))) (U Boolean BSeries)]{
...
}

@subsubsection[#:tag "bseries-loc"]{bseries-loc}
@defproc[(bseries-loc (arg0 BSeries) (arg1 (U Label (Listof Label) (Listof Boolean)))) (U Boolean BSeries)]{
...
}

@subsubsection[#:tag "bseries-loc-multi-index"]{bseries-loc-multi-index}
@defproc[(bseries-loc-multi-index (arg0 BSeries) (arg1 (U (Listof String) ListofListofString))) (U Boolean BSeries)]{
...
}

@subsubsection[#:tag "bseries-iloc"]{bseries-iloc}
@defproc[(bseries-iloc (arg0 BSeries) (arg1 (U Index (Listof Index)))) (U Boolean BSeries)]{
...
}

@subsubsection[#:tag "bseries-iloc-range"]{bseries-iloc-range}
@defproc[(bseries-iloc-range (arg0 BSeries) (arg1 Index) (arg2 Index)) BSeries]{
...
}

@subsubsection[#:tag "bseries-not"]{bseries-not}
@defproc[(bseries-not (arg0 BSeries)) BSeries]{
...
}

@subsubsection[#:tag "bseries-print"]{bseries-print}
@defproc[(bseries-print (arg0 BSeries) (arg1 (#:output-port Output-Port))) Void]{
...
}

@subsubsection[#:tag "Boolean Series Builder"]{Boolean Series Builder}
@codeblock|{
(struct-out BSeriesBuilder)

(struct: BSeriesBuilder ([index  : Index]
			 [data : (Vectorof Boolean)]) #:mutable)
}|

@subsubsection[#:tag "new-BSeriesBuilder"]{new-BSeriesBuilder}
@defproc[(new-BSeriesBuilder (arg0 (U Void Index))) BSeriesBuilder]{
...
}

@subsubsection[#:tag "append-BSeriesBuilder"]{append-BSeriesBuilder}
@defproc[(append-BSeriesBuilder (arg0 BSeriesBuilder) (arg1 (U Boolean String))) Void]{
...
}

@subsubsection[#:tag "complete-BSeriesBuilder"]{complete-BSeriesBuilder}
@defproc[(complete-BSeriesBuilder (arg0 BSeriesBuilder)) BSeries]{
...
}

@subsection[#:style 'toc]{Generic Series}

@"\U2190" Generic Series is abbreviated to GenSeries in RacketFrames.

@codeblock|{
(define DEFAULT_NULL_VALUE : GenericType null)
(struct GenSeries
  ([index : (Option RFIndex)]
   [data : (Vectorof GenericType)]
   [null-value : RFNULL]
   ; needed for type checking purposes and to do proper arithmetic operations in numeric series
   [any-null-value : GenericType]
   ; encode data by element count to optimze memory storage and read/write operations
   ; when data vector lacks variety
   [encoded : Boolean]
   [data-count-encoded : (Option (Listof (Pairof Any Real)))])
  #:mutable
  #:transparent)

; When working with very large values that occur frequently,
; it can be more performant to use the ISeries-Nominals form
; which will only keep one copy of the Fixnum and maintain a
; a light weight vector of index to reference to the nominals.
; categorical series are constructed in nominal form by default,
; but with other series types it is not
(struct: GenSeries-Nominals
  ([index : (Option RFIndex)]
   [data : (Vectorof Index)]
   [nominals : (Vectorof GenericType)]   
   [null-value : RFNULL])
  #:mutable
  #:transparent)
  }|

@local-table-of-contents[]

@subsubsection[#:tag "new-GenSeries"]{new-GenSeries}
@defproc[(new-GenSeries (arg0 (Sequenceof GenericType)) (arg1 (#:index (Option (U (Listof IndexDataType) RFIndex)))) (arg2 (#:fill-null RFNULL))) GenSeries]{
...
}

@subsubsection[#:tag "set-GenSeries-index"]{set-GenSeries-index}
@defproc[(set-GenSeries-index (arg0 GenSeries) (arg1 (U (Listof IndexDataType) RFIndex))) GenSeries]{
...
}

@subsubsection[#:tag "set-GenSeries-null-value"]{set-GenSeries-null-value}
@defproc[(set-GenSeries-null-value (arg0 GenSeries) (arg1 RFNULL)) GenSeries]{
...
}

@subsubsection[#:tag "set-GenSeries-any-null-value-inplace"]{set-GenSeries-any-null-value-inplace}
@defproc[(set-GenSeries-any-null-value-inplace (arg0 GenSeries) (arg1 GenericType)) Void]{
...
}

@subsubsection[#:tag "gen-series-iref"]{gen-series-iref}
@defproc[(gen-series-iref (arg0 GenSeries) (arg1 (Listof Index))) GenericType]{
...
}

@subsubsection[#:tag "gen-series-index-ref"]{gen-series-index-ref}
@defproc[(gen-series-index-ref (arg0 GenSeries) (arg1 IndexDataType)) (Listof GenericType)]{
...
}

@subsubsection[#:tag "gen-series-label-ref"]{gen-series-label-ref}
@defproc[(gen-series-label-ref (arg0 GenSeries) (arg1 Label)) GenericType]{
...
}

@subsubsection[#:tag "gen-series-range"]{gen-series-range}
@defproc[(gen-series-range (arg0 GenSeries) (arg1 Index) (arg2 Index)) (Vectorof GenericType)]{
...
}

@subsubsection[#:tag "gen-series-length"]{gen-series-length}
@defproc[(gen-series-length (arg0 GenSeries)) Index]{
...
}

@subsubsection[#:tag "gen-series-referencer"]{gen-series-referencer}
@defproc[(gen-series-referencer (arg0 GenSeries)) (Index -> GenericType)]{
...
}

@subsubsection[#:tag "gen-series-data"]{gen-series-data}
@defproc[(gen-series-data (arg0 GenSeries)) (Vectorof GenericType)]{
...
}

@subsubsection[#:tag "gen-series-index"]{gen-series-index}
@defproc[(gen-series-index (arg0 GenSeries)) (U False RFIndex)]{
...
}

@subsubsection[#:tag "in-gen-series"]{in-gen-series}
@defproc[(in-gen-series (arg0 GenericType) (arg1 GenSeries)) Boolean]{
...
}

@subsubsection[#:tag "gen-series-null-value"]{gen-series-null-value}
@defproc[(gen-series-null-value (arg0 GenSeries)) GenericType]{
...
}

@subsubsection[#:tag "gen-series-loc-boolean"]{gen-series-loc-boolean}
@defproc[(gen-series-loc-boolean (arg0 GenSeries) (arg1 (Listof Boolean))) (U GenericType GenSeries)]{
...
}

@subsubsection[#:tag "gen-series-loc"]{gen-series-loc}
@defproc[(gen-series-loc (arg0 GenSeries) (arg1 (U Label (Listof Label) (Listof Boolean)))) (U GenericType GenSeries)]{
...
}

@subsubsection[#:tag "gen-series-loc-multi-index"]{gen-series-loc-multi-index}
@defproc[(gen-series-loc-multi-index (arg0 GenSeries) (arg1 (U (Listof String) ListofListofString))) (U GenericType GenSeries)]{
...
}

@subsubsection[#:tag "gen-series-iloc"]{gen-series-iloc}
@defproc[(gen-series-iloc (arg0 GenSeries) (arg1 (U Index (Listof Index)))) (U GenericType GenSeries)]{
...
}

@subsubsection[#:tag "gen-series-iloc-range"]{gen-series-iloc-range}
@defproc[(gen-series-iloc-range (arg0 GenSeries) (arg1 Index) (arg2 Index)) GenSeries]{
...
}

@subsubsection[#:tag "map/gen-s"]{map/gen-s}
@defproc[(map/gen-s (arg0 GenSeries) (arg1 (GenericType -> GenericType))) GenSeries]{
...
}

@subsubsection[#:tag "gen-series-print"]{gen-series-print}
@defproc[(gen-series-print (arg0 GenSeries) (arg1 (#:output-port Output-Port))) Void]{
...
}

@subsection[#:style 'toc]{Datetime Series}

@"\U2190" Series consisting of a custom RacketFrames Datetime data type.

@codeblock|{
(define-type RFDatetime (U Datetime RFNoData))
(define-predicate RFDatetime? RFDatetime)
(define DEFAULT_NULL_VALUE : Datetime (Datetime (Date 0 0 0) (Time 0 0 0 0 0)))
(struct DatetimeSeries
  ([index : (Option RFIndex)]
   [data : (Vectorof RFDatetime)]
   ; when the null-value is not a fixnum?, the fixnum-null-value is set to 0
   [null-value : RFNULL]
   ; needed for type checking purposes and to do proper arithmetic operations in numeric series
   [datetime-null-value : Datetime])
  #:mutable
  #:transparent)
}|

@local-table-of-contents[]

@subsubsection[#:tag "new-DatetimeSeries"]{new-DatetimeSeries}
@defproc[(new-DatetimeSeries (arg0 (U (Vectorof Datetime) (Sequenceof Datetime) (Sequenceof RFDatetime))) (arg1 (#:index (Option (U (Sequenceof IndexDataType) RFIndex)))) (arg2 (#:fill-null RFNULL))) DatetimeSeries]{
...
}

@subsubsection[#:tag "set-DatetimeSeries-index"]{set-DatetimeSeries-index}
@defproc[(set-DatetimeSeries-index (arg0 DatetimeSeries) (arg1 (U (Listof IndexDataType) RFIndex))) DatetimeSeries]{
...
}

@subsubsection[#:tag "datetime-series-iref"]{datetime-series-iref}
@defproc[(datetime-series-iref (arg0 DatetimeSeries) (arg1 (Listof Index))) (Listof RFDatetime)]{
...
}

@subsubsection[#:tag "datetime-series-index-ref"]{datetime-series-index-ref}
@defproc[(datetime-series-index-ref (arg0 DatetimeSeries) (arg1 IndexDataType)) (Listof RFDatetime)]{
...
}

@subsubsection[#:tag "datetime-series-loc-multi-index"]{datetime-series-loc-multi-index}
@defproc[(datetime-series-loc-multi-index (arg0 DatetimeSeries) (arg1 (U (Listof String) ListofListofString))) (U RFDatetime DatetimeSeries)]{
...
}

@subsubsection[#:tag "datetime-series-loc-boolean"]{datetime-series-loc-boolean}
@defproc[(datetime-series-loc-boolean (arg0 DatetimeSeries) (arg1 (Listof Boolean))) (U RFDatetime DatetimeSeries)]{
...
}

@subsubsection[#:tag "datetime-series-loc"]{datetime-series-loc}
@defproc[(datetime-series-loc (arg0 DatetimeSeries) (arg1 (U Label (Listof Label) (Listof Boolean)))) (U RFDatetime DatetimeSeries)]{
...
}

@subsubsection[#:tag "datetime-series-iloc"]{datetime-series-iloc}
@defproc[(datetime-series-iloc (arg0 DatetimeSeries) (arg1 (U Index (Listof Index)))) (U RFDatetime DatetimeSeries)]{
...
}

@subsubsection[#:tag "datetime-series-iloc-range"]{datetime-series-iloc-range}
@defproc[(datetime-series-iloc-range (arg0 DatetimeSeries) (arg1 Index) (arg2 Index)) DatetimeSeries]{
...
}

@subsubsection[#:tag "datetime-series-label-ref"]{datetime-series-label-ref}
@defproc[(datetime-series-label-ref (arg0 DatetimeSeries) (arg1 Label)) (Listof RFDatetime)]{
...
}

@subsubsection[#:tag "datetime-series-range"]{datetime-series-range}
@defproc[(datetime-series-range (arg0 DatetimeSeries) (arg1 Index) (arg2 Index)) (Vectorof RFDatetime)]{
...
}

@subsubsection[#:tag "datetime-series-length"]{datetime-series-length}
@defproc[(datetime-series-length (arg0 DatetimeSeries)) Index]{
...
}

@subsubsection[#:tag "datetime-series-referencer"]{datetime-series-referencer}
@defproc[(datetime-series-referencer (arg0 DatetimeSeries)) (Index -> RFDatetime)]{
...
}

@subsubsection[#:tag "datetime-series-data"]{datetime-series-data}
@defproc[(datetime-series-data (arg0 DatetimeSeries)) (Vectorof RFDatetime)]{
...
}

@subsubsection[#:tag "datetime-series-index"]{datetime-series-index}
@defproc[(datetime-series-index (arg0 DatetimeSeries)) (U False RFIndex)]{
...
}

@subsubsection[#:tag "datetime-series-null-value"]{datetime-series-null-value}
@defproc[(datetime-series-null-value (arg0 DatetimeSeries)) RFNULL]{
...
}

@subsubsection[#:tag "datetime-series-datetime-null-value"]{datetime-series-datetime-null-value}
@defproc[(datetime-series-datetime-null-value (arg0 DatetimeSeries)) Datetime]{
...
}

@subsubsection[#:tag "in-datetime-series"]{in-datetime-series}
@defproc[(in-datetime-series (arg0 Datetime) (arg1 DatetimeSeries)) Boolean]{
...
}

@subsubsection[#:tag "map/datetime-series-data"]{map/datetime-series-data}
@defproc[(map/datetime-series-data (arg0 DatetimeSeries) (arg1 (Datetime -> Datetime))) DatetimeSeries]{
...
}

@subsubsection[#:tag "datetime-range"]{datetime-range}
@defproc[(datetime-range (arg0 Datetime) (arg1 (Option Symbol)) (arg2 (Option Index)) (arg3 (Option Datetime))) (Listof RFDatetime)]{
...
}

@subsubsection[#:tag "bop/datetime-series"]{bop/datetime-series}
@defproc[(bop/datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries) (arg2 (Datetime Datetime -> Datetime))) DatetimeSeries]{
...
}

@subsubsection[#:tag "comp/datetime-series"]{comp/datetime-series}
@defproc[(comp/datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries) (arg2 (Datetime Datetime -> Boolean))) BSeries]{
...
}

@subsubsection[#:tag "+/datetime-series"]{+/datetime-series}
@defproc[(+/datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries)) DatetimeSeries]{
...
}

@subsubsection[#:tag "-/datetime-series"]{-/datetime-series}
@defproc[(-/datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries)) DatetimeSeries]{
...
}

@subsubsection[#:tag ">/datetime-series"]{>/datetime-series}
@defproc[(>/datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries)) BSeries]{
...
}

@subsubsection[#:tag "</datetime-series"]{</datetime-series}
@defproc[(</datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries)) BSeries]{
...
}

@subsubsection[#:tag ">=/datetime-series"]{>=/datetime-series}
@defproc[(>=/datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries)) BSeries]{
...
}

@subsubsection[#:tag "<=/datetime-series"]{<=/datetime-series}
@defproc[(<=/datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries)) BSeries]{
...
}

@subsubsection[#:tag "=/datetime-series"]{=/datetime-series}
@defproc[(=/datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries)) BSeries]{
...
}

@subsubsection[#:tag "!=/datetime-series"]{!=/datetime-series}
@defproc[(!=/datetime-series (arg0 DatetimeSeries) (arg1 DatetimeSeries)) BSeries]{
...
}

@subsubsection[#:tag "datetime-series-print"]{datetime-series-print}
@defproc[(datetime-series-print (arg0 DatetimeSeries) (arg1 (#:output-port Output-Port))) Void]{
...
}

@subsubsection[#:tag "datetime-series-groupby"]{datetime-series-groupby}
@defproc[(datetime-series-groupby (arg0 DatetimeSeries) (arg1 (#:by-value Boolean))) GroupHash]{
...
}

@subsubsection[#:tag "set-DatetimeSeries-null-value"]{set-DatetimeSeries-null-value}
@defproc[(set-DatetimeSeries-null-value (arg0 DatetimeSeries) (arg1 RFNULL)) DatetimeSeries]{
...
}

@subsubsection[#:tag "set-DatetimeSeries-datetime-null-value-inplace"]{set-DatetimeSeries-datetime-null-value-inplace}
@defproc[(set-DatetimeSeries-datetime-null-value-inplace (arg0 DatetimeSeries) (arg1 Datetime)) Void]{
...
}

@subsubsection[#:tag "Datetime Series Builder"]{Datetime Series Builder}
@codeblock|{
(struct-out DatetimeSeriesBuilder)

(struct: DatetimeSeriesBuilder ([index  : Index]
			 [data : (Vectorof RFDatetime)]) #:mutable)
}|

@subsubsection[#:tag "new-DatetimeSeriesBuilder"]{new-DatetimeSeriesBuilder}
@defproc[(new-DatetimeSeriesBuilder (arg0 (U Void Index))) DatetimeSeriesBuilder]{
...
}

@subsubsection[#:tag "append-DatetimeSeriesBuilder"]{append-DatetimeSeriesBuilder}
@defproc[(append-DatetimeSeriesBuilder (arg0 DatetimeSeriesBuilder) (arg1 (U RFDatetime String))) Void]{
...
}

@subsubsection[#:tag "complete-DatetimeSeriesBuilder"]{complete-DatetimeSeriesBuilder}
@defproc[(complete-DatetimeSeriesBuilder (arg0 DatetimeSeriesBuilder)) DatetimeSeries]{
...
}

@subsection[#:style 'toc]{Date Series}

@"\U2190" Series consisting of the native Racket date struct.

@(link "https://docs.racket-lang.org/reference/time.html#%28def._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._date%29%29")

@codeblock|{
#|
(struct	 date	 
(second
 	minute
 	hour
 	day
 	month
 	year
 	week-day
 	year-day
 	dst?
 	time-zone-offset)
  #:extra-constructor-name make-date
  #:transparent)
  second : (integer-in 0 60)
  minute : (integer-in 0 59)
  hour : (integer-in 0 23)
  day : (integer-in 1 31)
  month : (integer-in 1 12)
  year : exact-integer?
  week-day : (integer-in 0 6)
  year-day : (integer-in 0 365)
  dst? : boolean?
  time-zone-offset : exact-integer?
|#

(define-type RFDate (U date RFNoData))
(define-predicate RFDate? RFDate)
(define DEFAULT_NULL_VALUE : date (current-date))
(struct DateSeries
  ([index : (Option RFIndex)]
   [data : (Vectorof RFDate)]
   ; when the null-value is not a fixnum?, the fixnum-null-value is set to 0
   [null-value : RFNULL]
   ; needed for type checking purposes and to do proper arithmetic operations in numeric series
   [date-null-value : date])
  #:mutable
  #:transparent)
}|

@local-table-of-contents[]

@subsubsection[#:tag "new-DateSeries"]{new-DateSeries}
@defproc[(new-DateSeries (arg0 (U (Vectorof date) (Sequenceof date) (Sequenceof RFDate))) (arg1 (#:index (Option (U (Listof IndexDataType) RFIndex)))) (arg2 (#:fill-null RFNULL))) DateSeries]{
...
}

@subsubsection[#:tag "set-DateSeries-index"]{set-DateSeries-index}
@defproc[(set-DateSeries-index (arg0 DateSeries) (arg1 (U (Listof IndexDataType) RFIndex))) DateSeries]{
...
}

@subsubsection[#:tag "date-series-iref"]{date-series-iref}
@defproc[(date-series-iref (arg0 DateSeries) (arg1 (Listof Index))) (Listof RFDate)]{
...
}

@subsubsection[#:tag "date-series-index-ref"]{date-series-index-ref}
@defproc[(date-series-index-ref (arg0 DateSeries) (arg1 IndexDataType)) (Listof RFDate)]{
...
}

@subsubsection[#:tag "date-series-loc-multi-index"]{date-series-loc-multi-index}
@defproc[(date-series-loc-multi-index (arg0 DateSeries) (arg1 (U (Listof String) ListofListofString))) (U RFDate DateSeries)]{
...
}

@subsubsection[#:tag "date-series-loc-boolean"]{date-series-loc-boolean}
@defproc[(date-series-loc-boolean (arg0 DateSeries) (arg1 (Listof Boolean))) (U RFDate DateSeries)]{
...
}

@subsubsection[#:tag "date-series-loc"]{date-series-loc}
@defproc[(date-series-loc (arg0 DateSeries) (arg1 (U Label (Listof Label) (Listof Boolean)))) (U RFDate DateSeries)]{
...
}

@subsubsection[#:tag "date-series-iloc"]{date-series-iloc}
@defproc[(date-series-iloc (arg0 DateSeries) (arg1 (U Index (Listof Index)))) (U RFDate DateSeries)]{
...
}

@subsubsection[#:tag "date-series-iloc-range"]{date-series-iloc-range}
@defproc[(date-series-iloc-range (arg0 DateSeries) (arg1 Index) (arg2 Index)) DateSeries]{
...
}

@subsubsection[#:tag "date-series-label-ref"]{date-series-label-ref}
@defproc[(date-series-label-ref (arg0 DateSeries) (arg1 Label)) (Listof RFDate)]{
...
}

@subsubsection[#:tag "date-series-range"]{date-series-range}
@defproc[(date-series-range (arg0 DateSeries) (arg1 Index) (arg2 Index)) (Vectorof RFDate)]{
...
}

@subsubsection[#:tag "date-series-length"]{date-series-length}
@defproc[(date-series-length (arg0 DateSeries)) Index]{
...
}

@subsubsection[#:tag "date-series-referencer"]{date-series-referencer}
@defproc[(date-series-referencer (arg0 DateSeries)) (Index -> RFDate)]{
...
}

@subsubsection[#:tag "date-series-data"]{date-series-data}
@defproc[(date-series-data (arg0 DateSeries)) (Vectorof RFDate)]{
...
}

@subsubsection[#:tag "date-series-index"]{date-series-index}
@defproc[(date-series-index (arg0 DateSeries)) (U False RFIndex)]{
...
}

@subsubsection[#:tag "in-date-series"]{in-date-series}
@defproc[(in-date-series (arg0 date) (arg1 DateSeries)) Boolean]{
...
}

@subsubsection[#:tag "date-series-null-value"]{date-series-null-value}
@defproc[(date-series-null-value (arg0 DateSeries)) RFNULL]{
...
}

@subsubsection[#:tag "date-series-date-null-value"]{date-series-date-null-value}
@defproc[(date-series-date-null-value (arg0 DateSeries)) date]{
...
}

@subsubsection[#:tag "map/date-series-data"]{map/date-series-data}
@defproc[(map/date-series-data (arg0 DateSeries) (arg1 (date -> date))) DateSeries]{
...
}

@subsubsection[#:tag "date-range"]{date-range}
@defproc[(date-range (arg0 date) (arg1 (Option Symbol)) (arg2 (Option Index)) (arg3 (Option date))) (Listof RFDate)]{
...
}

@subsubsection[#:tag "bop/date-series"]{bop/date-series}
@defproc[(bop/date-series (arg0 DateSeries) (arg1 DateSeries) (arg2 (date date -> date))) DateSeries]{
...
}

@subsubsection[#:tag "comp/date-series"]{comp/date-series}
@defproc[(comp/date-series (arg0 DateSeries) (arg1 DateSeries) (arg2 (date date -> Boolean))) BSeries]{
...
}

@subsubsection[#:tag "+/date-series"]{+/date-series}
@defproc[(+/date-series (arg0 DateSeries) (arg1 DateSeries)) DateSeries]{
...
}

@subsubsection[#:tag "-/date-series"]{-/date-series}
@defproc[(-/date-series (arg0 DateSeries) (arg1 DateSeries)) DateSeries]{
...
}

@subsubsection[#:tag ">/date-series"]{>/date-series}
@defproc[(>/date-series (arg0 DateSeries) (arg1 DateSeries)) BSeries]{
...
}

@subsubsection[#:tag "</date-series"]{</date-series}
@defproc[(</date-series (arg0 DateSeries) (arg1 DateSeries)) BSeries]{
...
}

@subsubsection[#:tag ">=/date-series"]{>=/date-series}
@defproc[(>=/date-series (arg0 DateSeries) (arg1 DateSeries)) BSeries]{
...
}

@subsubsection[#:tag "<=/date-series"]{<=/date-series}
@defproc[(<=/date-series (arg0 DateSeries) (arg1 DateSeries)) BSeries]{
...
}

@subsubsection[#:tag "=/date-series"]{=/date-series}
@defproc[(=/date-series (arg0 DateSeries) (arg1 DateSeries)) BSeries]{
...
}

@subsubsection[#:tag "!=/date-series"]{!=/date-series}
@defproc[(!=/date-series (arg0 DateSeries) (arg1 DateSeries)) BSeries]{
...
}

@subsubsection[#:tag "date-series-print"]{date-series-print}
@defproc[(date-series-print (arg0 DateSeries) (arg1 (#:output-port Output-Port))) Void]{
...
}

@subsubsection[#:tag "date-series-groupby"]{date-series-groupby}
@defproc[(date-series-groupby (arg0 DateSeries) (arg1 (#:by-value Boolean))) GroupHash]{
...
}

@subsubsection[#:tag "set-DateSeries-null-value"]{set-DateSeries-null-value}
@defproc[(set-DateSeries-null-value (arg0 DateSeries) (arg1 RFNULL)) DateSeries]{
...
}

@subsubsection[#:tag "set-DateSeries-date-null-value-inplace"]{set-DateSeries-date-null-value-inplace}
@defproc[(set-DateSeries-date-null-value-inplace (arg0 DateSeries) (arg1 date)) Void]{
...
}

@subsubsection[#:tag "derive-date-value"]{derive-date-value}
@defproc[(derive-date-value (arg0 DateSeries) (arg1 RFDate)) date]{
...
}

@subsubsection[#:tag "Date Series Builder"]{Date Series Builder}
@codeblock|{
  (struct-out DateSeriesBuilder)

  (struct: DateSeriesBuilder ([index  : Index]
  [data : (Vectorof RFDate)]) #:mutable)
}|

@subsubsection[#:tag "new-DateSeriesBuilder"]{new-DateSeriesBuilder}
@defproc[(new-DateSeriesBuilder (arg0 (U Void Index))) DateSeriesBuilder]{
...
}

@subsubsection[#:tag "append-DateSeriesBuilder"]{append-DateSeriesBuilder}
@defproc[(append-DateSeriesBuilder (arg0 DateSeriesBuilder) (arg1 (U RFDate String))) Void]{
...
}

@subsubsection[#:tag "complete-DateSeriesBuilder"]{complete-DateSeriesBuilder}
@defproc[(complete-DateSeriesBuilder (arg0 DateSeriesBuilder)) DateSeries]{
...
}

@subsection[#:tag "Series Convenience Methods"]{Series Convenience Methods}
@subsubsection[#:tag "new-series"]{new-series}
@defproc[(new-series (arg0 (Sequenceof Any)) (arg1 (#:index (Option (U (Listof IndexDataType) RFIndex))))) Series]{
...
}

@subsubsection[#:tag "set-series-index"]{set-series-index}
@defproc[(set-series-index (arg0 Series) (arg1 (U (Listof IndexDataType) RFIndex))) Series]{
...
}

@subsubsection[#:tag "series-set-null-value"]{series-set-null-value}
@defproc[(series-set-null-value (arg0 Series) (arg1 GenericType)) Series]{
...
}

@subsubsection[#:tag "series-groupby"]{series-groupby}
@defproc[(series-groupby (arg0 Series) (arg1 (#:by-value Boolean))) GroupHash]{
...
}

@subsubsection[#:tag "series-complete"]{series-complete}
@defproc[(series-complete (arg0 SeriesBuilder)) Series]{
...
}

@subsubsection[#:tag "series-data"]{series-data}
@defproc[(series-data (arg0 Series)) (U (Vectorof GenericType) FlVector (Vectorof Symbol) (Vectorof RFFixnum) (Vectorof Boolean) (Vectorof RFDatetime) (Vectorof RFDate))]{
...
}

@subsubsection[#:tag "series-iref"]{series-iref}
@defproc[(series-iref (arg0 Series) (arg1 Index)) Any]{
...
}

@subsubsection[#:tag "series-index-ref"]{series-index-ref}
@defproc[(series-index-ref (arg0 Series) (arg1 IndexDataType)) Any]{
...
}

@subsubsection[#:tag "series-referencer"]{series-referencer}
@defproc[(series-referencer (arg0 Series)) (-> Index Any)]{
...
}

@subsubsection[#:tag "series-loc-boolean"]{series-loc-boolean}
@defproc[(series-loc-boolean (arg0 Series) (arg1 (Listof Boolean))) (U Any Series)]{
...
}

@subsubsection[#:tag "series-loc"]{series-loc}
@defproc[(series-loc (arg0 Series) (arg1 (U Label (Listof Label) (Listof Boolean)))) (U Any Series)]{
...
}

@subsubsection[#:tag "series-iloc"]{series-iloc}
@defproc[(series-iloc (arg0 Series) (arg1 (U Index (Listof Index)))) (U Any Series)]{
...
}

@subsubsection[#:tag "get-series-index"]{get-series-index}
@defproc[(get-series-index (arg0 Series)) RFIndex]{
...
}

@subsubsection[#:tag "has-series-index?"]{has-series-index?}
@defproc[(has-series-index? (arg0 Series)) Boolean]{
...
}

@subsubsection[#:tag "in-series"]{in-series}
@defproc[(in-series (arg0 GenericType) (arg1 Series)) Boolean]{
...
}

@subsubsection[#:tag "indexable-series->index"]{indexable-series->index}
@defproc[(indexable-series->index (arg0 IndexableSeries)) RFIndex]{
...
}

@subsubsection[#:tag "series-data->indexable-sequence"]{series-data->indexable-sequence}
@defproc[(series-data->indexable-sequence (arg0 (U (Vectorof Any) (Vectorof Boolean) (Vectorof RFDatetime) (Vectorof RFFixnum) (Vectorof Symbol) (Vectorof RFDate) FlVector))) (Sequenceof IndexDataType)]{
...
}

@subsubsection[#:tag "SeriesDescription"]{SeriesDescription}
@codeblock|{
(provide
 (struct-out SeriesDescription)
 Series Series? SeriesList SeriesList? SeriesType IndexableSeries IndexableSeries?)

(define-type Series (U GenSeries NSeries CSeries ISeries BSeries DatetimeSeries DateSeries))

(define-predicate Series? Series)

(define-type SeriesList (Listof Series))

(define-predicate SeriesList? SeriesList)

(define-type SeriesType (U 'GenericSeries 'NumericSeries 'CategoricalSeries 'IntegerSeries 'BooleanSeries 'DatetimeSeries 'DateSeries))

(define-type IndexableSeries (U GenSeries CSeries ISeries NSeries DatetimeSeries DateSeries))

(define-predicate IndexableSeries? IndexableSeries)

(struct: SeriesDescription ([name : Label]
                            [type : SeriesType]
                            [length : Integer]) #:transparent)

}|

@subsubsection[#:tag "series-description"]{series-description}
@defproc[(series-description (arg0 Label) (arg1 Series)) SeriesDescription]{
...
}

@subsubsection[#:tag "series-type"]{series-type}
@defproc[(series-type (arg0 Series)) SeriesType]{
...
}

@subsubsection[#:tag "series-length"]{series-length}
@defproc[(series-length (arg0 Series)) Index]{
...
}

@; ======================================================================

@section[#:tag "Indexing"]{Indexing}

The axis labeling information in RacketFrame objects serves many purposes.
@itemlist[
@item{
Identifies data (i.e. provides metadata) using known indicators, important for analysis, visualization, and interactive console display.
}
@item{
Enables automatic and explicit data alignment.
}
@item{
Allows intuitive getting and setting of subsets of the data set.
}
]

@codeblock|{
(define-type Label Symbol)

; series have the option to set any type of null value
; and be converted to a GenSeries
(define-type RFNULL Any)

(define-predicate Label? Label)

(define-predicate ListofLabel? (Listof Label))

(define-predicate ListofFixnum? (Listof Fixnum))

(define-predicate SetofIndex? (Setof Index))

(define-predicate ListofIndex? (Listof Index))

(define-predicate ListofFlonum? (Listof Flonum))

(define-predicate ListofBoolean? (Listof Boolean))

(define-predicate ListofDatetime? (Listof Datetime))

(define-predicate ListofDate? (Listof Date))

(define-predicate Listofdate? (Listof date))

(define-predicate ListofAny? (Listof Any))

(define-predicate ListofAnyPair? (Listof (Pair Any Any)))

; Map index to a  (Listof Fixnum)
(define-type Labeling (Listof (Pair Label (Listof Index))))

(define-type SIndex (HashTable Label (Listof Index)))

; Range Index
(define-type IIndex (HashTable Fixnum (Listof Index)))

(define-type FIndex (HashTable Flonum (Listof Index)))

(define-type DTIndex (HashTable Datetime (Listof Index)))

(define-type DIndex (HashTable date (Listof Index)))

(define-type IndexDataType (U Label Fixnum Flonum Datetime date))

(define-predicate ListofIndexDataType? (Listof IndexDataType))

(define-predicate SetofIndexDataType? (Setof IndexDataType))

(define-type LabelProjection (U (Listof Label) (Setof Label)))

(define-type ListofIndex (Listof Index))

(define-type ListofListofIndex (Listof (Listof Index)))

(define-predicate ListofListofIndex? (Listof (Listof Index)))

(define-type ListofListofString (Listof (Listof String)))

(define-predicate ListofListofString? (Listof (Listof String)))

(define-predicate LabelProjection? LabelProjection)

(struct LabelIndex ([index : SIndex]) #:mutable #:transparent)
(struct FixnumIndex ([index : IIndex]) #:mutable #:transparent)
(struct FlonumIndex ([index : FIndex]) #:mutable #:transparent)
(struct DatetimeIndex ([index : DTIndex]) #:mutable #:transparent)
(struct DateIndex ([index : DIndex]) #:mutable #:transparent)

(define-type IndexType (U SIndex IIndex FIndex DTIndex DIndex))

; add RangeIndex later
(define-type RFIndex (U LabelIndex FixnumIndex FlonumIndex DatetimeIndex DateIndex))

(define-predicate RFIndex? RFIndex)

(struct RFNoData () #:transparent)
}|

@subsection[#:style 'toc]{Index}

@subsubsection[#:tag "is-labeled?"]{is-labeled?}
@defproc[(is-labeled? (arg0 LabelIndex)) Boolean]{
...
}

@subsubsection[#:tag "label-sort-positional"]{label-sort-positional}
@defproc[(label-sort-positional (arg0 LabelIndex) (arg1 (#:project LabelProjection))) Labeling]{
...
}

@subsubsection[#:tag "label-sort-lexical"]{label-sort-lexical}
@defproc[(label-sort-lexical (arg0 LabelIndex)) Labeling]{
...
}

@subsubsection[#:tag "build-index-from-sequence"]{build-index-from-sequence}
@defproc[(build-index-from-sequence (arg0 (Sequenceof IndexDataType))) RFIndex]{
...
}

@subsubsection[#:tag "build-index-from-list"]{build-index-from-list}
@defproc[(build-index-from-list (arg0 (Listof IndexDataType))) RFIndex]{
...
}

@subsubsection[#:tag "build-data-vector-from-sequence"]{build-data-vector-from-sequence}
@defproc[(build-data-vector-from-sequence (arg0 (Sequenceof GenericType))) (Vectorof GenericType)]{
...
}

@subsubsection[#:tag "labeling"]{labeling}
@defproc[(labeling (arg0 LabelIndex)) (Listof (Pair Label (Listof Index)))]{
...
}

@subsubsection[#:tag "get-index"]{get-index}
@defproc[(get-index (arg0 RFIndex) (arg1 IndexDataType)) (Listof Index)]{
...
}

@subsubsection[#:tag "extract-index"]{extract-index}
@defproc[(extract-index (arg0 RFIndex)) IndexType]{
...
}

@subsubsection[#:tag "is-indexed?"]{is-indexed?}
@defproc[(is-indexed? (arg0 RFIndex)) Boolean]{
...
}

@subsubsection[#:tag "index-keys"]{index-keys}
@defproc[(index-keys (arg0 RFIndex)) (Listof IndexDataType)]{
...
}

@subsubsection[#:tag "index-idxes"]{index-idxes}
@defproc[(index-idxes (arg0 RFIndex)) (Listof Index)]{
...
}

@subsubsection[#:tag "index-keys-intersection"]{index-keys-intersection}
@defproc[(index-keys-intersection (arg0 (Listof RFIndex))) (Setof IndexDataType)]{
...
}

@subsection[#:style 'toc]{MultiIndex}

@subsubsection[#:tag "build-multi-index-from-list"]{build-multi-index-from-list}
@defproc[(build-multi-index-from-list (arg0 (Listof (Listof GenericType)))) LabelIndex]{
...
}

@subsection[#:style 'toc]{DatetimeIndex}

@; ======================================================================
@section{DataFrames}

@local-table-of-contents[]

@subsection[#:style 'toc]{DataFrame}

@local-table-of-contents[]

@codeblock|{
;; Data Structure Definitions

(define-type Column (Pair Label Series))
(define-type Columns (Listof Column))

(define-predicate Column? Column)

(define-predicate Columns? Columns)

;; A DataFrame is map of series.
(struct: DataFrame LabelIndex
  ([series : (Vectorof Series)]                    
   [index : (Option RFIndex)]))

(struct: DataFrameDescription ([dimensions : Dim]
                               [series : (Listof SeriesDescription)]))
}|

@subsubsection[#:tag "column"]{column}
@defproc[(column (arg0 Label) (arg1 Series)) Column]{
...
}

@subsubsection[#:tag "column-heading"]{column-heading}
@defproc[(column-heading (arg0 Column)) Label]{
...
}

@subsubsection[#:tag "column-series"]{column-series}
@defproc[(column-series (arg0 Column)) Series]{
...
}

@subsubsection[#:tag "data-frame-series"]{data-frame-series}
@defproc[(data-frame-series (arg0 DataFrame)) (Vectorof Series)]{
...
}

@subsubsection[#:tag "data-frame-index"]{data-frame-index}
@defproc[(data-frame-index (arg0 DataFrame)) (Option RFIndex)]{
...
}

@subsubsection[#:tag "data-frame-series-ref"]{data-frame-series-ref}
@defproc[(data-frame-series-ref (arg0 DataFrame) (arg1 Label)) Series]{
...
}

@subsubsection[#:tag "data-frame-rename"]{data-frame-rename}
@defproc[(data-frame-rename (arg0 DataFrame) (arg1 Label) (arg2 Label)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-project"]{data-frame-project}
@defproc[(data-frame-project (arg0 DataFrame) (arg1 LabelProjection)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-drop"]{data-frame-drop}
@defproc[(data-frame-drop (arg0 DataFrame) (arg1 Label)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-remove"]{data-frame-remove}
@defproc[(data-frame-remove (arg0 DataFrame) (arg1 LabelProjection)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-explode"]{data-frame-explode}
@defproc[(data-frame-explode (arg0 DataFrame) (arg1 (#:project LabelProjection))) Columns]{
...
}

@subsubsection[#:tag "data-frame-replace"]{data-frame-replace}
@defproc[(data-frame-replace (arg0 DataFrame) (arg1 Column)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-extend"]{data-frame-extend}
@defproc[(data-frame-extend (arg0 DataFrame) (arg1 (U Column Columns DataFrame))) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-description"]{data-frame-description}
@defproc[(data-frame-description (arg0 DataFrame) (arg1 (#:project LabelProjection))) DataFrameDescription]{
...
}

@subsubsection[#:tag "show-data-frame-description"]{show-data-frame-description}
@defproc[(show-data-frame-description (arg0 DataFrameDescription)) Void]{
...
}

@subsubsection[#:tag "data-frame-set-index"]{data-frame-set-index}
@defproc[(data-frame-set-index (arg0 DataFrame) (arg1 (U (Sequenceof IndexDataType) RFIndex Series))) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-loc"]{data-frame-loc}
@defproc[(data-frame-loc (arg0 DataFrame) (arg1 (U Label (Listof Label) (Listof Boolean))) (arg2 LabelProjection)) (U Series DataFrame)]{
...
}

@subsubsection[#:tag "data-frame-iloc"]{data-frame-iloc}
@defproc[(data-frame-iloc (arg0 DataFrame) (arg1 (U Index (Listof Index))) (arg2 (U Index (Listof Index)))) (U Series DataFrame)]{
...
}

@subsubsection[#:tag "data-frame-iloc-label"]{data-frame-iloc-label}
@defproc[(data-frame-iloc-label (arg0 DataFrame) (arg1 (U Index (Listof Index))) (arg2 LabelProjection)) (U Series DataFrame)]{
...
}

@subsubsection[#:tag "data-frame-labels"]{data-frame-labels}
@defproc[(data-frame-labels (arg0 DataFrame)) (Listof (Pair Symbol (Listof Index)))]{
...
}

@subsubsection[#:tag "data-frame-series-names"]{data-frame-series-names}
@defproc[(data-frame-series-names (arg0 DataFrame)) (Listof Symbol)]{
...
}

@subsubsection[#:tag "projection-set"]{projection-set}
@defproc[(projection-set (arg0 LabelProjection)) (Setof Label)]{
...
}

@subsubsection[#:tag "data-frame-all-labels-projection-set"]{data-frame-all-labels-projection-set}
@defproc[(data-frame-all-labels-projection-set (arg0 DataFrame)) (Setof Label)]{
...
}

@subsubsection[#:tag "data-frame-contains?"]{data-frame-contains?}
@defproc[(data-frame-contains? (arg0 DataFrame) (arg1 (Listof Label))) Boolean]{
...
}

@subsubsection[#:tag "data-frame-contains/any?"]{data-frame-contains/any?}
@defproc[(data-frame-contains/any? (arg0 DataFrame) (arg1 (Listof Label))) Boolean]{
...
}

@subsubsection[#:tag "data-frame-get-series"]{data-frame-get-series}
@defproc[(data-frame-get-series (arg0 DataFrame) (arg1 (U Label (Listof Label)))) (U Series (Listof Series))]{
...
}

@subsubsection[#:tag "data-frame-row-count"]{data-frame-row-count}
@defproc[(data-frame-row-count (arg0 DataFrame)) Index]{
...
}

@subsubsection[#:tag "data-frame-column-count"]{data-frame-column-count}
@defproc[(data-frame-column-count (arg0 DataFrame)) Index]{
...
}

@subsubsection[#:tag "in-data-frame"]{in-data-frame}
@defproc[(in-data-frame (arg0 GenericType) (arg1 DataFrame)) Boolean]{
...
}

@subsubsection[#:tag "data-frame+"]{data-frame+}
@defproc[(data-frame+ (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-"]{data-frame-}
@defproc[(data-frame- (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame*"]{data-frame*}
@defproc[(data-frame* (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame/"]{data-frame/}
@defproc[(data-frame/ (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame%"]{data-frame%}
@defproc[(data-frame% (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-r"]{data-frame-r}
@defproc[(data-frame-r (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame="]{data-frame=}
@defproc[(data-frame= (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame!="]{data-frame!=}
@defproc[(data-frame!= (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame>="]{data-frame>=}
@defproc[(data-frame>= (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame<="]{data-frame<=}
@defproc[(data-frame<= (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame>"]{data-frame>}
@defproc[(data-frame> (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame<"]{data-frame<}
@defproc[(data-frame< (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-abs"]{data-frame-abs}
@defproc[(data-frame-abs (arg0 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-filter"]{data-frame-filter}
@defproc[(data-frame-filter (arg0 DataFrame) (arg1 BSeries)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-example-usage"]{Example Usage}
@defproc[#:link-target? #f
 (new-data-frame [columns Columns])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
   ;******************
  ;data-frame-integer
  ;******************
  ; will define parse to automatically build this columns structure
  (define columns-integer
  (list 
  (cons 'col1 (new-ISeries (fxvector 1 2 3 4)
  #:index (build-index-from-list (list 'a 'b 'c 'd))))
  (cons 'col2 (new-ISeries (fxvector 5 6 7 8)
  #:index (build-index-from-list (list 'e 'f 'g 'h))))
  (cons 'col3 (new-ISeries (fxvector 9 10 11 12)
  #:index (build-index-from-list (list 'i 'j 'k 'l))))))

  ; create new data-frame-integer
  (define data-frame-integer (new-data-frame columns-integer))
  }|

@defproc[#:link-target? #f
 (data-frame-rename [df DataFrame] [col Label] [new-col Label])
DataFrame?]{
 This function consumes a DataFrame and two labels. It locates
 the index of the column in the DataFrame LabelIndex and creates
 a new LabelIndex with the new column name mapped to this index.
 Then a new DataFrame is created and returned.
}

@codeblock|{
    (data-frame-rename)
  }|

@defproc[#:link-target? #f
 (data-frame-drop [df DataFrame] [col-name Label])
DataFrame?]{
 This function consumes a DataFrame and a Label for the column
 to drop from the DataFrame. Using the data-frame-explode
 function, this column is filtered out of the DataFrame, and a
 new DataFrame is returned.
}

@codeblock|{
    (data-frame-drop)
  }|

@defproc[#:link-target? #f
 (data-frame-drop [df DataFrame] [col-name Label])
Series?]{
 This function consumes a DataFrame and a Symbol representing
 the column name and returns the Series of that column.
}

@codeblock|{
    (data-frame-series)
  }|

@defproc[#:link-target? #f
 (data-frame-names [df DataFrame] [col-name Label])
Series?]{
 This function consumes a DataFrame and returns of Listof
 Symbol representing all the column names.
}

@codeblock|{
    (data-frame-names)
  }|

@defproc[#:link-target? #f
 (data-frame-dim [df DataFrame])
Dim?]{
 This function consumes a DataFrame and calculates the dimensions.
 It does so by calculating the length of a column series, thus
 getting the number of rows and the total number of columns. It
 then stores these two values in the Dim struct and returns it.
}

@codeblock|{
    (data-frame-dim)
  }|

@defproc[#:link-target? #f
 (data-frame-description [df DataFrame] [project LabelProjection])
DataFrameDescription?]{
 This function consumes a DataFrame and an optional LabelProjection
 and constructs a DataFrameDescription struct which contains the
 DataFrame Dim and a list of SeriesDecriptions for each series of
 each column.
}

@codeblock|{
    (data-frame-description)
  }|

@defproc[#:link-target? #f
 (show-data-frame-description [dfd DataFrameDescription])
Void?]{
 This function consumes a DataFrameDescription struct and displays
 the DataFrame Dim and Series Descriptions in formated form.
}

@codeblock|{
    (show-data-frame-description)
  }|

@defproc[#:link-target? #f
 (data-frame-explode [df DataFrame] [project LabelProjection])
Columns?]{
 This function consumes a DataFrame and an optional LabelProjection
 which indicates which columns to project and returns a Listof Column.
 If no LabelProjection is given, all columns are projected. The
 label-sort-positional returns a labeling, which is a (Listof (Pair Label Index)).
 This list is looped through and only the items to project are filtered for.
 In the end an appropriate Listof Column is returned.
}

@codeblock|{
    (data-frame-explode)
  }|

@defproc[#:link-target? #f
 (data-frame-remove [df DataFrame] [project LabelProjection])
DataFrame?]{
 This function consumes a DataFrame and LabelProjection indicating
 which columns to remove from the DataFrame. The column names in
 the DataFrame are put into a set called all-labels. The drop-projection
 is converted to a set as well. The labels to be kept are calculated
 by substracting the drop-projection from all of the possible labels.
 Then the DataFrame is exploded retaining only the columns to keep.
 A new data frame is constructed fomr these column and returned.
}

@codeblock|{
    (data-frame-remove)
  }|

@defproc[#:link-target? #f
 (data-frame-project [df DataFrame] [project LabelProjection])
DataFrame?]{
 This function consumes a DataFrame and LabelProjection and
 creates a new DataFrame only containing the columns to project.
}

@codeblock|{
    (data-frame-project)
  }|

@defproc[#:link-target? #f
 (data-frame-replace [df DataFrame] [col Column])
DataFrame?]{
 This function consumes a DataFrame and Column and replaces
 the old column with the same column heading with this new
 column.
}

@codeblock|{
    (data-frame-replace)
  }|

@defproc[#:link-target? #f
 (data-frame-extend [df DataFrame] [col (U Column Columns DataFrame)])
DataFrame?]{
 This functions consumes a DataFrame and either a Column,
 Listof Column or a DataFrame and extends the given DataFrame.
 If a DataFrame is passed for the second argument it is first
 exploded and appended on to the exploded given data frame. Then
 a new DataFrame is constructed and returned. The other cases
 are self-explanatory.
}

@codeblock|{
    (data-frame-extend)
  }|

@subsection[#:style 'toc]{DataFrame Operations}

@local-table-of-contents[]

@subsubsection[#:tag "data-frame+"]{data-frame+}
@defproc[#:link-target? #f
 (data-frame+ [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
  (define columns-integer-1
  (list 
  (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
  (cons 'col2 (new-ISeries (fxvector 5 6 7 8)))
  (cons 'col3 (new-ISeries (fxvector 9 10 11 12)))
  (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

  (define columns-integer-2
  (list 
  (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
  (cons 'col2 (new-ISeries (fxvector 25 26 27 28)))
  (cons 'col3 (new-ISeries (fxvector 29 30 31 32)))
  (cons 'col4 (new-ISeries (fxvector 1 2 3 4)))))

  ; create new data-frame-integer-1
  (define data-frame-integer-1 (new-data-frame columns-integer-1))

  ; create new data-frame-integer-2
  (define data-frame-integer-2 (new-data-frame columns-integer-2))

  (displayln "data-frame+")

  (data-frame-write-delim data-frame-integer-1)

  (data-frame-write-delim data-frame-integer-2)

  (data-frame-write-delim (data-frame+ data-frame-integer-1 data-frame-integer-2))
  }|

@subsubsection[#:tag "data-frame-"]{data-frame-}
@defproc[#:link-target? #f
 (data-frame- [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
  (define columns-integer-1
  (list 
  (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
  (cons 'col2 (new-ISeries (fxvector 5 6 7 8)))
  (cons 'col3 (new-ISeries (fxvector 9 10 11 12)))
  (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

  (define columns-integer-2
  (list 
  (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
  (cons 'col2 (new-ISeries (fxvector 25 26 27 28)))
  (cons 'col3 (new-ISeries (fxvector 29 30 31 32)))
  (cons 'col4 (new-ISeries (fxvector 1 2 3 4)))))

  ; create new data-frame-integer-1
  (define data-frame-integer-1 (new-data-frame columns-integer-1))

  ; create new data-frame-integer-2
  (define data-frame-integer-2 (new-data-frame columns-integer-2))

  (displayln "data-frame-")

  (data-frame-write-delim data-frame-integer-1)

  (data-frame-write-delim data-frame-integer-2)

  (data-frame-write-delim (data-frame- data-frame-integer-1 data-frame-integer-2))
  }|

@subsubsection[#:tag "data-frame*"]{data-frame*}
@defproc[#:link-target? #f
 (data-frame* [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
  (define columns-integer-1
  (list 
  (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
  (cons 'col2 (new-ISeries (fxvector 5 6 7 8)))
  (cons 'col3 (new-ISeries (fxvector 9 10 11 12)))
  (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

  (define columns-integer-2
  (list 
  (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
  (cons 'col2 (new-ISeries (fxvector 25 26 27 28)))
  (cons 'col3 (new-ISeries (fxvector 29 30 31 32)))
  (cons 'col4 (new-ISeries (fxvector 1 2 3 4)))))

  ; create new data-frame-integer-1
  (define data-frame-integer-1 (new-data-frame columns-integer-1))

  ; create new data-frame-integer-2
  (define data-frame-integer-2 (new-data-frame columns-integer-2))

  (displayln "data-frame*")

  (data-frame-write-delim data-frame-integer-1)

  (data-frame-write-delim data-frame-integer-2)

  (data-frame-write-delim (data-frame* data-frame-integer-1 data-frame-integer-2))
  }|

@subsubsection[#:tag "data-frame/"]{data-frame/}
@defproc[#:link-target? #f
 (data-frame/ [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
  (define columns-integer-1
  (list 
  (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
  (cons 'col2 (new-ISeries (fxvector 5 6 7 8)))
  (cons 'col3 (new-ISeries (fxvector 9 10 11 12)))
  (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

  (define columns-integer-2
  (list 
  (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
  (cons 'col2 (new-ISeries (fxvector 25 26 27 28)))
  (cons 'col3 (new-ISeries (fxvector 29 30 31 32)))
  (cons 'col4 (new-ISeries (fxvector 1 2 3 4)))))

  ; create new data-frame-integer-1
  (define data-frame-integer-1 (new-data-frame columns-integer-1))

  ; create new data-frame-integer-2
  (define data-frame-integer-2 (new-data-frame columns-integer-2))

  (displayln "data-frame/")

  (data-frame-write-delim data-frame-integer-1)

  (data-frame-write-delim data-frame-integer-2)

  (data-frame-write-delim (data-frame/ data-frame-integer-1 data-frame-integer-2))
  }|

@subsubsection[#:tag "data-frame%"]{data-frame%}
@defproc[#:link-target? #f
 (data-frame% [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@subsubsection[#:tag "data-frame-r"]{data-frame-r}
@defproc[#:link-target? #f
 (data-frame-r [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@subsubsection[#:tag "data-frame="]{data-frame=}
@defproc[#:link-target? #f
 (data-frame= [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@subsubsection[#:tag "data-frame!="]{data-frame!=}
@defproc[#:link-target? #f
 (data-frame!= [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@subsubsection[#:tag "data-frame<"]{data-frame<}
@defproc[#:link-target? #f
 (data-frame< [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@subsubsection[#:tag "data-frame>"]{data-frame>}
@defproc[#:link-target? #f
 (data-frame> [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@subsubsection[#:tag "data-frame<="]{data-frame<=}
@defproc[#:link-target? #f
 (data-frame<= [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@subsubsection[#:tag "data-frame>="]{data-frame>=}
@defproc[#:link-target? #f
 (data-frame>= [dfa DataFrame] [dfb DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@subsubsection[#:tag "data-frame-abs"]{data-frame-abs}
@defproc[#:link-target? #f
 (data-frame-abs [df DataFrame])
DataFrame?]{
Returns a new DataFrame.
}

@subsection[#:style 'toc]{DataFrame Join}

@local-table-of-contents[]
@subsubsection[#:tag "data-frame-join-left"]{data-frame-join-left}
@defproc[(data-frame-join-left (arg0 DataFrame) (arg1 DataFrame) (arg2 (#:on (Listof Symbol)))) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-join-right"]{data-frame-join-right}
@defproc[(data-frame-join-right (arg0 DataFrame) (arg1 DataFrame) (arg2 (#:on (Listof Symbol)))) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-join-inner"]{data-frame-join-inner}
@defproc[(data-frame-join-inner (arg0 DataFrame) (arg1 DataFrame) (arg2 (#:on (Listof Symbol)))) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-join-outer"]{data-frame-join-outer}
@defproc[(data-frame-join-outer (arg0 DataFrame) (arg1 DataFrame) (arg2 (#:on (Listof Symbol)))) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-groupby"]{data-frame-groupby}
@defproc[(data-frame-groupby (arg0 DataFrame) (arg1 (Listof Label))) GroupHash]{
...
}

@subsubsection[#:tag "apply-agg-data-frame"]{apply-agg-data-frame}
@defproc[(apply-agg-data-frame (arg0 Symbol) (arg1 GroupHash)) Series]{
...
}

@subsubsection[#:tag "copy-column-row-error"]{copy-column-row-error}
@defproc[(copy-column-row-error (arg0 Series) (arg1 Integer)) Void]{
...
}

@subsubsection[#:tag "copy-column-row"]{copy-column-row}
@defproc[(copy-column-row (arg0 (Vectorof Series)) (arg1 (Vectorof SeriesBuilder)) (arg2 Index)) Void]{
...
}

@subsubsection[#:tag "dest-mapping-series-builders"]{dest-mapping-series-builders}
@defproc[(dest-mapping-series-builders (arg0 DataFrameDescription) (arg1 Index)) (Listof SeriesBuilder)]{
...
}

@subsubsection[#:tag "join-column-name"]{join-column-name}
@defproc[(join-column-name (arg0 Column) (arg1 (Setof Label)) (arg2 String)) Symbol]{
...
}

@subsubsection[#:tag "build-multi-index-from-cols"]{build-multi-index-from-cols}
@defproc[(build-multi-index-from-cols (arg0 (U (Listof IndexableSeries) Columns))) SIndex]{
...
}

@subsubsection[#:tag "key-cols-sort-lexical"]{key-cols-sort-lexical}
@defproc[(key-cols-sort-lexical (arg0 Columns)) Columns]{
...
}

@subsubsection[#:tag "key-cols-series"]{key-cols-series}
@defproc[(key-cols-series (arg0 Columns)) (Listof IndexableSeries)]{
...
}

@subsubsection[#:tag "key-fn"]{key-fn}
@defproc[(key-fn (arg0 (Listof IndexableSeries))) (Index -> Key)]{
...
}

@subsubsection[#:tag "Example Usage"]{Example Usage}
@defproc[#:link-target? #f
 (data-frame-join-left [dfa DataFrame] [dfb DataFrame] [on (Listof Symbol)])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
   (define columns-mixed-7
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'c 'd)))
   (cons 'col3 (new-GenSeries (vector 'a 1.5 20 10)))
   (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

(define columns-mixed-8
  (list 
   (cons 'col1 (new-ISeries (fxvector 11 21 31 41)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'g 'd)))
   (cons 'col3 (new-GenSeries (vector 'a 'b 'c 'd)))
   (cons 'col4 (new-ISeries (fxvector 22 22 23 24)))))

; create new data-frame-mixed-7
(define data-frame-mixed-7 (new-data-frame columns-mixed-7))

; create new data-frame-mixed-8
(define data-frame-mixed-8 (new-data-frame columns-mixed-8))

(data-frame-write-delim data-frame-mixed-7)

(data-frame-write-delim data-frame-mixed-8)

(data-frame-write-delim (data-frame-join-left data-frame-mixed-7 data-frame-mixed-8
  #:on (list 'col3)))

;; output ;;
col1	col2	col3	col4
1	a	a	21
2	b	1.5	22
3	c	20	23
4	d	10	24

col1	col2	col3	col4
11	a	a	22
21	b	b	22
31	g	c	23
41	d	d	24

dfa-col1	dfa-col2	dfa-col3	dfa-col4	dfb-col1	dfb-col2	dfb-col4
1		a		a		21		11		a		22
2		b		1.5		22		0		null		0	
3		c		20		23		0		null		0
4		d		10		24		0		null		0
;; output ;;

  }|

@defproc[#:link-target? #f
 (data-frame-join-right [dfa DataFrame] [dfb DataFrame] [on (Listof Symbol)])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
   (define columns-mixed-7
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'c 'd)))
   (cons 'col3 (new-GenSeries (vector 'a 1.5 20 10)))
   (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

(define columns-mixed-8
  (list 
   (cons 'col1 (new-ISeries (fxvector 11 21 31 41)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'g 'd)))
   (cons 'col3 (new-GenSeries (vector 'a 'b 'c 'd)))
   (cons 'col4 (new-ISeries (fxvector 22 22 23 24)))))

; create new data-frame-mixed-7
(define data-frame-mixed-7 (new-data-frame columns-mixed-7))

; create new data-frame-mixed-8
(define data-frame-mixed-8 (new-data-frame columns-mixed-8))

(data-frame-write-delim data-frame-mixed-7)

(data-frame-write-delim data-frame-mixed-8)

(data-frame-write-delim (data-frame-join-right data-frame-mixed-7 data-frame-mixed-8
  #:on (list 'col3)))

;; output ;;
col1	col2	col3	col4
1	a	a	21
2	b	1.5	22
3	c	20	23
4	d	10	24

  col1	col2	col3	col4
11	a	a	22
21	b	b	22
31	g	c	23
41	d	d	24

dfa-col1	dfa-col2	dfa-col4	dfb-col1	dfb-col2	dfb-col3	dfb-col4
1		a		21		11		a		a		22
0		null		0		21		b		b		22
0		null		0		31		g		c		23
0		null		0		41		d		d		24
;; output ;;
  }|

@defproc[#:link-target? #f
 (data-frame-join-inner [dfa DataFrame] [dfb DataFrame] [on (Listof Symbol)])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
   (define columns-mixed-7
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'c 'd)))
   (cons 'col3 (new-GenSeries (vector 'a 1.5 20 10)))
   (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

(define columns-mixed-8
  (list 
   (cons 'col1 (new-ISeries (fxvector 11 21 31 41)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'g 'd)))
   (cons 'col3 (new-GenSeries (vector 'a 'b 'c 'd)))
   (cons 'col4 (new-ISeries (fxvector 22 22 23 24)))))

; create new data-frame-mixed-7
(define data-frame-mixed-7 (new-data-frame columns-mixed-7))

; create new data-frame-mixed-8
(define data-frame-mixed-8 (new-data-frame columns-mixed-8))

(data-frame-write-delim data-frame-mixed-7)

(data-frame-write-delim data-frame-mixed-8)

(data-frame-write-delim (data-frame-join-inner data-frame-mixed-7 data-frame-mixed-8
  #:on (list 'col3)))

;; output ;;
col1	col2	col3	col4
1	a	a	21
2	b	1.5	22
3	c	20	23
4	d	10	24

  col1	col2	col3	col4
11	a	a	22
21	b	b	22
31	g	c	23
41	d	d	24

dfa-col1	dfa-col2	dfa-col3	dfa-col4	dfb-col1	dfb-col2	dfb-col3	dfb-col4
1		a		a		21		11		a		a		22
;; output ;;
  }|

@defproc[#:link-target? #f
 (data-frame-join-outer [dfa DataFrame] [dfb DataFrame] [on (Listof Symbol)])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
(define columns-mixed-7
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'c 'd)))
   (cons 'col3 (new-GenSeries (vector 'a 1.5 20 10)))
   (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

(define columns-mixed-8
  (list 
   (cons 'col1 (new-ISeries (fxvector 11 21 31 41)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'g 'd)))
   (cons 'col3 (new-GenSeries (vector 'a 'b 'c 'd)))
   (cons 'col4 (new-ISeries (fxvector 22 22 23 24)))))

; create new data-frame-mixed-7
(define data-frame-mixed-7 (new-data-frame columns-mixed-7))

; create new data-frame-mixed-8
(define data-frame-mixed-8 (new-data-frame columns-mixed-8))

(data-frame-write-delim data-frame-mixed-7)

(data-frame-write-delim data-frame-mixed-8)

(data-frame-write-delim (data-frame-join-outer data-frame-mixed-7 data-frame-mixed-8
  #:on (list 'col3)))

;; output ;;
col1	col2	col3	col4
1	a	a	21
2	b	1.5	22
3	c	20	23
4	d	10	24

col1	col2	col3	col4
11	a	a	22
21	b	b	22
31	g	c	23
41	d	d	24

dfa-col1	dfa-col2	dfa-col3	dfa-col4	dfb-col1	dfb-col2	dfb-col3	dfb-col4
1		a		a		21		11		a		a		22
2		b		1.5		22		0		null		null		0
3		c		20		23		0		null		null		0
4		d		10		24		0		null		null		0
0		null		null		0		21		b		b		22
0		null		null		0		31		g		c		23
0		null		null		0		41		d		d		24
;; output ;;
  }|


@subsection[#:tag "DataFrame Concatenation"]{DataFrame Concatenation}

@subsubsection[#:tag "data-frame-concat-vertical"]{data-frame-concat-vertical}
@defproc[(data-frame-concat-vertical (arg0 DataFrame) (arg1 DataFrame) (arg2 (#:col (Listof Symbol)))) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-concat-vertical-list"]{data-frame-concat-vertical-list}
@defproc[(data-frame-concat-vertical-list (arg0 (Listof DataFrame))) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-concat-horizontal"]{data-frame-concat-horizontal}
@defproc[(data-frame-concat-horizontal (arg0 DataFrame) (arg1 DataFrame)) DataFrame]{
...
}

@subsubsection[#:tag "data-frame-concat-horizontal-list"]{data-frame-concat-horizontal-list}
@defproc[(data-frame-concat-horizontal-list (arg0 (Listof DataFrame))) DataFrame]{
...
}

@subsubsection[#:tag "Example Usage"]{Example Usage}
@defproc[#:link-target? #f
 (data-frame-concat-vertical [dfa DataFrame] [dfb DataFrame] [col (Listof Symbol)])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
(define columns-mixed-1
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
   (cons 'col2 (new-NSeries (flvector 5.2 6.2 7.2 8.2)))
   (cons 'col3 (new-CSeries (vector 'a 'b 'c 'd)))
   (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

(define columns-mixed-2
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
   (cons 'col2 (new-NSeries (flvector 25.3 26.3 27.3 28.3)))
   (cons 'col3 (new-CSeries (vector 'e 'f 'g 'h)))
   (cons 'col4 (new-ISeries (fxvector 1 2 3 4)))))

; create new data-frame-mixed-1
(define data-frame-mixed-1 (new-data-frame columns-mixed-1))

; create new data-frame-mixed-2
(define data-frame-mixed-2 (new-data-frame columns-mixed-2))

; display created data frames
(data-frame-write-delim data-frame-mixed-1)

(data-frame-write-delim data-frame-mixed-2)

; vertical concat
(data-frame-write-delim (data-frame-concat-vertical data-frame-mixed-1 data-frame-mixed-2))

;; output ;;
col1	col2	col3	col4
1	5.2	a	21
2	6.2	b	22
3	7.2	c	23
4	8.2	d	24

  col1	col2	col3	col4
1	25.3	e	1
2	26.3	f	2
3	27.3	g	3
4	28.3	h	4

col1	col2	col3	col4
1	5.2	a	21
2	6.2	b	22
3	7.2	c	23
4	8.2	d	24
1	25.3	e	1
2	26.3	f	2
3	27.3	g	3
4	28.3	h	4
;; output ;;
  }|

@subsubsection[#:tag "data-frame-concat-horizontal"]{data-frame-concat-horizontal}
@defproc[#:link-target? #f
 (data-frame-concat-horizontal [dfa DataFrame] [dfb DataFrame] [col (Listof Symbol)])
DataFrame?]{
Returns a new DataFrame.
}

@codeblock|{
(define columns-mixed-1
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
   (cons 'col2 (new-NSeries (flvector 5.2 6.2 7.2 8.2)))
   (cons 'col3 (new-CSeries (vector 'a 'b 'c 'd)))
   (cons 'col4 (new-ISeries (fxvector 21 22 23 24)))))

(define columns-mixed-2
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4)))
   (cons 'col2 (new-NSeries (flvector 25.3 26.3 27.3 28.3)))
   (cons 'col3 (new-CSeries (vector 'e 'f 'g 'h)))
   (cons 'col4 (new-ISeries (fxvector 1 2 3 4)))))

; create new data-frame-mixed-1
(define data-frame-mixed-1 (new-data-frame columns-mixed-1))

; create new data-frame-mixed-2
(define data-frame-mixed-2 (new-data-frame columns-mixed-2))

; display created data frames
(data-frame-write-delim data-frame-mixed-1)

(data-frame-write-delim data-frame-mixed-2)

; horizontal concat
(data-frame-write-delim (data-frame-concat-horizontal data-frame-mixed-1 data-frame-mixed-2))

;; output ;;
col1	col2	col3	col4
1	5.2	a	21
2	6.2	b	22
3	7.2	c	23
4	8.2	d	24

col1	col2	col3	col4
1	25.3	e	1
2	26.3	f	2
3	27.3	g	3
4	28.3	h	4

dfa-col1	dfa-col2	dfa-col3	dfa-col4	dfb-col1	dfb-col2	dfb-col3	dfb-col4
1	        5.2		a		21		1		25.3	        e		1
2	        6.2		b		22		2		26.3	        f		2
3	        7.2		c		23		3		27.3	        g		3
4  		8.2		d		24		4		28.3	        h		4   
;; output ;;
  }|

@subsubsection[#:tag "data-frame-groupby"]{data-frame-groupby}
@defproc[#:link-target? #f
 (data-frame-groupby [dfa DataFrame] [by (Listof Symbol)])
GroupHash?]{
Returns a new DataFrame.
}

@codeblock|{
(define columns-integer
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4 2 )))
   (cons 'col2 (new-ISeries (fxvector 5 6 7 8 6)))
   (cons 'col3 (new-ISeries (fxvector 9 10 11 12 17)))
   (cons 'col4 (new-ISeries (fxvector 13 14 15 16 18)))))

; create new data-frame-integer
(define data-frame-integer (new-data-frame columns-integer))

(data-frame-write-delim data-frame-integer)

(data-frame-groupby data-frame-integer (list 'col1))

(data-frame-groupby data-frame-integer (list 'col2))

(data-frame-groupby data-frame-integer (list 'col1 'col2))
            
;; output ;;

col1	col2	col3	col4
1	5	9	13
2	6	10	14
3	7	11	15
4	8	12	16
2	6	17	18

'#hash(("2\t" . (6 17 18 6 10 14))
       ("1\t" . (5 9 13))
       ("4\t" . (8 12 16))
       ("3\t" . (7 11 15)))
       
'#hash(("8\t" . (4 12 16))
       ("7\t" . (3 11 15))
       ("6\t" . (2 17 18 2 10 14))
       ("5\t" . (1 9 13)))
       
'#hash(("4\t8\t" . (12 16))
       ("2\t6\t" . (17 18 10 14))
       ("3\t7\t" . (11 15))
       ("1\t5\t" . (9 13)))
       
;; output ;;
  }|

@subsubsection[#:tag "apply-agg-data-frame"]{apply-agg-data-frame}
@defproc[#:link-target? #f
 (apply-agg-data-frame [function-name Symbol] [group-hash GroupHash])
AggValueHash?]{
Returns a new DataFrame.
}

@codeblock|{
(define columns-integer
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4 2 )))
   (cons 'col2 (new-ISeries (fxvector 5 6 7 8 6)))
   (cons 'col3 (new-ISeries (fxvector 9 10 11 12 17)))
   (cons 'col4 (new-ISeries (fxvector 13 14 15 16 18)))))

; create new data-frame-integer
(define data-frame-integer (new-data-frame columns-integer))

(data-frame-write-delim data-frame-integer)

(displayln "data-frame-groupby aggregate mean")
(apply-agg-data-frame 'mean (data-frame-groupby data-frame-integer (list 'col1 'col2)))

(displayln "data-frame-groupby aggregate count")
(apply-agg-data-frame 'count (data-frame-groupby data-frame-integer (list 'col1 'col2)))
            
;; output ;;

col1	col2	col3	col4
1	5	9	13
2	6	10	14
3	7	11	15
4	8	12	16
2	6	17	18

data-frame-groupby aggregate mean
'#hash(("4\t8\t" . 14) ("1\t5\t" . 11) ("3\t7\t" . 13) ("2\t6\t" . 14.75))
data-frame-groupby aggregate count
'#hash(("4\t8\t" . 2) ("1\t5\t" . 2) ("3\t7\t" . 2) ("2\t6\t" . 4))

;; output ;;
  }|

@section[#:style 'toc]{Loading}

@subsubsection[#:tag "data-frame-write-delim"]{data-frame-write-delim}
@defproc[(data-frame-write-delim (arg0 DataFrame) (arg1 (#:output-port Output-Port)) (arg2 (#:heading Boolean)) (arg3 (#:delim String))) Void]{
...
}

@subsubsection[#:tag "data-frame-write-csv"]{data-frame-write-csv}
@defproc[(data-frame-write-csv (arg0 DataFrame) (arg1 Path-String)) Void]{
...
}

@subsubsection[#:tag "data-frame-write-json"]{data-frame-write-json}
@defproc[(data-frame-write-json (arg0 DataFrame) (arg1 (#:output-port Output-Port))) Void]{
...
}

@subsubsection[#:tag "data-frame-write-json-file"]{data-frame-write-json-file}
@defproc[(data-frame-write-json-file (arg0 DataFrame) (arg1 Path-String)) Void]{
...
}

Loading data from various data sources is important for any DataFrames implementation.
RacketFrames supports delimited files such as CSV (comma-separated value) as well as SQL Lite databases through the Racket SQL Lite driver.

@subsection[#:style 'toc]{Delimitted Files}
Read CSV (comma-separated or other delimitted) file into DataFrame.

@codeblock|{
; read csv
(define salary-data-frame-csv-schema (load-csv-file "../sample-csv/salary.csv" #:schema salary-schema))

(data-frame-head salary-data-frame-csv-schema)

; no schema
(define salary-data-frame-csv-no-schema (load-csv-file "../sample-csv/salary.csv" #:schema #f))

(data-frame-head salary-data-frame-csv-no-schema)

; read delimited
(define random-demographic-data-frame-delimited (load-delimited-file "../sample-csv/random_demographic.csv" "|" #:schema random-demographic-schema))

(data-frame-head random-demographic-data-frame-delimited)

; no schema
(define fruits-data-frame-delimited-no-schema (load-delimited-file "../sample-csv/random_demographic.csv" "|" #:schema #f))

; (data-frame-head (case-> (DataFrame -> Void) (DataFrame (Option Index) -> Void)))
(data-frame-head fruits-data-frame-delimited-no-schema) }|

@subsection[#:style 'toc]{Databases}
@"\U2190" RacketFrames supports SQL Lite 3 databases, but the library can easily be extended to construct DataFrames from other databases.

@codeblock|{
(require typed/db)
            
(define data-frame-from-sql-genres (data-frame-from-sql (sqlite3-connect #:database "db/chinook.db") #f "SELECT * FROM genres" empty))

(data-frame-head data-frame-from-sql-genres) }|

@tabular[#:sep @hspace[1]
(list (list @bold{GenreId} @bold{Name})
(list "1" "Rock")
(list "2" "Jazz")
(list "3" "Metal")
(list "4" "Alternative & P")
(list "5" "Rock And Roll")
(list "6" "Blues")
(list "7" "Latin")
(list "8" "Reggae")
(list "9" "Pop")
(list "10" "Soundtrack"))]

@section[#:style 'toc]{Plotting}

@local-table-of-contents[]

@subsection[#:tag "is-plottable-series"]{is-plottable-series}
@defproc[(is-plottable-series (arg0 Series)) Boolean]{
...
}

@subsection[#:tag "get-series-point-sequence"]{get-series-point-sequence}
@defproc[(get-series-point-sequence (arg0 Series)) (Listof (Listof Real))]{
...
}

@subsection[#:tag "get-column-point-sequence"]{get-column-point-sequence}
@defproc[(get-column-point-sequence (arg0 Column)) (Listof (Listof Real))]{
...
}

@subsection[#:tag "get-series-to-series-point-sequence"]{get-series-to-series-point-sequence}
@defproc[(get-series-to-series-point-sequence (arg0 Series) (arg1 Series)) (Listof (Listof Real))]{
...
}

@subsection[#:tag "get-data-frame-point-sequence"]{get-data-frame-point-sequence}
@defproc[(get-data-frame-point-sequence (arg0 DataFrame)) (Listof (Listof (Listof Real)))]{
...
}

@subsection[#:tag "get-series-list-point-sequence"]{get-series-list-point-sequence}
@defproc[(get-series-list-point-sequence (arg0 SeriesList)) (Listof (Listof (Listof Real)))]{
...
}

@subsection[#:tag "get-columns-point-sequence"]{get-columns-point-sequence}
@defproc[(get-columns-point-sequence (arg0 Columns)) (Listof (Listof (Listof Real)))]{
...
}

@subsection[#:tag "make-points"]{make-points}
@defproc[(make-points (arg0 (Listof (Listof Real)))) renderer2d]{
...
}

@subsection[#:tag "make-lines"]{make-lines}
@defproc[(make-lines (arg0 (Listof (Listof Real)))) renderer2d]{
...
}

@subsection[#:tag "make-scatter-plot"]{make-scatter-plot}
@defproc[(make-scatter-plot (arg0 (U Series (Listof Series) DataFrame Column Columns)) (arg1 (#:x-min Real)) (arg2 (#:x-max Real)) (arg3 (#:y-min Real)) (arg4 (#:y-max Real))) Any]{
...
}

@subsection[#:tag "make-line-plot"]{make-line-plot}
@defproc[(make-line-plot (arg0 (U Series (Listof Series) DataFrame Column Columns)) (arg1 (#:x-min Real)) (arg2 (#:x-max Real)) (arg3 (#:y-min Real)) (arg4 (#:y-max Real))) Any]{
...
}

@subsection[#:tag "make-hist-bin-stacked"]{make-hist-bin-stacked}
@defproc[(make-hist-bin-stacked) HistBinStacked]{
...
}

@subsection[#:tag "get-discrete-hist-data"]{get-discrete-hist-data}
@defproc[(get-discrete-hist-data (arg0 PlotVector)) HistBin]{
...
}

@subsection[#:tag "get-discrete-hist-data-vec"]{get-discrete-hist-data-vec}
@defproc[(get-discrete-hist-data-vec (arg0 PlotVector) (arg1 PlottableSeries)) HistBinStacked]{
...
}

@subsection[#:tag "discrete-histogram-stacked-from-vector"]{discrete-histogram-stacked-from-vector}
@defproc[(discrete-histogram-stacked-from-vector (arg0 PlotVector) (arg1 PlottableSeries)) (Listof renderer2d)]{
...
}

@subsection[#:tag "make-discrete-histogram"]{make-discrete-histogram}
@defproc[(make-discrete-histogram (arg0 (U Series (Listof Series) DataFrame Column Columns))) Any]{
...
}

@subsection[#:tag "make-discrete-histogram-stacked"]{make-discrete-histogram-stacked}
@defproc[(make-discrete-histogram-stacked (arg0 (U Series (Listof Series) DataFrame Column Columns))) Any]{
...
}

@subsection[#:tag "get-index-vector"]{get-index-vector}
@defproc[(get-index-vector (arg0 Series)) PlotVector]{
...
}

@subsection[#:style 'toc]{Example Usage}
@codeblock|{
(displayln "plotting integer series")

(make-scatter-plot (new-ISeries (fxvector 1 2 3 4 5)))

(make-line-plot (new-ISeries (fxvector 1 2 3 4 5))) }|

@(define-runtime-path integer-scatter-line-plots-png "integer_scatter_line_plots.png")
@image[integer-scatter-line-plots-png]

@codeblock|{
(define float-column (cons 'col1 (new-NSeries (flvector 1.5 2.5 3.5 4.5))))

(displayln "plotting float columns")

(make-scatter-plot float-column)

(make-line-plot float-column)}|

@(define-runtime-path float-scatter-line-plots-png "float_scatter_line_plots.png")
@image[float-scatter-line-plots-png]

@codeblock|{
;******************
;data-frame-integer
;******************
(define integer-columns
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4 4)))
   (cons 'col2 (new-ISeries (fxvector 5 6 7 8 24)))
   (cons 'col3 (new-ISeries (fxvector 9 10 11 12 24)))))

; create new data-frame-integer
(define data-frame-integer (new-data-frame integer-columns))

(displayln "plotting integer data-frame")

(make-scatter-plot data-frame-integer)

(displayln "plotting integer columns")

(make-scatter-plot integer-columns)
}|

@(define-runtime-path integer-columns-dataframe-plots-png "integer_columns_dataframe_plots.png")
@image[integer-columns-dataframe-plots-png]

@codeblock|{
;******************
;data-frame-float
;******************
(define float-columns
  (list 
   (cons 'col1 (new-NSeries (flvector 1.5 2.5 3.5 4.5)))
   (cons 'col2 (new-NSeries (flvector 5.5 6.5 7.5 8.5)))
   (cons 'col3 (new-NSeries (flvector 9.5 10.5 11.5 12.5)))))

; create new data-frame-float
(define data-frame-float (new-data-frame float-columns))

(displayln "plotting float data-frame")

(make-scatter-plot data-frame-float)

(displayln "plotting float columns")

(make-scatter-plot float-columns)

(displayln "discrete histogram")

(make-discrete-histogram (new-ISeries (fxvector 1 2 2 3 4 5 5 5)))

(make-discrete-histogram (new-GenSeries (vector 1 2 2 1.5 3 4 5 5 'a 5)))

(make-discrete-histogram float-column)

(make-discrete-histogram integer-columns)

(make-discrete-histogram data-frame-float)

(get-index-vector (new-ISeries (fxvector 1 2 3 4 4)))

(define series-integer-labeled
  (new-ISeries (fxvector 1 2 3 4)
               #:index (list 'a 'b 'c 'd)))

(get-index-vector series-integer-labeled)

(make-discrete-histogram-stacked float-column)

(make-discrete-histogram-stacked float-columns)

;******************
;data-frame-integer
;******************
(define integer-columns-2
  (list 
   (cons 'col1 (new-ISeries (fxvector 1 2 3 4)
                            #:index (build-index-from-list (list 'a 'b 'c 'd))))
   (cons 'col2 (new-ISeries (fxvector 5 6 7 8)
                            #:index (build-index-from-list (list 'e 'f 'g 'h))))
   (cons 'col3 (new-ISeries (fxvector 9 10 11 12)
                            #:index (build-index-from-list (list 'i 'j 'k 'l))))))

; create new data-frame-integer
(define data-frame-integer-2 (new-data-frame integer-columns-2))

(make-discrete-histogram-stacked data-frame-integer-2) }|

@section[#:style 'toc]{Summarising Groups}

Groupby aggregation is a useful functionality to split the rows of the original data set into their own groups based on the Index or a combination of Columns.
With this refactoring, we can apply functions like max(), min(), mean(), median(), first(), last() to obtain summary statistics for each grouping. For instance,
the expression dataframe-groupby(df, #:on '("day")) will split our DataFrame by the column day, thus we would expect 7 groups.

The groupby() function returns a GroupHash object with the Key being a computed unique string describing the group name. The (Listof <DataType>) contains the
list of corresponding axis values of the group name.

@local-table-of-contents[]

@subsection[#:tag "gen-series-groupby"]{gen-series-groupby}
@defproc[(gen-series-groupby (arg0 GenSeries) (arg1 (#:by-value Boolean))) GroupHash]{
...
}

@subsection[#:tag "apply-agg-gen-series"]{apply-agg-gen-series}
@defproc[(apply-agg-gen-series (arg0 Symbol) (arg1 GroupHash)) GenSeries]{
...
}

@subsection[#:tag "make-group-hash"]{make-group-hash}
@defproc[(make-group-hash) GroupHash]{
...
}

@subsection[#:tag "make-agg-value-hash-sindex"]{make-agg-value-hash-sindex}
@defproc[(make-agg-value-hash-sindex (arg0 (Listof (Pair String GenericType)))) SIndex]{
...
}

@subsection[#:tag "agg-value-hash-to-gen-series"]{agg-value-hash-to-gen-series}
@defproc[(agg-value-hash-to-gen-series (arg0 AggValueHash)) GenSeries]{
...
}

@section[#:style 'toc]{Example Module}
@codeblock|{
#lang typed/racket

(require RacketFrames)

(require typed/db)

;******************
;data-frame-mix
;******************
(define columns-mix
  (list
   (cons 'integer-col (new-ISeries (list 1 2 3 4)
                                   #:index (build-index-from-list (list 'a 'b 'c 'd))))
   (cons 'categorical-col (new-CSeries (vector 'hello 'world 'fizz 'buzz)
                                       #:index (build-index-from-list (list 'a 'b 'c 'd))))))

; create new data-frame-mix
(define data-frame-mix (new-data-frame columns-mix))

(data-frame-write-delim data-frame-mix)

; no schema
(define salary-data-frame-csv-no-schema (load-csv-file "../sample-csv/salary_date.csv" #:schema #f))

(data-frame-head salary-data-frame-csv-no-schema)

(print salary-data-frame-csv-no-schema)

(displayln "DataFrame List of Column Names")
(data-frame-names salary-data-frame-csv-no-schema)

(displayln "DataFrame Dimensions")
(data-frame-dim salary-data-frame-csv-no-schema)

(displayln "DataFrame Description")
(show-data-frame-description (data-frame-description salary-data-frame-csv-no-schema))

(displayln "DataFrame Remove")
(data-frame-head (data-frame-remove salary-data-frame-csv-no-schema (list 'first 'age)))

(displayln "DataFrame Project")
(data-frame-head (data-frame-project salary-data-frame-csv-no-schema (list 'first 'last 'dollar)))

(displayln "DataFrame Replace")
(data-frame-head (data-frame-replace salary-data-frame-csv-no-schema (cons 'salary (new-CSeries (make-vector 200 '$0.00)))))

(displayln "DataFrame Replace Non Existent Column")
(data-frame-head (data-frame-replace salary-data-frame-csv-no-schema (cons 'dollar (new-CSeries (make-vector 200 '$0.00)))))

(displayln "DataFrame Extend")
(data-frame-head (data-frame-extend salary-data-frame-csv-no-schema (cons 'state (new-CSeries (make-vector 200 'CA)))))

(displayln "DataFrame Operations")
(define columns-integer-1
  (list 
   (cons 'col1 (new-ISeries (list 1 2 3 4)))
   (cons 'col2 (new-ISeries (list 5 6 7 8)))
   (cons 'col3 (new-ISeries (list 9 10 11 12)))
   (cons 'col4 (new-ISeries (list 21 22 23 24)))))

(define columns-integer-2
  (list 
   (cons 'col1 (new-ISeries (list 1 2 3 4)))
   (cons 'col2 (new-ISeries (list 25 26 27 28)))
   (cons 'col3 (new-ISeries (list 29 30 31 32)))
   (cons 'col4 (new-ISeries (list 1 2 3 4)))))

; create new data-frame-integer-1
(define data-frame-integer-1 (new-data-frame columns-integer-1))

; create new data-frame-integer-2
(define data-frame-integer-2 (new-data-frame columns-integer-2))

(displayln "Sample DataFrames")
(data-frame-write-delim data-frame-integer-1)

(data-frame-write-delim data-frame-integer-2)
(display "\n")

(displayln "data-frame+")
(data-frame-write-delim (data-frame+ data-frame-integer-1 data-frame-integer-2))
(display "\n")

(displayln "data-frame-")
(data-frame-write-delim (data-frame- data-frame-integer-1 data-frame-integer-2))
(display "\n")

(displayln "data-frame*")
(data-frame-write-delim (data-frame* data-frame-integer-1 data-frame-integer-2))
(display "\n")

(displayln "data-frame/")
(data-frame-write-delim (data-frame/ data-frame-integer-1 data-frame-integer-2))
(display "\n")

(displayln "data-frame%")
(data-frame-write-delim (data-frame% data-frame-integer-1 data-frame-integer-2))
(display "\n")

(displayln "data-frame-r")
(data-frame-write-delim (data-frame-r data-frame-integer-1 data-frame-integer-2))
(display "\n")


(displayln "DataFrame Join Operations")
(define columns-integer
  (list 
   (cons 'col1 (new-ISeries (list 1 2 3 4)))
   (cons 'col2 (new-ISeries (list 5 6 7 8)))
   (cons 'col3 (new-ISeries (list 9 10 11 12)))))

(define columns-categorical
  (list 
   (cons 'col1 (new-CSeries (list 'a 'b 'c 'd 'e)))
   (cons 'col2 (new-CSeries (list 'e 'f 'g 'h 'i)))
   (cons 'col3 (new-CSeries (list 'j 'k 'l 'm 'n)))))

; create new data-frame-integer
(define data-frame-integer (new-data-frame columns-integer))

; create new data-frame-categorical
(define data-frame-categorical (new-data-frame columns-categorical))

(displayln "DataFrame Left Join")
(data-frame-write-delim (data-frame-join-left data-frame-integer data-frame-categorical))
(display "\n")

(displayln "DataFrame Right Join")
(data-frame-write-delim (data-frame-join-right data-frame-integer-1 data-frame-integer-2 #:on (list 'col1)))
(display "\n")

(displayln "DataFrame Right Join")
(data-frame-write-delim (data-frame-join-right data-frame-integer-1 data-frame-integer-2 #:on (list 'col2)))
(display "\n")

(define columns-mixed-5
  (list 
   (cons 'col1 (new-ISeries (list 1 2 3 4)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'c 'd)))
   (cons 'col3 (new-ISeries (list 21 22 23 24)))))

(define columns-mixed-6
  (list 
   (cons 'col1 (new-ISeries (list 11 21 31 41)))
   (cons 'col2 (new-CSeries (vector 'a 'b 'g 'd)))
   (cons 'col3 (new-ISeries (list 22 22 23 24)))))

; create new data-frame-mixed-5
(define data-frame-mixed-5 (new-data-frame columns-mixed-5))

; create new data-frame-mixed-6
(define data-frame-mixed-6 (new-data-frame columns-mixed-6))'

(displayln "DataFrame Mixed")
(data-frame-write-delim data-frame-mixed-5)

(displayln "DataFrame Mixed")
(data-frame-write-delim data-frame-mixed-6)

(displayln "DataFrame Inner Join")
(data-frame-write-delim (data-frame-join-inner data-frame-mixed-5  data-frame-mixed-6 #:on (list 'col2)))

(display "\n")

(displayln "DataFrame Outer Join")
(data-frame-write-delim (data-frame-join-outer data-frame-mixed-5  data-frame-mixed-6 #:on (list 'col2)))

(displayln "DataFrame iloc")

(define columns-integer-labeled
  (list 
   (cons 'col1 (new-ISeries (list 1 2 3 4)
                            #:index (build-index-from-list (list 'a 'b 'c 'd))))
   (cons 'col2 (new-ISeries (list 5 6 7 8)
                            #:index (build-index-from-list (list 'e 'f 'g 'h))))
   (cons 'col3 (new-ISeries (list 9 10 11 12)
                            #:index (build-index-from-list (list 'i 'j 'k 'l))))))

; create new data-frame-integer
(define data-frame-integer-labeled (new-data-frame columns-integer-labeled))

(data-frame-write-delim data-frame-integer-labeled
                     )

(displayln "data-frame-loc")
(data-frame-write-delim
 (assert (data-frame-loc data-frame-integer-labeled (list 'i 'k) (list 'col3)) DataFrame?)
)

(define columns-integer-labeled-2
  (list 
   (cons 'col1 (new-ISeries (list 1 2 3 4)
                            #:index (build-index-from-list (list 'a 'b 'c 'd))))
   (cons 'col2 (new-ISeries (list 5 6 7 8)
                            #:index (build-index-from-list (list 'a 'b 'c 'd))))
   (cons 'col3 (new-ISeries (list 9 10 11 12)
                            #:index (build-index-from-list (list 'a 'b 'c 'd))))))

; create new data-frame-integer
(define data-frame-integer-labeled-2 (new-data-frame columns-integer-labeled-2))

(displayln "data-frame-loc-2")
(data-frame-write-delim
 (assert (data-frame-loc data-frame-integer-labeled-2 (list 'b 'c 'd) (list 'col2 'col3)) DataFrame?)
)

(set! data-frame-integer-labeled (data-frame-set-index data-frame-integer-labeled (list 'a 'b 'c 'd)))

(data-frame-write-delim
 (assert (data-frame-loc data-frame-integer-labeled (list 'b 'c 'd) (list 'col2 'col3)) DataFrame?)
)

(data-frame-write-delim
 (assert (data-frame-iloc data-frame-integer-labeled (list 1 2 3) (list 0 1)) DataFrame?)
)

(println "Hash list")
(hash->list (LabelIndex-index data-frame-integer-labeled))

(iseries-data (assert (data-frame-iloc data-frame-integer-labeled (list 1 2 3) 1) ISeries?))

(gen-series-data (assert (data-frame-iloc data-frame-integer-labeled 3 1) GenSeries?))

(data-frame-write-delim
 (assert (data-frame-iloc-label data-frame-integer-labeled (list 1 2 3) (list 'col1 'col2)) DataFrame?)
)

(gen-series-data (assert (data-frame-iloc-label data-frame-integer-labeled 1 (list 'col1 'col2)) GenSeries?))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Dataframe Load Test Cases;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define salary-date-schema (Schema #t (list (ColumnInfo 'first 'CategoricalSeries) (ColumnInfo 'last 'CategoricalSeries)
                                       (ColumnInfo 'age 'IntegerSeries) (ColumnInfo 'dollar 'CategoricalSeries)
                                       (ColumnInfo 'phone 'CategoricalSeries) (ColumnInfo 'join_date 'DatetimeSeries))))

(define salary-no-date-schema (Schema #t (list (ColumnInfo 'first 'CategoricalSeries) (ColumnInfo 'last 'CategoricalSeries)
                                       (ColumnInfo 'age 'IntegerSeries) (ColumnInfo 'dollar 'CategoricalSeries)
                                       (ColumnInfo 'phone 'CategoricalSeries))))

(define salary-datetime-schema (Schema #t (list (ColumnInfo 'first 'CategoricalSeries) (ColumnInfo 'last 'CategoricalSeries)
                                       (ColumnInfo 'age 'IntegerSeries) (ColumnInfo 'dollar 'CategoricalSeries)
                                       (ColumnInfo 'phone 'CategoricalSeries) (ColumnInfo 'join_datetime 'DatetimeSeries))))

(define random-demographic-schema (Schema #t (list (ColumnInfo 'first 'CategoricalSeries) (ColumnInfo 'last 'CategoricalSeries)
                                                   (ColumnInfo 'gender 'CategoricalSeries) (ColumnInfo 'yn 'CategoricalSeries)
                                                   (ColumnInfo 'char 'GenericSeries) (ColumnInfo 'float 'NumericSeries))))

; read csv
(define salary-data-frame-csv-schema (load-csv-file "../sample-csv/salary_date.csv" #:schema salary-date-schema))

(data-frame-head salary-data-frame-csv-schema)

(define salary-no-date-data-frame-csv-schema (load-csv-file "../sample-csv/salary_no_date.csv" #:schema salary-no-date-schema))

(data-frame-head salary-no-date-data-frame-csv-schema)

(define salary-datetime-data-frame-csv-schema (load-csv-file "../sample-csv/salary_datetime.csv" #:schema salary-datetime-schema))

(data-frame-head salary-datetime-data-frame-csv-schema)

(define salary-datetime-date-data-frame-csv-schema (load-csv-file "../sample-csv/salary_datetime_date.csv" #:schema salary-datetime-schema))

(data-frame-head salary-datetime-date-data-frame-csv-schema)


; read delimited
(define random-demographic-data-frame-delimited (load-delimited-file "../sample-csv/random_demographic.csv" "|" #:schema random-demographic-schema))

(data-frame-head random-demographic-data-frame-delimited)

(series-data (data-frame-series-ref random-demographic-data-frame-delimited 'char))

; no schema
(define random-demographic-data-frame-delimited-no-schema (load-delimited-file "../sample-csv/random_demographic.csv" "|" #:schema #f))

(data-frame-head random-demographic-data-frame-delimited-no-schema)

(define data-frame-from-sql-genres (data-frame-from-sql (sqlite3-connect #:database "db/chinook.db") #f "SELECT * FROM genres" empty))

(data-frame-head data-frame-from-sql-genres)

(define data-frame-from-sql-customers (data-frame-from-sql (sqlite3-connect #:database "db/chinook.db") #f "SELECT * FROM customers" empty))

(data-frame-head data-frame-from-sql-customers)

(define data-frame-nba-csv (load-csv-file "../sample-csv/nbaallelo.csv" #:schema #f))

(data-frame-head data-frame-nba-csv)

(define nba-csv-schema (get-schema "../sample-csv/nbaallelo.csv" ","))

(Schema-headers nba-csv-schema)
(Schema-SeriesTypes nba-csv-schema)

; series constructors
(define int-series (new-series (list 1 2 3 4 5 6 6 6 6 6 6)))
(define gen-series (new-series (vector 'a 1 2 'c 'd 5.6)))

(iseries-groupby (assert int-series ISeries?))
;(iseries-groupby (assert int-series ISeries?) #:by-value #t)

(series-iref int-series 3)
(series-print int-series)

(series-iref gen-series 5)
(series-print gen-series)

(define int-series-with-index (new-series (list 1 2 3 4 5 6) #:index (list 'a 'b 'c 'd 'e 'f)))
(define gen-series-with-index (new-series (vector 'a 1 2 'c 'd 5.6) #:index (list 6 5 4 3 2 1)))

;(iseries-groupby (assert int-series-with-index ISeries?))

(series-index-ref int-series-with-index 'e)
(series-print int-series-with-index)

(series-index-ref gen-series-with-index 5)
(series-print gen-series-with-index)

; dataframe constructors
(define data-frame-from-hash (new-data-frame (hash 'a (list 1 2 3) 'b (list 3 5 6) 'c (list 3.4 5.5 6.7) 'd (list 'fizz 'buzz 'baz))))

(show-data-frame-description (data-frame-description data-frame-from-hash))

(define data-frame-from-hash-vector (new-data-frame (hash 'a '#(1 2 3) 'b '#(3 5 6) 'c '#(3.4 5.5 6.7))))

(show-data-frame-description (data-frame-description data-frame-from-hash-vector))

(data-frame-head data-frame-from-hash) }|

@section[#:style 'toc]{Example Module Output}
@verbatim|{
integer-col	categorical-col
1	hello
2	world
3	fizz
4	buzz
     first           last             age           dollar           phone         join_date    
'(Evan) '(Lloyd) '(19) '($3839.78) '(|(771) 255-1133|) '(2018-05-19) 
'(Etta) '(Griffith) '(50) '($8158.60) '(|(523) 731-6388|) '(2018-05-19) 
'(William) '(Conner) '(50) '($9966.70) '(|(759) 504-6619|) '(2018-05-19) 
'(Rhoda) '(Guerrero) '(20) '($6480.10) '(|(467) 431-4273|) '(2018-05-19) 
'(Kyle) '(Klein) '(59) '($6106.13) '(|(760) 829-2093|) '(2018-05-19) 
'(Benjamin) '(Patton) '(59) '($3925.51) '(|(488) 673-5745|) '(2018-05-19) 
'(Georgie) '(Hansen) '(51) '($8809.92) '(|(579) 706-4402|) '(2018-05-19) 
'(Gregory) '(Bowen) '(36) '($5176.21) '(|(533) 506-3845|) '(2018-05-19) 
'(Cornelia) '(Peterson) '(46) '($3626.31) '(|(861) 316-5672|) '(2018-05-19) 
'(Samuel) '(Cole) '(37) '($7677.20) '(|(760) 406-6331|) '(2018-05-19) 
(DataFrame '#hash((age . (2)) (dollar . (3)) (first . (0)) (join_date . (5)) (last . (1)) (phone . (4))) ...)DataFrame List of Column Names
'(first last age dollar phone join_date)
DataFrame Dimensions
(Dim 200 6)
DataFrame Description
DataFrame::(Cols: 6, Rows: 200)
  - first: GenericSeries
  - last: GenericSeries
  - age: GenericSeries
  - dollar: GenericSeries
  - phone: GenericSeries
  - join_date: GenericSeries
DataFrame Remove
     last           dollar           phone         join_date    
'(Lloyd) '($3839.78) '(|(771) 255-1133|) '(2018-05-19) 
'(Griffith) '($8158.60) '(|(523) 731-6388|) '(2018-05-19) 
'(Conner) '($9966.70) '(|(759) 504-6619|) '(2018-05-19) 
'(Guerrero) '($6480.10) '(|(467) 431-4273|) '(2018-05-19) 
'(Klein) '($6106.13) '(|(760) 829-2093|) '(2018-05-19) 
'(Patton) '($3925.51) '(|(488) 673-5745|) '(2018-05-19) 
'(Hansen) '($8809.92) '(|(579) 706-4402|) '(2018-05-19) 
'(Bowen) '($5176.21) '(|(533) 506-3845|) '(2018-05-19) 
'(Peterson) '($3626.31) '(|(861) 316-5672|) '(2018-05-19) 
'(Cole) '($7677.20) '(|(760) 406-6331|) '(2018-05-19) 
DataFrame Project
     first           last           dollar      
'(Evan) '(Lloyd) '($3839.78) 
'(Etta) '(Griffith) '($8158.60) 
'(William) '(Conner) '($9966.70) 
'(Rhoda) '(Guerrero) '($6480.10) 
'(Kyle) '(Klein) '($6106.13) 
'(Benjamin) '(Patton) '($3925.51) 
'(Georgie) '(Hansen) '($8809.92) 
'(Gregory) '(Bowen) '($5176.21) 
'(Cornelia) '(Peterson) '($3626.31) 
'(Samuel) '(Cole) '($7677.20) 
DataFrame Replace
     first           last             age           dollar           phone         join_date    
'(Evan) '(Lloyd) '(19) '($3839.78) '(|(771) 255-1133|) '(2018-05-19) 
'(Etta) '(Griffith) '(50) '($8158.60) '(|(523) 731-6388|) '(2018-05-19) 
'(William) '(Conner) '(50) '($9966.70) '(|(759) 504-6619|) '(2018-05-19) 
'(Rhoda) '(Guerrero) '(20) '($6480.10) '(|(467) 431-4273|) '(2018-05-19) 
'(Kyle) '(Klein) '(59) '($6106.13) '(|(760) 829-2093|) '(2018-05-19) 
'(Benjamin) '(Patton) '(59) '($3925.51) '(|(488) 673-5745|) '(2018-05-19) 
'(Georgie) '(Hansen) '(51) '($8809.92) '(|(579) 706-4402|) '(2018-05-19) 
'(Gregory) '(Bowen) '(36) '($5176.21) '(|(533) 506-3845|) '(2018-05-19) 
'(Cornelia) '(Peterson) '(46) '($3626.31) '(|(861) 316-5672|) '(2018-05-19) 
'(Samuel) '(Cole) '(37) '($7677.20) '(|(760) 406-6331|) '(2018-05-19) 
DataFrame Replace Non Existent Column
     first           last             age           dollar           phone         join_date    
'(Evan) '(Lloyd) '(19) $0.00           '(|(771) 255-1133|) '(2018-05-19) 
'(Etta) '(Griffith) '(50) $0.00           '(|(523) 731-6388|) '(2018-05-19) 
'(William) '(Conner) '(50) $0.00           '(|(759) 504-6619|) '(2018-05-19) 
'(Rhoda) '(Guerrero) '(20) $0.00           '(|(467) 431-4273|) '(2018-05-19) 
'(Kyle) '(Klein) '(59) $0.00           '(|(760) 829-2093|) '(2018-05-19) 
'(Benjamin) '(Patton) '(59) $0.00           '(|(488) 673-5745|) '(2018-05-19) 
'(Georgie) '(Hansen) '(51) $0.00           '(|(579) 706-4402|) '(2018-05-19) 
'(Gregory) '(Bowen) '(36) $0.00           '(|(533) 506-3845|) '(2018-05-19) 
'(Cornelia) '(Peterson) '(46) $0.00           '(|(861) 316-5672|) '(2018-05-19) 
'(Samuel) '(Cole) '(37) $0.00           '(|(760) 406-6331|) '(2018-05-19) 
DataFrame Extend
     first           last             age           dollar           phone         join_date         state      
'(Evan) '(Lloyd) '(19) '($3839.78) '(|(771) 255-1133|) '(2018-05-19) CA              
'(Etta) '(Griffith) '(50) '($8158.60) '(|(523) 731-6388|) '(2018-05-19) CA              
'(William) '(Conner) '(50) '($9966.70) '(|(759) 504-6619|) '(2018-05-19) CA              
'(Rhoda) '(Guerrero) '(20) '($6480.10) '(|(467) 431-4273|) '(2018-05-19) CA              
'(Kyle) '(Klein) '(59) '($6106.13) '(|(760) 829-2093|) '(2018-05-19) CA              
'(Benjamin) '(Patton) '(59) '($3925.51) '(|(488) 673-5745|) '(2018-05-19) CA              
'(Georgie) '(Hansen) '(51) '($8809.92) '(|(579) 706-4402|) '(2018-05-19) CA              
'(Gregory) '(Bowen) '(36) '($5176.21) '(|(533) 506-3845|) '(2018-05-19) CA              
'(Cornelia) '(Peterson) '(46) '($3626.31) '(|(861) 316-5672|) '(2018-05-19) CA              
'(Samuel) '(Cole) '(37) '($7677.20) '(|(760) 406-6331|) '(2018-05-19) CA              
DataFrame Operations
Sample DataFrames
col1	col2	col3	col4
1	5	9	21
2	6	10	22
3	7	11	23
4	8	12	24
col1	col2	col3	col4
1	25	29	1
2	26	30	2
3	27	31	3
4	28	32	4

data-frame+
col1	col2	col3	col4
2	30	38	22
4	32	40	24
6	34	42	26
8	36	44	28

data-frame-
col1	col2	col3	col4
0	-20	-20	20
0	-20	-20	20
0	-20	-20	20
0	-20	-20	20

data-frame*
col1	col2	col3	col4
1	125	261	21
4	156	300	44
9	189	341	69
16	224	384	96

data-frame/
col1	col2	col3	col4
1	0	0	21
1	0	0	11
1	0	0	7
1	0	0	6

data-frame%
col1	col2	col3	col4
0	5	9	0
0	6	10	0
0	7	11	2
0	8	12	0

data-frame-r
col1	col2	col3	col4
0	5	9	0
0	6	10	0
0	7	11	2
0	8	12	0

DataFrame Join Operations
DataFrame Left Join
dfa-col1	dfa-col2	dfa-col3	dfb-col1	dfb-col2	dfb-col3
1	5	9	null	null	null
2	6	10	null	null	null
3	7	11	null	null	null
4	8	12	null	null	null

DataFrame Right Join
dfa-col2	dfa-col3	dfa-col4	dfb-col1	dfb-col2	dfb-col3	dfb-col4
5	9	21	1	25	29	1
6	10	22	2	26	30	2
7	11	23	3	27	31	3
8	12	24	4	28	32	4

DataFrame Right Join
dfa-col1	dfa-col3	dfa-col4	dfb-col1	dfb-col2	dfb-col3	dfb-col4
0	0	0	1	25	29	1
0	0	0	2	26	30	2
0	0	0	3	27	31	3
0	0	0	4	28	32	4

'(displayln "DataFrame Mixed")
col1	col2	col3
1	a	21
2	b	22
3	c	23
4	d	24
DataFrame Mixed
col1	col2	col3
11	a	22
21	b	22
31	g	23
41	d	24
DataFrame Inner Join
dfa-col1	dfa-col2	dfa-col3	dfb-col1	dfb-col2	dfb-col3
1	a	21	11	a	22
2	b	22	21	b	22
4	d	24	41	d	24

DataFrame Outer Join
dfa-col1	dfa-col2	dfa-col3	dfb-col1	dfb-col2	dfb-col3
1	a	21	11	a	22
2	b	22	21	b	22
3	c	23	0	null	0
4	d	24	41	d	24
0	null	0	31	g	23
DataFrame iloc
col1	col2	col3
1	5	9
2	6	10
3	7	11
4	8	12
data-frame-loc
col3
9
11
data-frame-loc-2
col2	col3
6	10
7	11
8	12
col2	col3
6	10
7	11
8	12
col1	col2
2	6
3	7
4	8
"Hash list"
'((col2 1) (col1 0) (col3 2))
'#(6 7 8)
'#(8)
col1	col2
2	6
3	7
4	8
'#(2 6)
     first           last             age           dollar           phone         join_date    
'(Evan) '(Lloyd) '(19) '($3839.78) '(|(771) 255-1133|) '(2018-05-19) 
'(Etta) '(Griffith) '(50) '($8158.60) '(|(523) 731-6388|) '(2018-05-19) 
'(William) '(Conner) '(50) '($9966.70) '(|(759) 504-6619|) '(2018-05-19) 
'(Rhoda) '(Guerrero) '(20) '($6480.10) '(|(467) 431-4273|) '(2018-05-19) 
'(Kyle) '(Klein) '(59) '($6106.13) '(|(760) 829-2093|) '(2018-05-19) 
'(Benjamin) '(Patton) '(59) '($3925.51) '(|(488) 673-5745|) '(2018-05-19) 
'(Georgie) '(Hansen) '(51) '($8809.92) '(|(579) 706-4402|) '(2018-05-19) 
'(Gregory) '(Bowen) '(36) '($5176.21) '(|(533) 506-3845|) '(2018-05-19) 
'(Cornelia) '(Peterson) '(46) '($3626.31) '(|(861) 316-5672|) '(2018-05-19) 
'(Samuel) '(Cole) '(37) '($7677.20) '(|(760) 406-6331|) '(2018-05-19) 
     first           last             age           dollar           phone      
'(Evan) '(Lloyd) '(19) '($3839.78) '(|(771) 255-1133|) 
'(Etta) '(Griffith) '(50) '($8158.60) '(|(523) 731-6388|) 
'(William) '(Conner) '(50) '($9966.70) '(|(759) 504-6619|) 
'(Rhoda) '(Guerrero) '(20) '($6480.10) '(|(467) 431-4273|) 
'(Kyle) '(Klein) '(59) '($6106.13) '(|(760) 829-2093|) 
'(Benjamin) '(Patton) '(59) '($3925.51) '(|(488) 673-5745|) 
'(Georgie) '(Hansen) '(51) '($8809.92) '(|(579) 706-4402|) 
'(Gregory) '(Bowen) '(36) '($5176.21) '(|(533) 506-3845|) 
'(Cornelia) '(Peterson) '(46) '($3626.31) '(|(861) 316-5672|) 
'(Samuel) '(Cole) '(37) '($7677.20) '(|(760) 406-6331|) 
     first           last             age           dollar           phone       join_datetime  
'(Evan) '(Lloyd) '(19) '($3839.78) '(|(771) 255-1133|) '(2099-12-31T23:59:59.123) 
'(Etta) '(Griffith) '(50) '($8158.60) '(|(523) 731-6388|) '(2099-12-31T23:59:59.123) 
'(William) '(Conner) '(50) '($9966.70) '(|(759) 504-6619|) '(2099-12-31T23:59:59.123) 
'(Rhoda) '(Guerrero) '(20) '($6480.10) '(|(467) 431-4273|) '(2099-12-31T23:59:59.123) 
'(Kyle) '(Klein) '(59) '($6106.13) '(|(760) 829-2093|) '(2099-12-31T23:59:59.123) 
'(Benjamin) '(Patton) '(59) '($3925.51) '(|(488) 673-5745|) '(2099-12-31T23:59:59.123) 
'(Georgie) '(Hansen) '(51) '($8809.92) '(|(579) 706-4402|) '(2099-12-31T23:59:59.123) 
'(Gregory) '(Bowen) '(36) '($5176.21) '(|(533) 506-3845|) '(2099-12-31T23:59:59.123) 
'(Cornelia) '(Peterson) '(46) '($3626.31) '(|(861) 316-5672|) '(2099-12-31T23:59:59.123) 
'(Samuel) '(Cole) '(37) '($7677.20) '(|(760) 406-6331|) '(2099-12-31T23:59:59.123) 
     first           last             age           dollar           phone       join_datetime  
'(Evan) '(Lloyd) '(19) '($3839.78) '(|(771) 255-1133|) '(2099-12-31T23:59:59.123) 
'(Rebecca) '(Logan) '(28) '($7665.45) '(|(630) 728-2457|) '(2018-05-19) 
'(Etta) '(Griffith) '(50) '($8158.60) '(|(523) 731-6388|) '(2099-12-31T23:59:59.123) 
'(William) '(Conner) '(50) '($9966.70) '(|(759) 504-6619|) '(2099-12-31T23:59:59.123) 
'(Jeffery) '(Cooper) '(64) '($925.54) '(|(515) 612-3212|) '(2018-05-19) 
'(Ellen) '(Clayton) '(47) '($3870.14) '(|(402) 887-8694|) '(2018-05-19) 
'(Rhoda) '(Guerrero) '(20) '($6480.10) '(|(467) 431-4273|) '(2099-12-31T23:59:59.123) 
'(Kyle) '(Klein) '(59) '($6106.13) '(|(760) 829-2093|) '(2099-12-31T23:59:59.123) 
'(Timothy) '(Francis) '(36) '($4771.53) '(|(703) 219-6407|) '(2018-05-19) 
'(Benjamin) '(Patton) '(59) '($3925.51) '(|(488) 673-5745|) '(2099-12-31T23:59:59.123) 
     first           last           gender            yn             char            float      
Louis           Lawson          Male            Y               '(z) -320102186614.78 
Arthur          Williams        Male            N               '(m) 533549655313.61 
Lou             Clayton         Male            N               '(i) -212304637041.05 
Nora            Dean            Female          Y               '(9) -881170010708.38 
Cecelia         Guzman          Female          Y               '(q) -360380776631.50 
Matthew         Maxwell         Male            N               '(q) -850854199217.36 
Sophie          Murray          Male            N               '(x) 616161740220.01 
Johnny          Barnes          Female          Y               '(D) 374206918085.84 
Lena            Bradley         Male            N               '(S) -107760003422.62 
Jerome          May             Female          N               '(n) 819900671904.97 
'#(z
   m
   i
   9
   q
   q
   x
   D
   S
   n
   z
   c
   p
   m
   4
   !
   0
   f
   6
   $
   |]|
   O
   I
   X
   !
   Y
   r
   3
   w
   5
   e
   w
   7
   c
   w
   t
   a
   j
   0
   p
   1
   N
   d
   U
   P
   O
   4
   @
   V
   m
   o
   7
   a
   q
   1
   j
   e
   c
   f
   @
   7
   E
   !
   $
   C
   9
   |[|
   W
   K
   0
   8
   T
   L
   R
   y
   3
   Y
   x
   y
   c
   F
   e
   l
   2
   2
   2
   |)|
   b
   S
   b
   D
   %
   C
   |]|
   C
   t
   !
   |(|
   u
   @
   &
   A
   f
   9
   3
   |]|
   j
   e
   w
   X
   f
   i
   z
   8
   Z
   &
   8
   M
   l
   J
   H
   %
   f
   6
   E
   7
   h
   M
   Y
   1
   R
   W
   r
   P
   x
   |#|
   2
   n
   G
   Q
   u
   M
   3
   D
   8
   e
   T
   t
   Z
   G
   g
   n
   a
   &
   b
   Y
   F
   W
   w
   3
   Y
   h
   o
   O
   9
   o
   Z
   W
   P
   K
   B
   g
   C
   g
   j
   O
   |[|
   9
   |]|
   3
   e
   Z
   l
   v
   B
   M
   U
   o
   C
   y
   9
   C
   |#|
   4
   l
   R
   W
   I
   t
   l
   6
   z
   j
   t
   |(|
   H
   l
   T
   g
   r
   g
   F
   $
   E
   T
   H
   &
   7
   c
   |)|
   |#|
   S
   B
   9
   A
   D
   O
   |(|
   g
   2
   |(|
   E
   B
   4
   |)|
   o
   8
   H
   y
   0
   u
   g
   Q
   k
   n
   9
   g
   y
   |[|
   z
   9
   d
   8
   F
   m
   T
   4
   J
   8
   w
   K
   |(|
   4
   &
   q
   A
   a
   m
   5
   F
   1
   |(|
   K
   |(|
   L
   S
   l
   I
   q
   |[|
   N
   I
   N
   |(|
   v
   m
   x
   b
   @
   N
   t
   S
   5
   p
   9
   Y
   t
   c
   L
   C)
     first           last           gender            yn             char            float      
Louis           Lawson          Male            Y               '(z) -320102186614.78 
Arthur          Williams        Male            N               '(m) 533549655313.61 
Lou             Clayton         Male            N               '(i) -212304637041.05 
Nora            Dean            Female          Y               '(9) -881170010708.38 
Cecelia         Guzman          Female          Y               '(q) -360380776631.50 
Matthew         Maxwell         Male            N               '(q) -850854199217.36 
Sophie          Murray          Male            N               '(x) 616161740220.01 
Johnny          Barnes          Female          Y               '(D) 374206918085.84 
Lena            Bradley         Male            N               '(S) -107760003422.62 
Jerome          May             Female          N               '(n) 819900671904.97 
    GenreId          Name       
              1 Rock            
              2 Jazz            
              3 Metal           
              4 Alternative & P 
              5 Rock And Roll   
              6 Blues           
              7 Latin           
              8 Reggae          
              9 Pop             
             10 Soundtrack      
  CustomerId       FirstName       LastName         Company         Address          City            State          Country       PostalCode         Phone            Fax            Email       SupportRepId   
              1 Luís            Gonçalves       '(|Embraer - Empresa Brasileira de Aeronáutica S.A.|) Av. Brigadeiro  São José dos Ca '(SP) Brazil          '(12227-000) '(|+55 (12) 3923-5555|) '(|+55 (12) 3923-5566|) luisg@embraer.c               3 
              2 Leonie          Köhler          '(#<sql-null>) Theodor-Heuss-S Stuttgart       '(#<sql-null>) Germany         '(70174) '(|+49 0711 2842222|) '(#<sql-null>) leonekohler@sur               5 
              3 François        Tremblay        '(#<sql-null>) 1498 rue Bélang Montréal        '(QC) Canada          '(|H2G 1A7|) '(|+1 (514) 721-4711|) '(#<sql-null>) ftremblay@gmail               3 
              4 Bjørn           Hansen          '(#<sql-null>) Ullevålsveien 1 Oslo            '(#<sql-null>) Norway          '(171) '(|+47 22 44 22 22|) '(#<sql-null>) bjorn.hansen@ya               4 
              5 František       Wichterlová     '(|JetBrains s.r.o.|) Klanova 9/506   Prague          '(#<sql-null>) Czech Republic  '(14700) '(|+420 2 4172 5555|) '(|+420 2 4172 5555|) frantisekw@jetb               4 
              6 Helena          Holý            '(#<sql-null>) Rilská 3174/6   Prague          '(#<sql-null>) Czech Republic  '(14300) '(|+420 2 4177 0449|) '(#<sql-null>) hholy@gmail.com               5 
              7 Astrid          Gruber          '(#<sql-null>) Rotenturmstraße Vienne          '(#<sql-null>) Austria         '(1010) '(|+43 01 5134505|) '(#<sql-null>) astrid.gruber@a               5 
              8 Daan            Peeters         '(#<sql-null>) Grétrystraat 63 Brussels        '(#<sql-null>) Belgium         '(1000) '(|+32 02 219 03 03|) '(#<sql-null>) daan_peeters@ap               4 
              9 Kara            Nielsen         '(#<sql-null>) Sønder Boulevar Copenhagen      '(#<sql-null>) Denmark         '(1720) '(|+453 3331 9991|) '(#<sql-null>) kara.nielsen@ju               4 
             10 Eduardo         Martins         '(|Woodstock Discos|) Rua Dr. Falcão  São Paulo       '(SP) Brazil          '(01007-010) '(|+55 (11) 3033-5446|) '(|+55 (11) 3033-4564|) eduardo@woodsto               4 
   gameorder        game_id          lg_id          _iscopy         year_id       seasongame      is_playoffs       team_id         fran_id           pts            elo_i           elo_n         win_equiv        opp_id         opp_fran         opp_pts        opp_elo_i       opp_elo_n     game_location    game_result      forecast     
'(1) '(194611010TRH) '(NBA) '(0) '(1947) '(1) '(0) '(TRH) '(Huskies) '(66) '(1300) '(1293.2767) '(40.29483) '(NYK) '(Knicks) '(68) '(1300) '(1306.7233) '(H) '(L) '(0.64006501) 
'(1) '(194611010TRH) '(NBA) '(1) '(1947) '(1) '(0) '(NYK) '(Knicks) '(68) '(1300) '(1306.7233) '(41.70517) '(TRH) '(Huskies) '(66) '(1300) '(1293.2767) '(A) '(W) '(0.35993499) 
'(2) '(194611020CHS) '(NBA) '(0) '(1947) '(1) '(0) '(CHS) '(Stags) '(63) '(1300) '(1309.6521) '(42.012257) '(NYK) '(Knicks) '(47) '(1306.7233) '(1297.0712) '(H) '(W) '(0.63110125) 
'(2) '(194611020CHS) '(NBA) '(1) '(1947) '(2) '(0) '(NYK) '(Knicks) '(47) '(1306.7233) '(1297.0712) '(40.692783) '(CHS) '(Stags) '(63) '(1300) '(1309.6521) '(A) '(L) '(0.36889875) 
'(3) '(194611020DTF) '(NBA) '(0) '(1947) '(1) '(0) '(DTF) '(Falcons) '(33) '(1300) '(1279.6189) '(38.864048) '(WSC) '(Capitols) '(50) '(1300) '(1320.3811) '(H) '(L) '(0.64006501) 
'(3) '(194611020DTF) '(NBA) '(1) '(1947) '(1) '(0) '(WSC) '(Capitols) '(50) '(1300) '(1320.3811) '(43.135952) '(DTF) '(Falcons) '(33) '(1300) '(1279.6189) '(A) '(W) '(0.35993499) 
'(4) '(194611020PRO) '(NBA) '(1) '(1947) '(1) '(0) '(BOS) '(Celtics) '(53) '(1300) '(1294.8458) '(40.459381) '(PRO) '(Steamrollers) '(59) '(1300) '(1305.1542) '(A) '(L) '(0.35993499) 
'(4) '(194611020PRO) '(NBA) '(0) '(1947) '(1) '(0) '(PRO) '(Steamrollers) '(59) '(1300) '(1305.1542) '(41.540619) '(BOS) '(Celtics) '(53) '(1300) '(1294.8458) '(H) '(W) '(0.64006501) 
'(5) '(194611020STB) '(NBA) '(1) '(1947) '(1) '(0) '(PIT) '(Ironmen) '(51) '(1300) '(1295.3092) '(40.50798) '(STB) '(Bombers) '(56) '(1300) '(1304.6908) '(A) '(L) '(0.35993499) 
'(5) '(194611020STB) '(NBA) '(0) '(1947) '(1) '(0) '(STB) '(Bombers) '(56) '(1300) '(1304.6908) '(41.49202) '(PIT) '(Ironmen) '(51) '(1300) '(1295.3092) '(H) '(W) '(0.64006501) 
'(gameorder game_id lg_id _iscopy year_id seasongame is_playoffs team_id fran_id pts elo_i elo_n win_equiv opp_id opp_fran opp_pts opp_elo_i opp_elo_n game_location game_result forecast)
'(IntegerSeries
  CategoricalSeries
  CategoricalSeries
  IntegerSeries
  IntegerSeries
  IntegerSeries
  IntegerSeries
  CategoricalSeries
  CategoricalSeries
  IntegerSeries
  NumericSeries
  NumericSeries
  NumericSeries
  CategoricalSeries
  CategoricalSeries
  IntegerSeries
  NumericSeries
  NumericSeries
  CategoricalSeries
  CategoricalSeries
  NumericSeries)
'#hash(("0" . (1)) ("1" . (2)) ("10" . (6)) ("2" . (3)) ("3" . (4)) ("4" . (5)) ("5" . (6)) ("6" . (6)) ("7" . (6)) ("8" . (6)) ("9" . (6)))
'(4)
*********
$ISeries
*********
0 1
1 2
2 3
3 4
4 5
5 6
6 6
7 6
8 6
9 6
10 6
'(5.6)
*********
$GenSeries
*********
0 a
1 1
2 2
3 c
4 d
5 5.6
'(5)
*********
$ISeries
*********
a 1
b 2
c 3
d 4
e 5
f 6
'(1)
*********
$GenSeries
*********
6 a
5 1
4 2
3 c
2 d
1 5.6
DataFrame::(Cols: 4, Rows: 3)
  - b: IntegerSeries
  - d: CategoricalSeries
  - a: IntegerSeries
  - c: NumericSeries
DataFrame::(Cols: 3, Rows: 3)
  - b: IntegerSeries
  - a: IntegerSeries
  - c: NumericSeries
  b               d               a               c        
  3 fizz                          1            3.40 
  5 buzz                          2            5.50 
  6 baz                           3            6.70 
            }|

@index-section[]