├── .formatter.exs ├── .gitignore ├── .iex.exs ├── LICENSE ├── Makefile ├── README.md ├── learning_expolars.ipynb ├── lib ├── datasets │ └── datasets.ex ├── ex_polars.ex └── ex_polars │ ├── dataframe.ex │ ├── native.ex │ ├── plot.ex │ └── series.ex ├── mix.exs ├── mix.lock ├── native └── expolars │ ├── .cargo │ └── config │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── crimea.json │ └── src │ ├── dataframe.rs │ ├── datatypes.rs │ ├── error.rs │ ├── lib.rs │ └── series.rs ├── priv ├── dataset_info.json ├── datasets │ ├── airports.csv │ ├── anscombe.json │ ├── barley.json │ ├── btc.csv │ ├── burtin.json │ ├── cars.json │ ├── crimea.json │ ├── driving.json │ ├── iowa-electricity.csv │ ├── iris.json │ ├── la-riots.csv │ ├── movies.json │ ├── ohlc.json │ ├── seattle-temps.csv │ ├── seattle-weather.csv │ ├── sf-temps.csv │ ├── stocks.csv │ ├── us-employment.csv │ └── wheat.json └── local_datasets.json ├── slides ├── assets │ └── custom.css ├── ex-polars-lessons-learned.md └── images │ ├── deneb.png │ ├── deneb1.jpg │ ├── deneb2.jpg │ ├── ex_polars.jpg │ ├── happy.webp │ ├── solved.webp │ └── tubi.png └── test ├── ex_polars_test.exs └── test_helper.exs /.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | ex_polars-*.tar 24 | 25 | 26 | # Temporary files for e.g. tests 27 | /tmp 28 | 29 | *.so 30 | .vscode 31 | .ipynb_checkpoints 32 | -------------------------------------------------------------------------------- /.iex.exs: -------------------------------------------------------------------------------- 1 | alias ExPolars.Series, as: S 2 | alias ExPolars.DataFrame, as: DF 3 | alias ExPolars.Datasets 4 | import Kernel, except: [+: 2, -: 2, *: 2, /: 2, ==: 2, <>: 2, >: 2, >=: 2, <: 2, <=: 2] 5 | import S, only: [+: 2, -: 2, *: 2, /: 2, ==: 2, <>: 2, >: 2, >=: 2, <: 2, <=: 2] 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tyr Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MARP=marp --theme $(ASSET_DIR)/custom.css 2 | 3 | TOP_DIR=slides 4 | SRC_DIR=$(TOP_DIR) 5 | TARGET_DIR=$(TOP_DIR)/_build 6 | ASSET_DIR=$(TOP_DIR)/assets 7 | 8 | run: 9 | @$(MARP) -s $(SRC_DIR) 10 | 11 | build: $(TARGET_DIR) copy-assets 12 | @$(MARP) -I SRC_DIR -o $(TARGET_DIR) 13 | 14 | build-pdf: build 15 | @$(MARP) -I SRC_DIR -o $(TARGET_DIR) --allow-local-files --pdf 16 | 17 | copy-assets: 18 | @rsync -arv $(SRC_DIR)/images $(TARGET_DIR) 19 | 20 | $(TARGET_DIR): 21 | @mkdir -p $@ 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ExPolars 2 | 3 | Elixir support for [polars](https://github.com/ritchie46/polars), a DataFrame library written in rust. 4 | 5 | ## Usage 6 | 7 | ```elixir 8 | alias ExPolars.DataFrame, as: Df 9 | df = Df.read_csv("iris.csv") 10 | Df.head(df) 11 | 12 | ``` 13 | 14 | ## Installation 15 | 16 | To build ex_polars, you need to install rust nightly. This is because polars is using nightly features at the moment. 17 | 18 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 19 | by adding `ex_polars` to your list of dependencies in `mix.exs`: 20 | 21 | ```elixir 22 | def deps do 23 | [ 24 | {:ex_polars, "~> 0.1.0"} 25 | ] 26 | end 27 | ``` 28 | 29 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 30 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 31 | be found at [https://hexdocs.pm/ex_polars](https://hexdocs.pm/ex_polars). 32 | -------------------------------------------------------------------------------- /lib/datasets/datasets.ex: -------------------------------------------------------------------------------- 1 | defmodule ExPolars.Datasets do 2 | @moduledoc """ 3 | Vega datasets, copied from altair: https://github.com/altair-viz/vega_datasets 4 | """ 5 | 6 | alias ExPolars.DataFrame, as: DF 7 | 8 | path = Application.app_dir(:ex_polars, ["priv"]) 9 | 10 | datasets = 11 | path 12 | |> Path.join("local_datasets.json") 13 | |> File.read!() 14 | |> Jason.decode!() 15 | |> Enum.reduce(%{}, fn {name, v}, acc -> 16 | name = String.replace(name, "-", "_") 17 | 18 | result = 19 | case is_map(v) do 20 | true -> %{v | "file" => Path.join(path, v["file"])} 21 | _ -> %{"file" => Path.join(path, v)} 22 | end 23 | 24 | Map.put(acc, name, result) 25 | end) 26 | 27 | Enum.each(datasets, fn {name, %{"file" => filename} = v} -> 28 | fname = String.to_atom(name) 29 | date = Map.get(v, "date") 30 | format = Map.get(v, "format") 31 | 32 | def unquote(fname)() do 33 | filename = unquote(filename) 34 | date = unquote(date) 35 | format = unquote(format) 36 | 37 | {:ok, df} = 38 | case Path.extname(filename) do 39 | ".json" -> DF.read_json(filename) 40 | ".csv" -> DF.read_csv(filename) 41 | ".parquet" -> DF.read_parquet(filename) 42 | _ -> {:ok, nil} 43 | end 44 | 45 | case {df, date} do 46 | {nil, nil} -> nil 47 | {_, nil} -> df 48 | {_, _} -> DF.parse_date(df, date, format) 49 | end 50 | 51 | df 52 | end 53 | end) 54 | end 55 | -------------------------------------------------------------------------------- /lib/ex_polars.ex: -------------------------------------------------------------------------------- 1 | defmodule ExPolars do 2 | @moduledoc """ 3 | Documentation for `ExPolars`. 4 | """ 5 | end 6 | -------------------------------------------------------------------------------- /lib/ex_polars/dataframe.ex: -------------------------------------------------------------------------------- 1 | defmodule ExPolars.DataFrame do 2 | alias ExPolars.Native 3 | alias ExPolars.Series, as: S 4 | alias ExPolars.Plot 5 | 6 | @type t :: ExPolars.DataFrame 7 | @type s :: ExPolars.Series 8 | 9 | defstruct [:inner] 10 | 11 | @spec read_csv( 12 | String.t(), 13 | integer(), 14 | integer(), 15 | boolean(), 16 | boolean(), 17 | integer() | nil, 18 | integer(), 19 | list(integer()) | nil, 20 | String.t(), 21 | boolean(), 22 | list(String.t()) | nil, 23 | String.t() 24 | ) :: {:ok, t()} | {:error, term()} 25 | defdelegate read_csv( 26 | filename, 27 | infer_schema_length \\ 100, 28 | batch_size \\ 64, 29 | has_header \\ true, 30 | ignore_errors \\ false, 31 | stop_after_n_rows \\ nil, 32 | skip_rows \\ 0, 33 | projection \\ nil, 34 | sep \\ ",", 35 | rechunk \\ true, 36 | columns \\ nil, 37 | encoding \\ "utf8" 38 | ), 39 | to: Native, 40 | as: :df_read_csv 41 | 42 | @spec read_parquet(String.t()) :: {:ok, t()} | {:error, term()} 43 | defdelegate read_parquet(filename), to: Native, as: :df_read_parquet 44 | 45 | @spec read_json(String.t(), boolean()) :: {:ok, t()} | {:error, term()} 46 | defdelegate read_json(filename, line_delimited_json \\ false), to: Native, as: :df_read_json 47 | 48 | @spec to_csv(t() | {:ok, t()}, integer(), boolean(), integer()) :: 49 | {:ok, String.t()} | {:error, term()} 50 | def to_csv(df, batch_size \\ 100_000, has_headers \\ true, delimiter \\ ?,) 51 | 52 | def to_csv({:ok, df}, batch_size, has_headers, delimiter), 53 | do: to_csv(df, batch_size, has_headers, delimiter) 54 | 55 | defdelegate to_csv(df, batch_size, has_headers, delimiter), to: Native, as: :df_to_csv 56 | 57 | @spec to_csv_file(t() | {:ok, t()}, String.t(), integer(), boolean(), integer()) :: 58 | {:ok, {}} | {:error, term()} 59 | def to_csv_file(df, filename, batch_size \\ 100_000, has_headers \\ true, delimiter \\ ?,) 60 | 61 | def to_csv_file({:ok, df}, filename, batch_size, has_headers, delimiter), 62 | do: to_csv_file(df, filename, batch_size, has_headers, delimiter) 63 | 64 | defdelegate to_csv_file(df, filename, batch_size, has_headers, delimiter), 65 | to: Native, 66 | as: :df_to_csv_file 67 | 68 | # defdelegate as_str(df), to: Native, as: :df_as_str 69 | 70 | @spec add(t() | {:ok, t()}, s() | {:ok, s()}) :: {:ok, t()} | {:error, term()} 71 | def add(df, {:ok, s}), do: add(df, s) 72 | def add({:ok, df}, {:ok, s}), do: add(df, s) 73 | def add({:ok, df}, s), do: add(df, s) 74 | defdelegate add(df, s), to: Native, as: :df_add 75 | 76 | @spec sub(t() | {:ok, t()}, s() | {:ok, s()}) :: {:ok, t()} | {:error, term()} 77 | def sub(df, {:ok, s}), do: sub(df, s) 78 | def sub({:ok, df}, {:ok, s}), do: sub(df, s) 79 | def sub({:ok, df}, s), do: sub(df, s) 80 | defdelegate sub(df, s), to: Native, as: :df_sub 81 | 82 | @spec divide(t() | {:ok, t()}, s() | {:ok, s()}) :: {:ok, t()} | {:error, term()} 83 | def divide(df, {:ok, s}), do: divide(df, s) 84 | def divide({:ok, df}, {:ok, s}), do: divide(df, s) 85 | def divide({:ok, df}, s), do: divide(df, s) 86 | defdelegate divide(df, s), to: Native, as: :df_div 87 | 88 | @spec mul(t() | {:ok, t()}, s() | {:ok, s()}) :: {:ok, t()} | {:error, term()} 89 | def mul(df, {:ok, s}), do: mul(df, s) 90 | def mul({:ok, df}, {:ok, s}), do: mul(df, s) 91 | def mul({:ok, df}, s), do: mul(df, s) 92 | defdelegate mul(df, s), to: Native, as: :df_mul 93 | 94 | @spec remainder(t() | {:ok, t()}, s() | {:ok, s()}) :: {:ok, t()} | {:error, term()} 95 | def remainder({:ok, df}, {:ok, s}), do: remainder(df, s) 96 | def remainder(df, {:ok, s}), do: remainder(df, s) 97 | def remainder({:ok, df}, s), do: remainder(df, s) 98 | defdelegate remainder(df, s), to: Native, as: :df_rem 99 | 100 | @spec rechunk(t() | {:ok, t()}) :: {:ok, {}} | {:error, term()} 101 | def rechunk({:ok, df}), do: rechunk(df) 102 | defdelegate rechunk(df), to: Native, as: :df_rechunk 103 | 104 | @spec fill_none(t() | {:ok, t()}, String.t()) :: {:ok, t()} | {:error, term()} 105 | def fill_none({:ok, df}, strategy), do: fill_none(df, strategy) 106 | defdelegate fill_none(df, strategy), to: Native, as: :df_fill_none 107 | 108 | @spec join(t() | {:ok, t()}, t() | {:ok, t()}, list(String.t()), list(String.t()), String.t()) :: 109 | {:ok, t()} | {:error, term()} 110 | def join({:ok, df}, other, left_on, right_on, how), do: join(df, other, left_on, right_on, how) 111 | defdelegate join(df, other, left_on, right_on, how), to: Native, as: :df_join 112 | 113 | @spec get_columns(t() | {:ok, t()}) :: {:ok, list(s() | {:ok, s()})} | {:error, term()} 114 | def get_columns({:ok, df}), do: get_columns(df) 115 | defdelegate get_columns(df), to: Native, as: :df_get_columns 116 | 117 | @spec columns(t() | {:ok, t()}) :: {:ok, list(String.t())} | {:error, term()} 118 | def columns({:ok, df}), do: columns(df) 119 | defdelegate columns(def), to: Native, as: :df_columns 120 | 121 | @spec set_column_names(t() | {:ok, t()}, list(String.t())) :: {:ok, {}} | {:error, term()} 122 | def set_column_names({:ok, df}, names), do: set_column_names(df, names) 123 | defdelegate set_column_names(df, names), to: Native, as: :df_set_column_names 124 | 125 | @spec dtypes(t() | {:ok, t()}) :: {:ok, list(integer())} | {:error, term()} 126 | def dtypes({:ok, df}), do: dtypes(df) 127 | defdelegate dtypes(df), to: Native, as: :df_dtypes 128 | 129 | @spec n_chunks(t() | {:ok, t()}) :: {:ok, integer()} | {:error, term()} 130 | defdelegate n_chunks(df), to: Native, as: :df_n_chunks 131 | 132 | @spec shape(t() | {:ok, t()}) :: {:ok, {integer(), integer()}} | {:error, term()} 133 | def shape({:ok, df}), do: shape(df) 134 | defdelegate shape(df), to: Native, as: :df_shape 135 | 136 | @spec height(t() | {:ok, t()}) :: {:ok, integer()} | {:error, term()} 137 | def height({:ok, df}), do: height(df) 138 | defdelegate height(df), to: Native, as: :df_height 139 | 140 | @spec width(t() | {:ok, t()}) :: {:ok, integer()} | {:error, term()} 141 | def width({:ok, df}), do: width(df) 142 | defdelegate width(df), to: Native, as: :df_width 143 | 144 | @spec hstack_mut(t() | {:ok, t()}, list(s() | {:ok, s()})) :: {:ok, {}} | {:error, term()} 145 | def hstack_mut({:ok, df}, cols), do: hstack_mut(df, cols) 146 | defdelegate hstack_mut(df, cols), to: Native, as: :df_hstack_mut 147 | 148 | @spec hstack(t() | {:ok, t()}, list(s() | {:ok, s()})) :: {:ok, t()} | {:error, term()} 149 | def hstack({:ok, df}, cols), do: hstack(df, cols) 150 | defdelegate hstack(df, cols), to: Native, as: :df_hstack 151 | 152 | @spec vstack(t() | {:ok, t()}, t() | {:ok, t()}) :: {:ok, {}} | {:error, term()} 153 | def vstack({:ok, df}, other), do: vstack(df, other) 154 | defdelegate vstack(df, other), to: Native, as: :df_vstack 155 | 156 | @spec drop_in_place(t() | {:ok, t()}, String.t()) :: {:ok, s()} | {:error, term()} 157 | def drop_in_place({:ok, df}, name), do: drop_in_place(df, name) 158 | defdelegate drop_in_place(df, name), to: Native, as: :df_drop_in_place 159 | 160 | @spec drop_nulls(t() | {:ok, t()}, list(String.t()) | nil) :: {:ok, t()} | {:error, term()} 161 | def drop_nulls({:ok, df}, subset), do: drop_nulls(df, subset) 162 | defdelegate drop_nulls(df, subset), to: Native, as: :df_drop_nulls 163 | 164 | @spec drop(t() | {:ok, t()}, String.t()) :: {:ok, t()} | {:error, term()} 165 | def drop({:ok, df}, name), do: drop(df, name) 166 | defdelegate drop(df, name), to: Native, as: :df_drop 167 | 168 | @spec select_at_idx(t() | {:ok, t()}, integer()) :: {:ok, s() | nil} | {:error, term()} 169 | def select_at_idx({:ok, df}, idx), do: select_at_idx(df, idx) 170 | defdelegate select_at_idx(df, idx), to: Native, as: :df_select_at_idx 171 | 172 | @spec find_idx_by_name(t() | {:ok, t()}, String.t()) :: 173 | {:ok, integer() | nil} | {:error, term()} 174 | def find_idx_by_name({:ok, df}, name), do: find_idx_by_name(df, name) 175 | defdelegate find_idx_by_name(df, name), to: Native, as: :df_find_idx_by_name 176 | 177 | @spec column(t() | {:ok, t()}, String.t()) :: {:ok, s() | nil} | {:error, term()} 178 | def column({:ok, df}, name), do: column(df, name) 179 | defdelegate column(df, name), to: Native, as: :df_column 180 | 181 | @spec select(t() | {:ok, t()}, list(String.t())) :: {:ok, t()} | {:error, term()} 182 | def select({:ok, df}, selection), do: select(df, selection) 183 | defdelegate select(df, selection), to: Native, as: :df_select 184 | 185 | @spec filter(t() | {:ok, t()}, s() | {:ok, s()}) :: {:ok, t()} | {:error, term()} 186 | def filter({:ok, df}, {:ok, mask}), do: filter(df, mask) 187 | def filter(df, {:ok, mask}), do: filter(df, mask) 188 | def filter({:ok, df}, mask), do: filter(df, mask) 189 | defdelegate filter(df, mask), to: Native, as: :df_filter 190 | 191 | @spec take(t() | {:ok, t()}, list(integer())) :: {:ok, t()} | {:error, term()} 192 | def take({:ok, df}, indices), do: take(df, indices) 193 | defdelegate take(df, indices), to: Native, as: :df_take 194 | 195 | @spec take_with_series(t() | {:ok, t()}, s() | {:ok, s()}) :: {:ok, t()} | {:error, term()} 196 | def take_with_series({:ok, df}, {:ok, indices}), do: take_with_series(df, indices) 197 | def take_with_series(df, {:ok, indices}), do: take_with_series(df, indices) 198 | def take_with_series({:ok, df}, indices), do: take_with_series(df, indices) 199 | defdelegate take_with_series(df, indices), to: Native, as: :df_take_with_series 200 | 201 | @spec replace(t() | {:ok, t()}, String.t(), s() | {:ok, s()}) :: {:ok, {}} | {:error, term()} 202 | def replace({:ok, df}, col, {:ok, new_col}), do: replace(df, col, new_col) 203 | def replace(df, col, {:ok, new_col}), do: replace(df, col, new_col) 204 | def replace({:ok, df}, col, new_col), do: replace(df, col, new_col) 205 | defdelegate replace(df, col, new_col), to: Native, as: :df_replace 206 | 207 | @spec replace_at_idx(t() | {:ok, t()}, integer(), s() | {:ok, s()}) :: 208 | {:ok, {}} | {:error, term()} 209 | def replace_at_idx({:ok, df}, index, {:ok, new_col}), do: replace_at_idx(df, index, new_col) 210 | def replace_at_idx(df, index, {:ok, new_col}), do: replace_at_idx(df, index, new_col) 211 | def replace_at_idx({:ok, df}, index, new_col), do: replace_at_idx(df, index, new_col) 212 | defdelegate replace_at_idx(df, index, new_col), to: Native, as: :df_replace_at_idx 213 | 214 | @spec insert_at_idx(t() | {:ok, t()}, integer(), s() | {:ok, s()}) :: 215 | {:ok, {}} | {:error, term()} 216 | def insert_at_idx({:ok, df}, index, {:ok, new_col}), do: insert_at_idx(df, index, new_col) 217 | def insert_at_idx(df, index, {:ok, new_col}), do: insert_at_idx(df, index, new_col) 218 | def insert_at_idx({:ok, df}, index, new_col), do: insert_at_idx(df, index, new_col) 219 | defdelegate insert_at_idx(df, index, new_col), to: Native, as: :df_insert_at_idx 220 | 221 | @spec slice(t() | {:ok, t()}, integer(), integer()) :: {:ok, t()} | {:error, term()} 222 | def slice({:ok, df}, offset, length), do: slice(df, offset, length) 223 | defdelegate slice(df, offset, length), to: Native, as: :df_slice 224 | 225 | @spec head(t() | {:ok, t()}, integer()) :: {:ok, t()} | {:error, term()} 226 | def head(df, length \\ 5) 227 | def head({:ok, df}, length), do: head(df, length) 228 | defdelegate head(df, length), to: Native, as: :df_head 229 | 230 | @spec tail(t() | {:ok, t()}, integer()) :: {:ok, t()} | {:error, term()} 231 | def tail(df, length \\ 5) 232 | def tail({:ok, df}, length), do: tail(df, length) 233 | defdelegate tail(df, length), to: Native, as: :df_tail 234 | 235 | @spec is_unique(t() | {:ok, t()}) :: {:ok, s()} | {:error, term()} 236 | @doc """ 237 | Get a mask of all unique rows in this DataFrame 238 | """ 239 | def is_unique({:ok, df}), do: is_unique(df) 240 | defdelegate is_unique(df), to: Native, as: :df_is_unique 241 | 242 | @spec is_duplicated(t() | {:ok, t()}) :: {:ok, s()} | {:error, term()} 243 | @doc """ 244 | Get a mask of all duplicated rows in this DataFrame 245 | """ 246 | def is_duplicated({:ok, df}), do: is_duplicated(df) 247 | defdelegate is_duplicated(df), to: Native, as: :df_is_duplicated 248 | 249 | @spec equal(t() | {:ok, t()}, t() | {:ok, t()}, boolean()) :: 250 | {:ok, boolean()} | {:error, term()} 251 | @doc """ 252 | Check if DataFrame is equal to other. 253 | 254 | Parameters 255 | ---------- 256 | df: DataFrame 257 | other: DataFrame to compare with. 258 | null_equal: Consider null values as equal. 259 | """ 260 | def equal(df, other, null_equal \\ false) 261 | def equal({:ok, df}, {:ok, other}, null_equal), do: equal(df, other, null_equal) 262 | def equal(df, {:ok, other}, null_equal), do: equal(df, other, null_equal) 263 | def equal({:ok, df}, other, null_equal), do: equal(df, other, null_equal) 264 | defdelegate equal(df, other, null_equal), to: Native, as: :df_frame_equal 265 | 266 | @spec groupby(t() | {:ok, t()}, list(String.t()), list(String.t()) | nil, String.t()) :: 267 | {:ok, t()} | {:error, term()} 268 | def groupby({:ok, df}, by, sel, agg), do: groupby(df, by, sel, agg) 269 | defdelegate groupby(df, by, sel, agg), to: Native, as: :df_groupby 270 | 271 | @spec groupby_agg( 272 | t() | {:ok, t()}, 273 | list(String.t()), 274 | %{String.t() => list(String.t())} | list({String.t(), list(String.t())}) 275 | ) :: 276 | {:ok, t()} | {:error, term()} 277 | @doc """ 278 | Use multiple aggregations on columns 279 | 280 | Parameters 281 | ---------- 282 | column_to_agg 283 | map column to aggregation functions 284 | 285 | Examples: 286 | [{"foo", ["sum", "n_unique", "min"]}, 287 | {"bar": ["max"]}] 288 | 289 | {"foo": ["sum", "n_unique", "min"], 290 | "bar": "max"} 291 | 292 | Returns 293 | ------- 294 | Result of groupby split apply operations. 295 | """ 296 | def groupby_agg({:ok, df}, by, column_to_agg), do: groupby_agg(df, by, column_to_agg) 297 | 298 | def groupby_agg(df, by, column_to_agg) when is_map(column_to_agg), 299 | do: groupby_agg(df, by, Enum.into(column_to_agg, [])) 300 | 301 | def groupby_agg(df, by, column_to_agg) when is_list(column_to_agg), 302 | do: Native.df_groupby_agg(df, by, column_to_agg) 303 | 304 | @spec groupby_quantile(t() | {:ok, t()}, list(String.t()), list(String.t()), float()) :: 305 | {:ok, t()} | {:error, term()} 306 | @doc """ 307 | Count the unique values per group. 308 | """ 309 | def groupby_quantile({:ok, df}, by, sel, quant), do: groupby_quantile(df, by, sel, quant) 310 | defdelegate groupby_quantile(df, by, sel, quant), to: Native, as: :df_groupby_quantile 311 | 312 | @spec pivot(t() | {:ok, t()}, list(String.t()), String.t(), String.t(), String.t()) :: 313 | {:ok, t()} | {:error, term()} 314 | @doc """ 315 | Do a pivot operation based on the group key, a pivot column and an aggregation function on the values column. 316 | 317 | Parameters 318 | ---------- 319 | pivot_column 320 | Column to pivot. 321 | values_column 322 | Column that will be aggregated 323 | """ 324 | def pivot({:ok, df}, by, pivot_column, values_column, agg), 325 | do: pivot(df, by, pivot_column, values_column, agg) 326 | 327 | defdelegate pivot(df, by, pivot_column, values_column, agg), to: Native, as: :df_pivot 328 | 329 | @spec clone(t() | {:ok, t()}) :: {:ok, t()} | {:error, term()} 330 | def clone({:ok, df}), do: clone(df) 331 | defdelegate clone(df), to: Native, as: :df_clone 332 | 333 | @spec explode(t() | {:ok, t()}, list(String.t())) :: {:ok, t()} | {:error, term()} 334 | @doc """ 335 | Explode `DataFrame` to long format by exploding a column with Lists. 336 | 337 | Parameters 338 | ---------- 339 | columns 340 | Column of LargeList type 341 | 342 | Returns 343 | ------- 344 | DataFrame 345 | """ 346 | def explode({:ok, df}, cols), do: explode(df, cols) 347 | defdelegate explode(df, cols), to: Native, as: :df_explode 348 | 349 | @spec melt(t() | {:ok, t()}, list(String.t()), list(String.t())) :: 350 | {:ok, t()} | {:error, term()} 351 | @doc """ 352 | Unpivot DataFrame to long format. 353 | 354 | Parameters 355 | ---------- 356 | id_vars 357 | Columns to use as identifier variables 358 | 359 | value_vars 360 | Values to use as identifier variables 361 | 362 | Returns 363 | ------- 364 | 365 | """ 366 | def melt({:ok, df}, id_vars, value_vars), do: melt(df, id_vars, value_vars) 367 | defdelegate melt(df, id_vars, value_vars), to: Native, as: :df_melt 368 | 369 | @spec shift(t() | {:ok, t()}, integer()) :: {:ok, t()} | {:error, term()} 370 | @doc """ 371 | Shift the values by a given period and fill the parts that will be empty due to this operation 372 | with `Nones`. 373 | 374 | Parameters 375 | ---------- 376 | periods 377 | Number of places to shift (may be negative). 378 | """ 379 | def shift({:ok, df}, periods), do: shift(df, periods) 380 | defdelegate shift(df, periods), to: Native, as: :df_shift 381 | 382 | @spec drop_duplicates(t() | {:ok, t()}, boolean(), list(String.t()) | nil) :: 383 | {:ok, t()} | {:error, term()} 384 | @doc """ 385 | Drop duplicate rows from this DataFrame. 386 | Note that this fails if there is a column of type `List` in the DataFrame. 387 | """ 388 | def drop_duplicates(df, maintain_order \\ true, subset \\ nil) 389 | 390 | def drop_duplicates({:ok, df}, maintain_order, subset), 391 | do: drop_duplicates(df, maintain_order, subset) 392 | 393 | defdelegate drop_duplicates(df, maintain_order, subset), 394 | to: Native, 395 | as: :df_drop_duplicates 396 | 397 | @spec max(t() | {:ok, t()}) :: {:ok, t()} | {:error, term()} 398 | def max({:ok, df}), do: max(df) 399 | defdelegate max(df), to: Native, as: :df_max 400 | 401 | @spec min(t() | {:ok, t()}) :: {:ok, t()} | {:error, term()} 402 | def min({:ok, df}), do: min(df) 403 | defdelegate min(df), to: Native, as: :df_min 404 | 405 | @spec sum(t() | {:ok, t()}) :: {:ok, t()} | {:error, term()} 406 | def sum({:ok, df}), do: sum(df) 407 | defdelegate sum(df), to: Native, as: :df_sum 408 | 409 | @spec mean(t() | {:ok, t()}) :: {:ok, t()} | {:error, term()} 410 | def mean({:ok, df}), do: mean(df) 411 | defdelegate mean(df), to: Native, as: :df_mean 412 | 413 | @spec std(t() | {:ok, t()}) :: {:ok, t()} | {:error, term()} 414 | def std({:ok, df}), do: std(df) 415 | defdelegate std(df), to: Native, as: :df_stdev 416 | 417 | @spec var(t() | {:ok, t()}) :: {:ok, t()} | {:error, term()} 418 | def var({:ok, df}), do: var(df) 419 | defdelegate var(df), to: Native, as: :df_var 420 | 421 | @spec median(t() | {:ok, t()}) :: {:ok, t()} | {:error, term()} 422 | def median({:ok, df}), do: median(df) 423 | defdelegate median(df), to: Native, as: :df_median 424 | 425 | @spec quantile(t() | {:ok, t()}, float()) :: {:ok, t()} | {:error, term()} 426 | def quantile({:ok, df}, quant), do: quantile(df, quant) 427 | defdelegate quantile(df, quant), to: Native, as: :df_quantile 428 | 429 | @spec to_dummies(t() | {:ok, t()}) :: {:ok, t()} | {:error, term()} 430 | def to_dummies({:ok, df}), do: to_dummies(df) 431 | defdelegate to_dummies(df), to: Native, as: :df_to_dummies 432 | 433 | @spec sample(t() | {:ok, t()}, integer() | float(), boolean()) :: {:ok, t()} | {:error, term()} 434 | def sample(df, n_or_frac, with_replacement \\ false) 435 | def sample({:ok, df}, n_or_frac, with_replacement), do: sample(df, n_or_frac, with_replacement) 436 | 437 | def sample(df, n_or_frac, with_replacement) do 438 | case is_integer(n_or_frac) do 439 | true -> Native.df_sample_n(df, n_or_frac, with_replacement) 440 | _ -> Native.df_sample_frac(df, n_or_frac, with_replacement) 441 | end 442 | end 443 | 444 | @spec sort(t() | {:ok, t()}, String.t(), boolean(), boolean()) :: {:ok, t()} | {:error, term()} 445 | def sort(df, by_column, inplace \\ false, reverse \\ false) 446 | def sort({:ok, df}, by_column, inplace, reverse), do: sort(df, by_column, inplace, reverse) 447 | 448 | def sort(df, by_column, inplace, reverse) do 449 | case inplace do 450 | true -> Native.df_sort_in_place(df, by_column, reverse) 451 | _ -> Native.df_sort_new(df, by_column, reverse) 452 | end 453 | end 454 | 455 | # custom functionalities 456 | @spec dtype(t() | {:ok, t()}, String.t()) :: String.t() | {:error, term()} 457 | def dtype(df, name, type \\ :str) do 458 | s = column(df, name) 459 | 460 | case type do 461 | :vega -> S.dtype_vega(s) 462 | _ -> S.dtype_str(s) 463 | end 464 | end 465 | 466 | @doc """ 467 | """ 468 | @spec set( 469 | t() | {:ok, t()}, 470 | String.t() | integer() | {String.t() | integer(), String.t()}, 471 | s() | {:ok, s()} 472 | ) :: {:ok, t()} | {:error, term()} 473 | def set({:ok, df}, key, {:ok, value}), do: set(df, key, value) 474 | def set(df, key, {:ok, value}), do: set(df, key, value) 475 | def set({:ok, df}, key, value), do: set(df, key, value) 476 | # df["foo"] = value 477 | def set(df, key, value) when is_binary(key) do 478 | case drop_in_place(df, key) do 479 | {:ok, _s} -> hstack_mut(df, [value]) 480 | _ -> hstack_mut(df, [value]) 481 | end 482 | end 483 | 484 | # df[idx] = value 485 | def set(df, key, value) when is_integer(key) do 486 | replace_at_idx(df, key, value) 487 | end 488 | 489 | # df[a, b] = value 490 | def set(_df, {_row, _col}, _value) do 491 | raise "Not implemented" 492 | end 493 | 494 | @spec set(t() | {:ok, t()}, String.t(), String.t()) :: {:ok, {}} | {:error, term()} 495 | def parse_date(df, name, format \\ "%Y/%m/%d") do 496 | with {:ok, s} <- drop_in_place(df, name), 497 | {:ok, s} <- S.str_parse_date32(s, format) do 498 | hstack_mut(df, [s]) 499 | else 500 | e -> e 501 | end 502 | end 503 | 504 | # plotting 505 | defdelegate plot_by_type(df, type, opts), to: Plot, as: :plot_by_type 506 | defdelegate plot_single(df, mark, x, y, opts \\ []), to: Plot, as: :plot_single 507 | defdelegate plot_repeat(df, mark, rows, colums, opts \\ []), to: Plot, as: :plot_repeat 508 | end 509 | 510 | defimpl Inspect, for: ExPolars.DataFrame do 511 | alias ExPolars.Native 512 | 513 | def inspect(data, _opts) do 514 | case Native.df_as_str(data) do 515 | {:ok, s} -> s 516 | _ -> "Cannot output dataframe" 517 | end 518 | end 519 | end 520 | -------------------------------------------------------------------------------- /lib/ex_polars/native.ex: -------------------------------------------------------------------------------- 1 | defmodule ExPolars.Native do 2 | @moduledoc """ 3 | Documentation for `Native`. 4 | """ 5 | 6 | use Rustler, otp_app: :ex_polars, crate: :expolars 7 | 8 | defstruct [:inner] 9 | 10 | def df_read_csv( 11 | _filename, 12 | _infer_schema_length \\ 100, 13 | _batch_size \\ 64, 14 | _has_header \\ true, 15 | _ignore_errors \\ false, 16 | _stop_after_n_rows \\ nil, 17 | _skip_rows \\ 0, 18 | _projection \\ nil, 19 | _sep \\ ",", 20 | _rechunk \\ true, 21 | _columns \\ nil, 22 | _encoding \\ "utf8" 23 | ), 24 | do: err() 25 | 26 | def df_read_parquet(_filename), do: err() 27 | def df_read_json(_filename, _type), do: err() 28 | 29 | def df_to_csv(_df, _batch_size \\ 100_000, _has_headers \\ true, _delimiter \\ ?,), 30 | do: err() 31 | 32 | def df_to_csv_file( 33 | _df, 34 | _filename, 35 | _batch_size \\ 100_000, 36 | _has_headers \\ true, 37 | _delimiter \\ ?, 38 | ), 39 | do: err() 40 | 41 | def df_as_str(_df), do: err() 42 | 43 | def df_add(_df, _s), do: err() 44 | def df_sub(_df, _s), do: err() 45 | def df_div(_df, _s), do: err() 46 | def df_mul(_df, _s), do: err() 47 | def df_rem(_df, _s), do: err() 48 | def df_sample_n(_df, _n, _with_replacement), do: err() 49 | def df_sample_frac(_df, _f, _with_replacement), do: err() 50 | def df_rechunk(_df), do: err() 51 | def df_fill_none(_df, _strategy), do: err() 52 | def df_join(_df, _other, _left_on, _right_on, _how), do: err() 53 | def df_get_columns(_df), do: err() 54 | def df_columns(_def), do: err() 55 | def df_set_column_names(_df, _names), do: err() 56 | def df_dtypes(_df), do: err() 57 | def df_n_chunks(_df), do: err() 58 | def df_shape(_df), do: err() 59 | def df_height(_df), do: err() 60 | def df_width(_df), do: err() 61 | def df_hstack_mut(_df, _cols), do: err() 62 | def df_hstack(_df, _cols), do: err() 63 | def df_vstack(_df, _other), do: err() 64 | def df_drop_in_place(_df, _name), do: err() 65 | def df_drop_nulls(_df, _subset), do: err() 66 | def df_drop(_df, _name), do: err() 67 | def df_select_at_idx(_df, _idx), do: err() 68 | def df_find_idx_by_name(_df, _name), do: err() 69 | def df_column(_df, _name), do: err() 70 | def df_select(_df, _selection), do: err() 71 | def df_filter(_df, _mask), do: err() 72 | def df_take(_df, _indices), do: err() 73 | def df_take_with_series(_df, _indices), do: err() 74 | def df_sort_new(_df, _by_column, _reverse), do: err() 75 | def df_sort_in_place(_df, _by_column, _reverse), do: err() 76 | def df_replace(_df, _col, _new_col), do: err() 77 | def df_replace_at_idx(_df, _index, _new_col), do: err() 78 | def df_insert_at_idx(_df, _index, _new_col), do: err() 79 | def df_slice(_df, _offset, _length), do: err() 80 | def df_head(_df, _length \\ 5), do: err() 81 | def df_tail(_df, _length \\ 5), do: err() 82 | def df_is_unique(_df), do: err() 83 | def df_is_duplicated(_df), do: err() 84 | def df_frame_equal(_df, _other, _null_equal \\ false), do: err() 85 | def df_groupby(_df, _by, _sel, _agg), do: err() 86 | def df_groupby_agg(_df, _by, _column_to_agg), do: err() 87 | def df_groupby_quantile(_df, _by, _sel, _quant), do: err() 88 | def df_pivot(_df, _by, _pivot_column, _values_column, _agg), do: err() 89 | def df_clone(_df), do: err() 90 | def df_explode(_df, _cols), do: err() 91 | def df_melt(_df, _id_vars, _value_vars), do: err() 92 | def df_shift(_df, _periods), do: err() 93 | def df_drop_duplicates(_df, _maintain_order \\ true, _subset \\ nil), do: err() 94 | def df_max(_df), do: err() 95 | def df_min(_df), do: err() 96 | def df_sum(_df), do: err() 97 | def df_mean(_df), do: err() 98 | def df_stdev(_df), do: err() 99 | def df_var(_df), do: err() 100 | def df_median(_df), do: err() 101 | def df_quantile(_df, _quant), do: err() 102 | def df_to_dummies(_df), do: err() 103 | 104 | # Series 105 | def s_as_str(_s), do: err() 106 | def s_new_i8(_name, _val), do: err() 107 | def s_new_i16(_name, _val), do: err() 108 | def s_new_i32(_name, _val), do: err() 109 | def s_new_i64(_name, _val), do: err() 110 | def s_new_bool(_name, _val), do: err() 111 | def s_new_u8(_name, _val), do: err() 112 | def s_new_u16(_name, _val), do: err() 113 | def s_new_u32(_name, _val), do: err() 114 | def s_new_u64(_name, _val), do: err() 115 | def s_new_date32(_name, _val), do: err() 116 | def s_new_date64(_name, _val), do: err() 117 | def s_new_duration_ns(_name, _val), do: err() 118 | def s_new_f32(_name, _val), do: err() 119 | def s_new_f64(_name, _val), do: err() 120 | def s_parse_date32_from_str_slice(_name, _val, _fmt), do: err() 121 | def s_new_str(_name, _val), do: err() 122 | def s_rechunk(_s), do: err() 123 | def s_chunk_lengths(_s), do: err() 124 | def s_name(_s), do: err() 125 | def s_rename(_s, _name), do: err() 126 | def s_dtype(_s), do: err() 127 | def s_n_chunks(_s), do: err() 128 | def s_limit(_s, _num_elem), do: err() 129 | def s_slice(_s, _offset, _length), do: err() 130 | def s_append(_s, _other), do: err() 131 | def s_filter(_s, _filter), do: err() 132 | def s_add(_s, _other), do: err() 133 | def s_sub(_s, _other), do: err() 134 | def s_mul(_s, _other), do: err() 135 | def s_div(_s, _other), do: err() 136 | def s_head(_s, _length), do: err() 137 | def s_tail(_s, _length), do: err() 138 | def s_sort(_s, _reverse), do: err() 139 | def s_argsort(_s, _reverse), do: err() 140 | def s_unique(_s), do: err() 141 | def s_value_counts(_s), do: err() 142 | def s_arg_unique(_s), do: err() 143 | def s_take(_s, _indeces), do: err() 144 | def s_take_with_series(_s, _indeces), do: err() 145 | def s_null_count(_s), do: err() 146 | def s_is_null(_s), do: err() 147 | def s_is_not_null(_s), do: err() 148 | def s_is_unique(_s), do: err() 149 | def s_arg_true(_s), do: err() 150 | def s_sample_n(_s, _n, _with_replacement), do: err() 151 | def s_sample_frac(_s, _frac, _with_replacement), do: err() 152 | def s_is_duplicated(_s), do: err() 153 | def s_explode(_s), do: err() 154 | def s_take_every(_s, _n), do: err() 155 | def s_series_equal(_s, _other, _null_equal \\ false), do: err() 156 | def s_eq(_s, _rhs), do: err() 157 | def s_neq(_s, _rhs), do: err() 158 | def s_gt(_s, _rhs), do: err() 159 | def s_gt_eq(_s, _rhs), do: err() 160 | def s_lt(_s, _rhs), do: err() 161 | def s_lt_eq(_s, _rhs), do: err() 162 | def s_not(_s), do: err() 163 | def s_len(_s), do: err() 164 | def s_drop_nulls(_s), do: err() 165 | def s_fill_none(_s, _strategy), do: err() 166 | def s_clone(_s), do: err() 167 | def s_shift(_s, _periods), do: err() 168 | def s_zip_with(_s, _mask, _other), do: err() 169 | def s_str_lengths(_s), do: err() 170 | def s_str_contains(_s, _pat), do: err() 171 | def s_str_replace(_s, _pat, _val), do: err() 172 | def s_str_replace_all(_s, _pat, _val), do: err() 173 | def s_str_to_uppercase(_s), do: err() 174 | def s_str_to_lowercase(_s), do: err() 175 | def s_str_parse_date32(_s, _fmt), do: err() 176 | def s_str_parse_date64(_s, _fmt), do: err() 177 | def s_datetime_str_fmt(_s, _fmt), do: err() 178 | def s_as_duration(_s), do: err() 179 | def s_to_dummies(_s), do: err() 180 | def s_get_list(_s, _index), do: err() 181 | def s_rolling_sum(_s, _window_size, _weight, _ignore_null), do: err() 182 | def s_rolling_mean(_s, _window_size, _weight, _ignore_null), do: err() 183 | def s_rolling_max(_s, _window_size, _weight, _ignore_null), do: err() 184 | def s_rolling_min(_s, _window_size, _weight, _ignore_null), do: err() 185 | def s_year(_s), do: err() 186 | def s_month(_s), do: err() 187 | def s_day(_s), do: err() 188 | def s_ordinal_day(_s), do: err() 189 | def s_hour(_s), do: err() 190 | def s_minute(_s), do: err() 191 | def s_second(_s), do: err() 192 | def s_nanosecond(_s), do: err() 193 | def s_set_with_mask_str(_s, _filter, _value), do: err() 194 | def s_set_with_mask_f64(_s, _filter, _value), do: err() 195 | def s_set_with_mask_f32(_s, _filter, _value), do: err() 196 | def s_set_with_mask_u8(_s, _filter, _value), do: err() 197 | def s_set_with_mask_u16(_s, _filter, _value), do: err() 198 | def s_set_with_mask_u32(_s, _filter, _value), do: err() 199 | def s_set_with_mask_u64(_s, _filter, _value), do: err() 200 | def s_set_with_mask_i8(_s, _filter, _value), do: err() 201 | def s_set_with_mask_i16(_s, _filter, _value), do: err() 202 | def s_set_with_mask_i32(_s, _filter, _value), do: err() 203 | def s_set_with_mask_i64(_s, _filter, _value), do: err() 204 | def s_get_f32(_s, _index), do: err() 205 | def s_get_f64(_s, _index), do: err() 206 | def s_get_u8(_s, _index), do: err() 207 | def s_get_u16(_s, _index), do: err() 208 | def s_get_u32(_s, _index), do: err() 209 | def s_get_u64(_s, _index), do: err() 210 | def s_get_i8(_s, _index), do: err() 211 | def s_get_i16(_s, _index), do: err() 212 | def s_get_i32(_s, _index), do: err() 213 | def s_get_i64(_s, _index), do: err() 214 | def s_get_str(_s, _index), do: err() 215 | def s_get_date32(_s, _index), do: err() 216 | def s_get_date64(_s, _index), do: err() 217 | def s_cast_u8(_s), do: err() 218 | def s_cast_u16(_s), do: err() 219 | def s_cast_u32(_s), do: err() 220 | def s_cast_u64(_s), do: err() 221 | def s_cast_i8(_s), do: err() 222 | def s_cast_i16(_s), do: err() 223 | def s_cast_i32(_s), do: err() 224 | def s_cast_i64(_s), do: err() 225 | def s_cast_f32(_s), do: err() 226 | def s_cast_f64(_s), do: err() 227 | def s_cast_date32(_s), do: err() 228 | def s_cast_date64(_s), do: err() 229 | def s_cast_time64ns(_s), do: err() 230 | def s_cast_duration_ns(_s), do: err() 231 | def s_cast_str(_s), do: err() 232 | def s_add_i64(_s, _other), do: err() 233 | def s_sub_i64(_s, _other), do: err() 234 | def s_mul_i64(_s, _other), do: err() 235 | def s_div_i64(_s, _other), do: err() 236 | def s_add_f64(_s, _other), do: err() 237 | def s_sub_f64(_s, _other), do: err() 238 | def s_mul_f64(_s, _other), do: err() 239 | def s_div_f64(_s, _other), do: err() 240 | def s_add_i64_rhs(_s, _other), do: err() 241 | def s_sub_i64_rhs(_s, _other), do: err() 242 | def s_mul_i64_rhs(_s, _other), do: err() 243 | def s_div_i64_rhs(_s, _other), do: err() 244 | def s_add_f64_rhs(_s, _other), do: err() 245 | def s_sub_f64_rhs(_s, _other), do: err() 246 | def s_mul_f64_rhs(_s, _other), do: err() 247 | def s_div_f64_rhs(_s, _other), do: err() 248 | def s_sum_u8(_s), do: err() 249 | def s_sum_u16(_s), do: err() 250 | def s_sum_u32(_s), do: err() 251 | def s_sum_u64(_s), do: err() 252 | def s_sum_i8(_s), do: err() 253 | def s_sum_i16(_s), do: err() 254 | def s_sum_i32(_s), do: err() 255 | def s_sum_i64(_s), do: err() 256 | def s_sum_f32(_s), do: err() 257 | def s_sum_f64(_s), do: err() 258 | 259 | def s_min_u8(_s), do: err() 260 | def s_min_u16(_s), do: err() 261 | def s_min_u32(_s), do: err() 262 | def s_min_u64(_s), do: err() 263 | def s_min_i8(_s), do: err() 264 | def s_min_i16(_s), do: err() 265 | def s_min_i32(_s), do: err() 266 | def s_min_i64(_s), do: err() 267 | def s_min_f32(_s), do: err() 268 | def s_min_f64(_s), do: err() 269 | 270 | def s_max_u8(_s), do: err() 271 | def s_max_u16(_s), do: err() 272 | def s_max_u32(_s), do: err() 273 | def s_max_u64(_s), do: err() 274 | def s_max_i8(_s), do: err() 275 | def s_max_i16(_s), do: err() 276 | def s_max_i32(_s), do: err() 277 | def s_max_i64(_s), do: err() 278 | def s_max_f32(_s), do: err() 279 | def s_max_f64(_s), do: err() 280 | 281 | def s_mean_u8(_s), do: err() 282 | def s_mean_u16(_s), do: err() 283 | def s_mean_u32(_s), do: err() 284 | def s_mean_u64(_s), do: err() 285 | def s_mean_i8(_s), do: err() 286 | def s_mean_i16(_s), do: err() 287 | def s_mean_i32(_s), do: err() 288 | def s_mean_i64(_s), do: err() 289 | def s_mean_f32(_s), do: err() 290 | def s_mean_f64(_s), do: err() 291 | 292 | def s_eq_u8(_s, _rhs), do: err() 293 | def s_neq_u8(_s, _rhs), do: err() 294 | def s_gt_u8(_s, _rhs), do: err() 295 | def s_lt_u8(_s, _rhs), do: err() 296 | def s_gt_eq_u8(_s, _rhs), do: err() 297 | def s_lt_eq_u8(_s, _rhs), do: err() 298 | 299 | def s_eq_u16(_s, _rhs), do: err() 300 | def s_neq_u16(_s, _rhs), do: err() 301 | def s_gt_u16(_s, _rhs), do: err() 302 | def s_lt_u16(_s, _rhs), do: err() 303 | def s_gt_eq_u16(_s, _rhs), do: err() 304 | def s_lt_eq_u16(_s, _rhs), do: err() 305 | 306 | def s_eq_u32(_s, _rhs), do: err() 307 | def s_neq_u32(_s, _rhs), do: err() 308 | def s_gt_u32(_s, _rhs), do: err() 309 | def s_lt_u32(_s, _rhs), do: err() 310 | def s_gt_eq_u32(_s, _rhs), do: err() 311 | def s_lt_eq_u32(_s, _rhs), do: err() 312 | 313 | def s_eq_u64(_s, _rhs), do: err() 314 | def s_neq_u64(_s, _rhs), do: err() 315 | def s_gt_u64(_s, _rhs), do: err() 316 | def s_lt_u64(_s, _rhs), do: err() 317 | def s_gt_eq_u64(_s, _rhs), do: err() 318 | def s_lt_eq_u64(_s, _rhs), do: err() 319 | 320 | def s_eq_i8(_s, _rhs), do: err() 321 | def s_neq_i8(_s, _rhs), do: err() 322 | def s_gt_i8(_s, _rhs), do: err() 323 | def s_lt_i8(_s, _rhs), do: err() 324 | def s_gt_eq_i8(_s, _rhs), do: err() 325 | def s_lt_eq_i8(_s, _rhs), do: err() 326 | 327 | def s_eq_i16(_s, _rhs), do: err() 328 | def s_neq_i16(_s, _rhs), do: err() 329 | def s_gt_i16(_s, _rhs), do: err() 330 | def s_lt_i16(_s, _rhs), do: err() 331 | def s_gt_eq_i16(_s, _rhs), do: err() 332 | def s_lt_eq_i16(_s, _rhs), do: err() 333 | 334 | def s_eq_i32(_s, _rhs), do: err() 335 | def s_neq_i32(_s, _rhs), do: err() 336 | def s_gt_i32(_s, _rhs), do: err() 337 | def s_lt_i32(_s, _rhs), do: err() 338 | def s_gt_eq_i32(_s, _rhs), do: err() 339 | def s_lt_eq_i32(_s, _rhs), do: err() 340 | 341 | def s_eq_i64(_s, _rhs), do: err() 342 | def s_neq_i64(_s, _rhs), do: err() 343 | def s_gt_i64(_s, _rhs), do: err() 344 | def s_lt_i64(_s, _rhs), do: err() 345 | def s_gt_eq_i64(_s, _rhs), do: err() 346 | def s_lt_eq_i64(_s, _rhs), do: err() 347 | 348 | def s_eq_f32(_s, _rhs), do: err() 349 | def s_neq_f32(_s, _rhs), do: err() 350 | def s_gt_f32(_s, _rhs), do: err() 351 | def s_lt_f32(_s, _rhs), do: err() 352 | def s_gt_eq_f32(_s, _rhs), do: err() 353 | def s_lt_eq_f32(_s, _rhs), do: err() 354 | 355 | def s_eq_f64(_s, _rhs), do: err() 356 | def s_neq_f64(_s, _rhs), do: err() 357 | def s_gt_f64(_s, _rhs), do: err() 358 | def s_lt_f64(_s, _rhs), do: err() 359 | def s_gt_eq_f64(_s, _rhs), do: err() 360 | def s_lt_eq_f64(_s, _rhs), do: err() 361 | 362 | def s_eq_str(_s, _rhs), do: err() 363 | def s_neq_str(_s, _rhs), do: err() 364 | def s_gt_str(_s, _rhs), do: err() 365 | def s_lt_str(_s, _rhs), do: err() 366 | def s_gt_eq_str(_s, _rhs), do: err() 367 | def s_lt_eq_str(_s, _rhs), do: err() 368 | def s_to_json(_s), do: err() 369 | 370 | defp err, do: :erlang.nif_error(:nif_not_loaded) 371 | end 372 | -------------------------------------------------------------------------------- /lib/ex_polars/plot.ex: -------------------------------------------------------------------------------- 1 | defmodule ExPolars.Plot do 2 | @moduledoc """ 3 | Plotting tools 4 | """ 5 | 6 | alias ExPolars.DataFrame, as: DF 7 | alias Deneb.{Chart, Encoding, Mark, Plot} 8 | 9 | def plot_by_type(df, type, opts \\ []) do 10 | {:ok, csv} = DF.to_csv(df) 11 | apply(Plot, type, [csv, opts]) 12 | end 13 | 14 | def plot_single(df, mark, x, y, opts \\ []) do 15 | default = [width: 800, height: 600] 16 | {color, opts} = get_color(df, opts) 17 | opts = Keyword.merge(default, opts) 18 | xtype = DF.dtype(df, x, :vega) 19 | ytype = DF.dtype(df, y, :vega) 20 | 21 | {:ok, csv} = DF.to_csv(df) 22 | 23 | mark 24 | |> Mark.new(true) 25 | |> Chart.new( 26 | Encoding.new(%{ 27 | x: %{field: x, type: xtype}, 28 | y: %{field: y, type: ytype}, 29 | color: color 30 | }) 31 | ) 32 | |> Chart.to_json(opts) 33 | |> Deneb.to_json(csv) 34 | end 35 | 36 | def plot_repeat(df, mark, rows, columns, opts \\ []) 37 | 38 | def plot_repeat(df, mark, rows, columns, opts) when is_list(rows) and is_list(columns) do 39 | {color, opts} = get_color(df, opts) 40 | {xtype, opts} = Keyword.pop(opts, :xtype, "quantitative") 41 | {ytype, opts} = Keyword.pop(opts, :ytype, "quantitative") 42 | default = [] 43 | opts = Keyword.merge(default, opts) 44 | 45 | {:ok, csv} = DF.to_csv(df) 46 | 47 | mark 48 | |> Mark.new(true) 49 | |> Chart.new( 50 | Encoding.new(%{ 51 | x: %{field: %{repeat: "column"}, type: xtype}, 52 | y: %{field: %{repeat: "row"}, type: ytype, axis: %{minExtend: 30}}, 53 | color: color 54 | }) 55 | ) 56 | |> Chart.repeat(%{row: rows, column: columns}, opts) 57 | |> Deneb.to_json(csv) 58 | end 59 | 60 | def plot_repeat(df, mark, x, ys, opts) when is_binary(x) and is_list(ys) do 61 | {color, opts} = get_color(df, opts) 62 | {columns, opts} = Keyword.pop(opts, :columns, 2) 63 | 64 | {ytype, opts} = Keyword.pop(opts, :ytype, "quantitative") 65 | 66 | default = [] 67 | opts = Keyword.merge(default, opts) 68 | 69 | {:ok, csv} = DF.to_csv(df) 70 | 71 | mark 72 | |> Mark.new(true) 73 | |> Chart.new( 74 | Encoding.new(%{ 75 | x: %{field: x, type: DF.dtype(df, x, :vega)}, 76 | y: %{field: %{repeat: "repeat"}, type: ytype}, 77 | color: color 78 | }) 79 | ) 80 | |> Chart.repeat(ys, opts) 81 | |> Deneb.to_json(csv) 82 | |> Map.put("columns", columns) 83 | end 84 | 85 | def plot_repeat(df, mark, xs, y, opts) when is_list(xs) and is_binary(y) do 86 | {color, opts} = get_color(df, opts) 87 | {columns, opts} = Keyword.pop(opts, :columns, 2) 88 | {xtype, opts} = Keyword.pop(opts, :xtype, "quantitative") 89 | 90 | default = [] 91 | opts = Keyword.merge(default, opts) 92 | 93 | {:ok, csv} = DF.to_csv(df) 94 | 95 | mark 96 | |> Mark.new(true) 97 | |> Chart.new( 98 | Encoding.new(%{ 99 | x: %{field: %{repeat: "repeat"}, type: xtype}, 100 | y: %{field: y, type: DF.dtype(df, y, :vega)}, 101 | color: color 102 | }) 103 | ) 104 | |> Chart.repeat(xs, opts) 105 | |> Deneb.to_json(csv) 106 | |> Map.put("columns", columns) 107 | end 108 | 109 | defp get_color(df, opts) do 110 | {color_field, opts} = Keyword.pop(opts, :color) 111 | 112 | case color_field do 113 | nil -> {nil, opts} 114 | v -> {%{field: v, type: DF.dtype(df, v, :vega)}, opts} 115 | end 116 | end 117 | end 118 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule ExPolars.MixProject do 2 | use Mix.Project 3 | 4 | @version "0.3.6-dev" 5 | def project do 6 | [ 7 | app: :ex_polars, 8 | compilers: [:rustler] ++ Mix.compilers(), 9 | rustler_crates: [ 10 | expolars: [ 11 | path: "native/expolars", 12 | mode: rustc_mode(Mix.env()) 13 | ] 14 | ], 15 | version: @version, 16 | elixir: "~> 1.11", 17 | start_permanent: Mix.env() == :prod, 18 | deps: deps(), 19 | 20 | # Docs 21 | name: "ExPolars", 22 | docs: [ 23 | extras: ["README.md"] 24 | ], 25 | source_url: "https://github.com/tyrchen/ex_polars", 26 | homepage_url: "https://github.com/tyrchen/ex_polars", 27 | description: """ 28 | Elixir support for [polars](https://github.com/ritchie46/polars), a DataFrame library written in rust. 29 | """, 30 | package: package() 31 | ] 32 | end 33 | 34 | # Run "mix help compile.app" to learn about applications. 35 | def application do 36 | [ 37 | extra_applications: [:logger] 38 | ] 39 | end 40 | 41 | defp rustc_mode(:prod), do: :release 42 | defp rustc_mode(_), do: :debug 43 | 44 | # Run "mix help deps" to learn about dependencies. 45 | defp deps do 46 | [ 47 | {:rustler, "~> 0.22.0-rc.0"}, 48 | {:jason, "~> 1.2"}, 49 | {:deneb, "~> 0.2"}, 50 | # {:deneb, path: "../deneb"}, 51 | 52 | # dev/test deps 53 | {:ex_doc, "~> 0.23", only: :dev, runtime: false}, 54 | {:credo, "~> 1.5", only: [:dev]} 55 | ] 56 | end 57 | 58 | defp package do 59 | [ 60 | files: ["lib", "priv/*.json", "priv/datasets", "native", "mix.exs", "README*", "LICENSE*"], 61 | licenses: ["MIT"], 62 | maintainers: ["tyr.chen@gmail.com"], 63 | links: %{ 64 | "GitHub" => "https://github.com/tyrchen/ex_polars", 65 | "Docs" => "https://hexdocs.pm/ex_polars" 66 | } 67 | ] 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{ 2 | "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, 3 | "credo": {:hex, :credo, "1.5.4", "9914180105b438e378e94a844ec3a5088ae5875626fc945b7c1462b41afc3198", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cf51af45eadc0a3f39ba13b56fdac415c91b34f7b7533a13dc13550277141bc4"}, 4 | "deneb": {:hex, :deneb, "0.2.2", "d4d7d5da4f61b27f3d753fa65b927fe56b188477a1c7ef9b659540ab2d82c944", [:mix], [{:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:typed_struct, "~> 0.2", [hex: :typed_struct, repo: "hexpm", optional: false]}], "hexpm", "9d29de7354dd9a9cfc93da22eef74102597ec98d4848550a7421bee026939c45"}, 5 | "earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"}, 6 | "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, 7 | "ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"}, 8 | "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, 9 | "jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"}, 10 | "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, 11 | "makeup_elixir": {:hex, :makeup_elixir, "0.15.0", "98312c9f0d3730fde4049985a1105da5155bfe5c11e47bdc7406d88e01e4219b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "75ffa34ab1056b7e24844c90bfc62aaf6f3a37a15faa76b07bc5eba27e4a8b4a"}, 12 | "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, 13 | "rustler": {:hex, :rustler, "0.22.0-rc.0", "d8a3d72862874d6c5a5c6421617911e8a2822a310b6e6d3ceb16803c2651350f", [:mix], [{:toml, "~> 0.5.2", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "0548ae8fd203bbd3c5ba689e60d827a1991e12cde599fb4c03d4cf56b00a3352"}, 14 | "toml": {:hex, :toml, "0.5.2", "e471388a8726d1ce51a6b32f864b8228a1eb8edc907a0edf2bb50eab9321b526", [:mix], [], "hexpm", "f1e3dabef71fb510d015fad18c0e05e7c57281001141504c6b69d94e99750a07"}, 15 | "typed_struct": {:hex, :typed_struct, "0.2.1", "e1993414c371f09ff25231393b6430bd89d780e2a499ae3b2d2b00852f593d97", [:mix], [], "hexpm", "8f5218c35ec38262f627b2c522542f1eae41f625f92649c0af701a6fab2e11b3"}, 16 | } 17 | -------------------------------------------------------------------------------- /native/expolars/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.x86_64-apple-darwin] 2 | rustflags = [ 3 | "-C", "link-arg=-undefined", 4 | "-C", "link-arg=dynamic_lookup", 5 | ] 6 | -------------------------------------------------------------------------------- /native/expolars/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "expolars" 3 | version = "0.1.0" 4 | authors = [] 5 | edition = "2018" 6 | 7 | [lib] 8 | name = "expolars" 9 | path = "src/lib.rs" 10 | crate-type = ["cdylib"] 11 | 12 | [dependencies] 13 | rustler = "0.22.0-rc.0" 14 | polars = {git = "https://github.com/ritchie46/polars", features = ["parquet", "json", "simd", "lazy", "strings", "temporal", "random", "object", "ipc"]} 15 | 16 | anyhow = "1.0" 17 | ndarray = "0.14" 18 | parquet = "2" 19 | serde_json = "1.0" 20 | thiserror = "1" 21 | arrow = "2" 22 | -------------------------------------------------------------------------------- /native/expolars/README.md: -------------------------------------------------------------------------------- 1 | # NIF for Elixir.ExPolars 2 | 3 | ## To build the NIF module: 4 | 5 | - Make sure your projects `mix.exs` has the `:rustler` compiler listed in the `project` function: `compilers: [:rustler] ++ Mix.compilers()` If there already is a `:compilers` list, you should append `:rustler` to it. 6 | - Add your crate to the `rustler_crates` attribute in the `project function. [See here](https://hexdocs.pm/rustler/basics.html#crate-configuration). 7 | - Your NIF will now build along with your project. 8 | 9 | ## To load the NIF: 10 | 11 | ```elixir 12 | defmodule ExPolars do 13 | use Rustler, otp_app: :ex_polars, crate: "expolars" 14 | 15 | # When your NIF is loaded, it will override this function. 16 | def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded) 17 | end 18 | ``` 19 | 20 | ## Examples 21 | 22 | [This](https://github.com/hansihe/NifIo) is a complete example of a NIF written in Rust. 23 | -------------------------------------------------------------------------------- /native/expolars/crimea.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "date": "1854-04-01", "wounds": 0, "other": 110, "disease": 110 }, 3 | { "date": "1854-05-01", "wounds": 0, "other": 95, "disease": 105 }, 4 | { "date": "1854-06-01", "wounds": 0, "other": 40, "disease": 95 }, 5 | { "date": "1854-07-01", "wounds": 0, "other": 140, "disease": 520 }, 6 | { "date": "1854-08-01", "wounds": 20, "other": 150, "disease": 800 }, 7 | { "date": "1854-09-01", "wounds": 220, "other": 230, "disease": 740 }, 8 | { "date": "1854-10-01", "wounds": 305, "other": 310, "disease": 600 }, 9 | { "date": "1854-11-01", "wounds": 480, "other": 290, "disease": 820 }, 10 | { "date": "1854-12-01", "wounds": 295, "other": 310, "disease": 1100 }, 11 | { "date": "1855-01-01", "wounds": 230, "other": 460, "disease": 1440 }, 12 | { "date": "1855-02-01", "wounds": 180, "other": 520, "disease": 1270 }, 13 | { "date": "1855-03-01", "wounds": 155, "other": 350, "disease": 935 }, 14 | { "date": "1855-04-01", "wounds": 195, "other": 195, "disease": 560 }, 15 | { "date": "1855-05-01", "wounds": 180, "other": 155, "disease": 550 }, 16 | { "date": "1855-06-01", "wounds": 330, "other": 130, "disease": 650 }, 17 | { "date": "1855-07-01", "wounds": 260, "other": 130, "disease": 430 }, 18 | { "date": "1855-08-01", "wounds": 290, "other": 110, "disease": 490 }, 19 | { "date": "1855-09-01", "wounds": 355, "other": 100, "disease": 290 }, 20 | { "date": "1855-10-01", "wounds": 135, "other": 95, "disease": 245 }, 21 | { "date": "1855-11-01", "wounds": 100, "other": 140, "disease": 325 }, 22 | { "date": "1855-12-01", "wounds": 40, "other": 120, "disease": 215 }, 23 | { "date": "1856-01-01", "wounds": 0, "other": 160, "disease": 160 }, 24 | { "date": "1856-02-01", "wounds": 0, "other": 100, "disease": 100 }, 25 | { "date": "1856-03-01", "wounds": 0, "other": 125, "disease": 90 } 26 | ] 27 | -------------------------------------------------------------------------------- /native/expolars/src/dataframe.rs: -------------------------------------------------------------------------------- 1 | // This file is modified based on: https://github.com/ritchie46/polars/blob/master/py-polars/src/dataframe.rs 2 | 3 | use polars::prelude::*; 4 | 5 | use polars::frame::ser::csv::CsvEncoding; 6 | use std::fs::File; 7 | use std::io::Cursor; 8 | use std::result::Result; 9 | 10 | use crate::series::{to_ex_series_collection, to_series_collection}; 11 | 12 | use crate::{DataType, ExDataFrame, ExPolarsError, ExSeries}; 13 | 14 | use crate::{df_read, df_read_read, df_write, df_write_read}; 15 | 16 | #[rustler::nif] 17 | pub fn df_read_csv( 18 | filename: &str, 19 | infer_schema_length: usize, 20 | batch_size: usize, 21 | has_header: bool, 22 | ignore_errors: bool, 23 | stop_after_n_rows: Option, 24 | skip_rows: usize, 25 | projection: Option>, 26 | sep: &str, 27 | do_rechunk: bool, 28 | column_names: Option>, 29 | encoding: &str, 30 | ) -> Result { 31 | let encoding = match encoding { 32 | "utf8-lossy" => CsvEncoding::LossyUtf8, 33 | _ => CsvEncoding::Utf8, 34 | }; 35 | let df = CsvReader::from_path(filename)? 36 | .infer_schema(Some(infer_schema_length)) 37 | .has_header(has_header) 38 | .with_stop_after_n_rows(stop_after_n_rows) 39 | .with_delimiter(sep.as_bytes()[0]) 40 | .with_skip_rows(skip_rows) 41 | .with_ignore_parser_errors(ignore_errors) 42 | .with_projection(projection) 43 | .with_rechunk(do_rechunk) 44 | .with_batch_size(batch_size) 45 | .with_encoding(encoding) 46 | .with_columns(column_names) 47 | .finish()?; 48 | Ok(ExDataFrame::new(df)) 49 | } 50 | 51 | #[rustler::nif] 52 | pub fn df_read_parquet(filename: &str) -> Result { 53 | let f = File::open(filename)?; 54 | let df = ParquetReader::new(f).finish()?; 55 | Ok(ExDataFrame::new(df)) 56 | } 57 | 58 | #[rustler::nif] 59 | pub fn df_read_json( 60 | filename: &str, 61 | line_delimited_json: bool, 62 | ) -> Result { 63 | let infer_size = 3; 64 | let batch_size = 100; 65 | let f = File::open(filename)?; 66 | let df = if line_delimited_json { 67 | JsonReader::new(f) 68 | .infer_schema(Some(infer_size)) 69 | .with_batch_size(batch_size) 70 | .finish()? 71 | } else { 72 | let v: serde_json::Value = serde_json::from_reader(f)?; 73 | let items: Vec = v 74 | .as_array() 75 | .unwrap() 76 | .iter() 77 | .map(|item| serde_json::to_string(&item).unwrap()) 78 | .collect(); 79 | 80 | JsonReader::new(Cursor::new(items.join("\n"))) 81 | .infer_schema(Some(infer_size)) 82 | .with_batch_size(batch_size) 83 | .finish()? 84 | }; 85 | 86 | Ok(ExDataFrame::new(df)) 87 | } 88 | 89 | #[rustler::nif] 90 | pub fn df_to_csv( 91 | data: ExDataFrame, 92 | batch_size: usize, 93 | has_headers: bool, 94 | delimiter: u8, 95 | ) -> Result { 96 | df_write!(data, df, { 97 | let mut buf: Vec = Vec::with_capacity(81920); 98 | CsvWriter::new(&mut buf) 99 | .has_headers(has_headers) 100 | .with_delimiter(delimiter) 101 | .with_batch_size(batch_size) 102 | .finish(&mut *df)?; 103 | 104 | let s = String::from_utf8(buf)?; 105 | Ok(s) 106 | }) 107 | } 108 | 109 | #[rustler::nif] 110 | pub fn df_to_csv_file( 111 | data: ExDataFrame, 112 | filename: &str, 113 | batch_size: usize, 114 | has_headers: bool, 115 | delimiter: u8, 116 | ) -> Result<(), ExPolarsError> { 117 | df_write!(data, df, { 118 | let mut f = File::create(filename)?; 119 | CsvWriter::new(&mut f) 120 | .has_headers(has_headers) 121 | .with_delimiter(delimiter) 122 | .with_batch_size(batch_size) 123 | .finish(&mut *df)?; 124 | Ok(()) 125 | }) 126 | } 127 | 128 | #[rustler::nif] 129 | /// Format `DataFrame` as String 130 | pub fn df_as_str(data: ExDataFrame) -> Result { 131 | df_read!(data, df, { Ok(format!("{:?}", &*df)) }) 132 | } 133 | 134 | #[rustler::nif] 135 | pub fn df_add(data: ExDataFrame, s: ExSeries) -> Result { 136 | df_read!(data, df, { 137 | let new_df = (&*df + &s.inner.0)?; 138 | Ok(ExDataFrame::new(new_df)) 139 | }) 140 | } 141 | 142 | #[rustler::nif] 143 | pub fn df_sub(data: ExDataFrame, s: ExSeries) -> Result { 144 | df_read!(data, df, { 145 | let new_df = (&*df - &s.inner.0)?; 146 | Ok(ExDataFrame::new(new_df)) 147 | }) 148 | } 149 | 150 | #[rustler::nif] 151 | pub fn df_div(data: ExDataFrame, s: ExSeries) -> Result { 152 | df_read!(data, df, { 153 | let new_df = (&*df / &s.inner.0)?; 154 | Ok(ExDataFrame::new(new_df)) 155 | }) 156 | } 157 | 158 | #[rustler::nif] 159 | pub fn df_mul(data: ExDataFrame, s: ExSeries) -> Result { 160 | df_read!(data, df, { 161 | let new_df = (&*df * &s.inner.0)?; 162 | Ok(ExDataFrame::new(new_df)) 163 | }) 164 | } 165 | 166 | #[rustler::nif] 167 | pub fn df_rem(data: ExDataFrame, s: ExSeries) -> Result { 168 | df_read!(data, df, { 169 | let new_df = (&*df % &s.inner.0)?; 170 | Ok(ExDataFrame::new(new_df)) 171 | }) 172 | } 173 | 174 | #[rustler::nif] 175 | pub fn df_sample_n( 176 | data: ExDataFrame, 177 | n: usize, 178 | with_replacement: bool, 179 | ) -> Result { 180 | df_read!(data, df, { 181 | let new_df = df.sample_n(n, with_replacement)?; 182 | Ok(ExDataFrame::new(new_df)) 183 | }) 184 | } 185 | 186 | #[rustler::nif] 187 | pub fn df_sample_frac( 188 | data: ExDataFrame, 189 | frac: f64, 190 | with_replacement: bool, 191 | ) -> Result { 192 | df_read!(data, df, { 193 | let new_df = df.sample_frac(frac, with_replacement)?; 194 | Ok(ExDataFrame::new(new_df)) 195 | }) 196 | } 197 | 198 | #[rustler::nif] 199 | pub fn df_rechunk(data: ExDataFrame) -> Result<(), ExPolarsError> { 200 | df_write!(data, df, { 201 | (&mut *df).agg_chunks(); 202 | Ok(()) 203 | }) 204 | } 205 | 206 | #[rustler::nif] 207 | pub fn df_fill_none(data: ExDataFrame, strategy: &str) -> Result { 208 | let strat = match strategy { 209 | "backward" => FillNoneStrategy::Backward, 210 | "forward" => FillNoneStrategy::Forward, 211 | "min" => FillNoneStrategy::Min, 212 | "max" => FillNoneStrategy::Max, 213 | "mean" => FillNoneStrategy::Mean, 214 | s => return Err(ExPolarsError::Other(format!("Strategy {} not supported", s)).into()), 215 | }; 216 | df_read!(data, df, { 217 | let new_df = df.fill_none(strat)?; 218 | Ok(ExDataFrame::new(new_df)) 219 | }) 220 | } 221 | 222 | #[rustler::nif] 223 | pub fn df_join( 224 | data: ExDataFrame, 225 | other: ExDataFrame, 226 | left_on: Vec<&str>, 227 | right_on: Vec<&str>, 228 | how: &str, 229 | ) -> Result { 230 | let how = match how { 231 | "left" => JoinType::Left, 232 | "inner" => JoinType::Inner, 233 | "outer" => JoinType::Outer, 234 | _ => return Err(ExPolarsError::Other(format!("Join method {} not supported", how)).into()), 235 | }; 236 | 237 | df_read_read!(data, other, df, df1, { 238 | let new_df = df.join(&*df1, left_on, right_on, how)?; 239 | Ok(ExDataFrame::new(new_df)) 240 | }) 241 | } 242 | 243 | #[rustler::nif] 244 | pub fn df_get_columns(data: ExDataFrame) -> Result, ExPolarsError> { 245 | df_read!(data, df, { 246 | Ok(to_ex_series_collection(df.get_columns().clone())) 247 | }) 248 | } 249 | 250 | /// Get column names 251 | #[rustler::nif] 252 | pub fn df_columns(data: ExDataFrame) -> Result, ExPolarsError> { 253 | df_read!(data, df, { 254 | let cols = df.get_column_names(); 255 | Ok(cols.into_iter().map(|s| s.to_owned()).collect()) 256 | }) 257 | } 258 | 259 | /// set column names 260 | #[rustler::nif] 261 | pub fn df_set_column_names(data: ExDataFrame, names: Vec<&str>) -> Result<(), ExPolarsError> { 262 | df_write!(data, df, { 263 | (&mut *df).set_column_names(&names)?; 264 | Ok(()) 265 | }) 266 | } 267 | 268 | /// Get datatypes 269 | #[rustler::nif] 270 | pub fn df_dtypes(data: ExDataFrame) -> Result, ExPolarsError> { 271 | df_read!(data, df, { 272 | let result = df 273 | .dtypes() 274 | .iter() 275 | .map(|arrow_dtype| { 276 | let dt: DataType = arrow_dtype.into(); 277 | dt as u8 278 | }) 279 | .collect(); 280 | Ok(result) 281 | }) 282 | } 283 | 284 | #[rustler::nif] 285 | pub fn df_n_chunks(data: ExDataFrame) -> Result { 286 | df_read!(data, df, { Ok(df.n_chunks()?) }) 287 | } 288 | 289 | #[rustler::nif] 290 | pub fn df_shape(data: ExDataFrame) -> Result<(usize, usize), ExPolarsError> { 291 | df_read!(data, df, { Ok(df.shape()) }) 292 | } 293 | 294 | #[rustler::nif] 295 | pub fn df_height(data: ExDataFrame) -> Result { 296 | df_read!(data, df, { Ok(df.height()) }) 297 | } 298 | 299 | #[rustler::nif] 300 | pub fn df_width(data: ExDataFrame) -> Result { 301 | df_read!(data, df, { Ok(df.width()) }) 302 | } 303 | 304 | #[rustler::nif] 305 | pub fn df_hstack_mut(data: ExDataFrame, cols: Vec) -> Result<(), ExPolarsError> { 306 | let cols = to_series_collection(cols); 307 | df_write!(data, df, { 308 | (&mut *df).hstack_mut(&cols)?; 309 | Ok(()) 310 | }) 311 | } 312 | 313 | #[rustler::nif] 314 | pub fn df_hstack(data: ExDataFrame, cols: Vec) -> Result { 315 | let cols = to_series_collection(cols); 316 | df_read!(data, df, { 317 | let new_df = df.hstack(&cols)?; 318 | Ok(ExDataFrame::new(new_df)) 319 | }) 320 | } 321 | 322 | #[rustler::nif] 323 | pub fn df_vstack(data: ExDataFrame, other: ExDataFrame) -> Result<(), ExPolarsError> { 324 | df_write_read!(data, other, df, df1, { 325 | (&mut *df).vstack_mut(&df1)?; 326 | Ok(()) 327 | }) 328 | } 329 | 330 | #[rustler::nif] 331 | pub fn df_drop_in_place(data: ExDataFrame, name: &str) -> Result { 332 | df_write!(data, df, { 333 | let s = (&mut *df).drop_in_place(name)?; 334 | Ok(ExSeries::new(s)) 335 | }) 336 | } 337 | 338 | #[rustler::nif] 339 | pub fn df_drop_nulls( 340 | data: ExDataFrame, 341 | subset: Option>, 342 | ) -> Result { 343 | df_read!(data, df, { 344 | let new_df = df.drop_nulls(subset.as_ref().map(|s| s.as_ref()))?; 345 | Ok(ExDataFrame::new(new_df)) 346 | }) 347 | } 348 | 349 | #[rustler::nif] 350 | pub fn df_drop(data: ExDataFrame, name: &str) -> Result { 351 | df_read!(data, df, { 352 | let new_df = (&*df).drop(name)?; 353 | Ok(ExDataFrame::new(new_df)) 354 | }) 355 | } 356 | 357 | #[rustler::nif] 358 | pub fn df_select_at_idx(data: ExDataFrame, idx: usize) -> Result, ExPolarsError> { 359 | df_read!(data, df, { 360 | let result = df.select_at_idx(idx).map(|s| ExSeries::new(s.clone())); 361 | Ok(result) 362 | }) 363 | } 364 | 365 | #[rustler::nif] 366 | pub fn df_find_idx_by_name(data: ExDataFrame, name: &str) -> Result, ExPolarsError> { 367 | df_read!(data, df, { Ok(df.find_idx_by_name(name)) }) 368 | } 369 | 370 | #[rustler::nif] 371 | pub fn df_column(data: ExDataFrame, name: &str) -> Result { 372 | df_read!(data, df, { 373 | let series = df.column(name).map(|s| ExSeries::new(s.clone()))?; 374 | Ok(series) 375 | }) 376 | } 377 | 378 | #[rustler::nif] 379 | pub fn df_select(data: ExDataFrame, selection: Vec<&str>) -> Result { 380 | df_read!(data, df, { 381 | let new_df = df.select(&selection)?; 382 | Ok(ExDataFrame::new(new_df)) 383 | }) 384 | } 385 | 386 | #[rustler::nif] 387 | pub fn df_filter(data: ExDataFrame, mask: ExSeries) -> Result { 388 | df_read!(data, df, { 389 | let filter_series = &mask.inner.0; 390 | if let Ok(ca) = filter_series.bool() { 391 | let new_df = df.filter(ca)?; 392 | Ok(ExDataFrame::new(new_df)) 393 | } else { 394 | Err(ExPolarsError::Other("Expected a boolean mask".into())) 395 | } 396 | }) 397 | } 398 | 399 | #[rustler::nif] 400 | pub fn df_take(data: ExDataFrame, indices: Vec) -> Result { 401 | df_read!(data, df, { 402 | let new_df = df.take(&indices); 403 | Ok(ExDataFrame::new(new_df)) 404 | }) 405 | } 406 | 407 | #[rustler::nif] 408 | pub fn df_take_with_series( 409 | data: ExDataFrame, 410 | indices: ExSeries, 411 | ) -> Result { 412 | let idx = indices.inner.0.u32()?; 413 | df_read!(data, df, { 414 | let new_df = df.take(&idx); 415 | Ok(ExDataFrame::new(new_df)) 416 | }) 417 | } 418 | 419 | #[rustler::nif] 420 | pub fn df_sort_new( 421 | data: ExDataFrame, 422 | by_column: &str, 423 | reverse: bool, 424 | ) -> Result { 425 | df_read!(data, df, { 426 | let new_df = df.sort(by_column, reverse)?; 427 | Ok(ExDataFrame::new(new_df)) 428 | }) 429 | } 430 | 431 | #[rustler::nif] 432 | pub fn df_sort_in_place( 433 | data: ExDataFrame, 434 | by_column: &str, 435 | reverse: bool, 436 | ) -> Result<(), ExPolarsError> { 437 | df_write!(data, df, { 438 | (&mut *df).sort_in_place(by_column, reverse)?; 439 | Ok(()) 440 | }) 441 | } 442 | 443 | #[rustler::nif] 444 | pub fn df_replace(data: ExDataFrame, col: &str, new_col: ExSeries) -> Result<(), ExPolarsError> { 445 | df_write!(data, df, { 446 | (&mut *df).replace(col, new_col.inner.0.clone())?; 447 | Ok(()) 448 | }) 449 | } 450 | 451 | #[rustler::nif] 452 | pub fn df_replace_at_idx( 453 | data: ExDataFrame, 454 | index: usize, 455 | new_col: ExSeries, 456 | ) -> Result<(), ExPolarsError> { 457 | df_write!(data, df, { 458 | (&mut *df).replace_at_idx(index, new_col.inner.0.clone())?; 459 | Ok(()) 460 | }) 461 | } 462 | 463 | #[rustler::nif] 464 | pub fn df_insert_at_idx( 465 | data: ExDataFrame, 466 | index: usize, 467 | new_col: ExSeries, 468 | ) -> Result<(), ExPolarsError> { 469 | df_write!(data, df, { 470 | (&mut *df).insert_at_idx(index, new_col.inner.0.clone())?; 471 | Ok(()) 472 | }) 473 | } 474 | 475 | #[rustler::nif] 476 | pub fn df_slice( 477 | data: ExDataFrame, 478 | offset: usize, 479 | length: usize, 480 | ) -> Result { 481 | df_read!(data, df, { 482 | let new_df = df.slice(offset, length)?; 483 | Ok(ExDataFrame::new(new_df)) 484 | }) 485 | } 486 | 487 | #[rustler::nif] 488 | pub fn df_head(data: ExDataFrame, length: Option) -> Result { 489 | df_read!(data, df, { 490 | let new_df = df.head(length); 491 | Ok(ExDataFrame::new(new_df)) 492 | }) 493 | } 494 | 495 | #[rustler::nif] 496 | pub fn df_tail(data: ExDataFrame, length: Option) -> Result { 497 | df_read!(data, df, { 498 | let new_df = df.tail(length); 499 | Ok(ExDataFrame::new(new_df)) 500 | }) 501 | } 502 | 503 | #[rustler::nif] 504 | pub fn df_is_unique(data: ExDataFrame) -> Result { 505 | df_read!(data, df, { 506 | let mask = df.is_unique()?; 507 | Ok(ExSeries::new(mask.into_series())) 508 | }) 509 | } 510 | 511 | #[rustler::nif] 512 | pub fn df_is_duplicated(data: ExDataFrame) -> Result { 513 | df_read!(data, df, { 514 | let mask = df.is_unique()?; 515 | Ok(ExSeries::new(mask.into_series())) 516 | }) 517 | } 518 | 519 | #[rustler::nif] 520 | pub fn df_frame_equal( 521 | data: ExDataFrame, 522 | other: ExDataFrame, 523 | null_equal: bool, 524 | ) -> Result { 525 | df_read_read!(data, other, df, df1, { 526 | let result = if null_equal { 527 | df.frame_equal_missing(&*df1) 528 | } else { 529 | df.frame_equal(&*df1) 530 | }; 531 | Ok(result) 532 | }) 533 | } 534 | 535 | #[rustler::nif] 536 | pub fn df_groupby( 537 | data: ExDataFrame, 538 | by: Vec<&str>, 539 | sel: Option>, 540 | agg: &str, 541 | ) -> Result { 542 | df_read!(data, df, { 543 | let gb = df.groupby(&by)?; 544 | let selection = match sel.as_ref() { 545 | Some(s) => gb.select(s), 546 | None => gb, 547 | }; 548 | let result = match agg { 549 | "min" => selection.min(), 550 | "max" => selection.max(), 551 | "mean" => selection.mean(), 552 | "first" => selection.first(), 553 | "last" => selection.last(), 554 | "sum" => selection.sum(), 555 | "count" => selection.count(), 556 | "n_unique" => selection.n_unique(), 557 | "median" => selection.median(), 558 | "agg_list" => selection.agg_list(), 559 | "groups" => selection.groups(), 560 | "std" => selection.std(), 561 | "var" => selection.var(), 562 | a => Err(PolarsError::Other( 563 | format!("agg fn {} does not exists", a).into(), 564 | )), 565 | }; 566 | Ok(ExDataFrame::new(result?)) 567 | }) 568 | } 569 | 570 | #[rustler::nif] 571 | pub fn df_groupby_agg( 572 | data: ExDataFrame, 573 | by: Vec<&str>, 574 | column_to_agg: Vec<(&str, Vec<&str>)>, 575 | ) -> Result { 576 | df_read!(data, df, { 577 | let gb = df.groupby(&by)?; 578 | let new_df = gb.agg(&column_to_agg)?; 579 | Ok(ExDataFrame::new(new_df)) 580 | }) 581 | } 582 | 583 | // TODO(tchen): groupby_apply(data: ExDataFrame, by: Vec<&str>, lambda: Fun) -> Result not implemented 584 | // I don't know how to pass an elixir function to rust for execution 585 | 586 | #[rustler::nif] 587 | pub fn df_groupby_quantile( 588 | data: ExDataFrame, 589 | by: Vec<&str>, 590 | sel: Vec, 591 | quant: f64, 592 | ) -> Result { 593 | df_read!(data, df, { 594 | let gb = df.groupby(&by)?; 595 | let selection = gb.select(&sel); 596 | let new_df = selection.quantile(quant)?; 597 | Ok(ExDataFrame::new(new_df)) 598 | }) 599 | } 600 | 601 | #[rustler::nif] 602 | pub fn df_pivot( 603 | data: ExDataFrame, 604 | by: Vec, 605 | pivot_column: &str, 606 | values_column: &str, 607 | agg: &str, 608 | ) -> Result { 609 | df_read!(data, df, { 610 | let mut gb = df.groupby(&by)?; 611 | let pivot = gb.pivot(pivot_column, values_column); 612 | let result = match agg { 613 | "first" => pivot.first(), 614 | "min" => pivot.min(), 615 | "max" => pivot.max(), 616 | "mean" => pivot.mean(), 617 | "median" => pivot.median(), 618 | "sum" => pivot.sum(), 619 | "count" => pivot.count(), 620 | a => Err(PolarsError::Other( 621 | format!("agg fn {} does not exists", a).into(), 622 | )), 623 | }; 624 | Ok(ExDataFrame::new(result?)) 625 | }) 626 | } 627 | 628 | #[rustler::nif] 629 | pub fn df_clone(data: ExDataFrame) -> Result { 630 | df_read!(data, df, { Ok(ExDataFrame::new(df.clone())) }) 631 | } 632 | 633 | #[rustler::nif] 634 | pub fn df_explode(data: ExDataFrame, cols: Vec) -> Result { 635 | df_read!(data, df, { 636 | let new_df = df.explode(&cols)?; 637 | Ok(ExDataFrame::new(new_df)) 638 | }) 639 | } 640 | 641 | #[rustler::nif] 642 | pub fn df_melt( 643 | data: ExDataFrame, 644 | id_vars: Vec<&str>, 645 | value_vars: Vec<&str>, 646 | ) -> Result { 647 | df_read!(data, df, { 648 | let new_df = df.melt(id_vars, value_vars)?; 649 | Ok(ExDataFrame::new(new_df)) 650 | }) 651 | } 652 | 653 | #[rustler::nif] 654 | pub fn df_shift(data: ExDataFrame, periods: i32) -> Result { 655 | df_read!(data, df, { 656 | let new_df = df.shift(periods)?; 657 | Ok(ExDataFrame::new(new_df)) 658 | }) 659 | } 660 | 661 | #[rustler::nif] 662 | pub fn df_drop_duplicates( 663 | data: ExDataFrame, 664 | maintain_order: bool, 665 | subset: Option>, 666 | ) -> Result { 667 | df_read!(data, df, { 668 | let new_df = df.drop_duplicates(maintain_order, subset.as_ref().map(|v| v.as_ref()))?; 669 | Ok(ExDataFrame::new(new_df)) 670 | }) 671 | } 672 | 673 | #[rustler::nif] 674 | pub fn df_max(data: ExDataFrame) -> Result { 675 | df_read!(data, df, { Ok(ExDataFrame::new(df.max())) }) 676 | } 677 | 678 | #[rustler::nif] 679 | pub fn df_min(data: ExDataFrame) -> Result { 680 | df_read!(data, df, { Ok(ExDataFrame::new(df.min())) }) 681 | } 682 | 683 | #[rustler::nif] 684 | pub fn df_sum(data: ExDataFrame) -> Result { 685 | df_read!(data, df, { Ok(ExDataFrame::new(df.sum())) }) 686 | } 687 | 688 | #[rustler::nif] 689 | pub fn df_mean(data: ExDataFrame) -> Result { 690 | df_read!(data, df, { Ok(ExDataFrame::new(df.mean())) }) 691 | } 692 | 693 | #[rustler::nif] 694 | pub fn df_stdev(data: ExDataFrame) -> Result { 695 | df_read!(data, df, { Ok(ExDataFrame::new(df.std())) }) 696 | } 697 | 698 | #[rustler::nif] 699 | pub fn df_var(data: ExDataFrame) -> Result { 700 | df_read!(data, df, { Ok(ExDataFrame::new(df.var())) }) 701 | } 702 | 703 | #[rustler::nif] 704 | pub fn df_median(data: ExDataFrame) -> Result { 705 | df_read!(data, df, { Ok(ExDataFrame::new(df.median())) }) 706 | } 707 | 708 | #[rustler::nif] 709 | pub fn df_quantile(data: ExDataFrame, quant: f64) -> Result { 710 | df_read!(data, df, { 711 | let new_df = df.quantile(quant)?; 712 | Ok(ExDataFrame::new(new_df)) 713 | }) 714 | } 715 | 716 | #[rustler::nif] 717 | pub fn df_to_dummies(data: ExDataFrame) -> Result { 718 | df_read!(data, df, { 719 | let new_df = df.to_dummies()?; 720 | Ok(ExDataFrame::new(new_df)) 721 | }) 722 | } 723 | -------------------------------------------------------------------------------- /native/expolars/src/datatypes.rs: -------------------------------------------------------------------------------- 1 | // This file is modified based on: https://github.com/ritchie46/polars/blob/master/py-polars/src/datatypes.rs 2 | 3 | use std::sync::RwLock; 4 | use polars::prelude::*; 5 | use rustler::NifStruct; 6 | use rustler::resource::ResourceArc; 7 | 8 | use std::result::Result; 9 | 10 | pub struct ExDataFrameRef(pub RwLock); 11 | pub struct ExSeriesRef(pub Series); 12 | 13 | #[derive(NifStruct)] 14 | #[module = "ExPolars.DataFrame"] 15 | pub struct ExDataFrame { 16 | pub inner: ResourceArc, 17 | } 18 | 19 | #[derive(NifStruct)] 20 | #[module = "ExPolars.Series"] 21 | pub struct ExSeries { 22 | pub inner: ResourceArc, 23 | } 24 | 25 | // Don't change the order of these! 26 | #[repr(u8)] 27 | pub enum DataType { 28 | Int8, 29 | Int16, 30 | Int32, 31 | Int64, 32 | UInt8, 33 | UInt16, 34 | UInt32, 35 | UInt64, 36 | Float32, 37 | Float64, 38 | Bool, 39 | Utf8, 40 | List, 41 | Date32, 42 | Date64, 43 | Time64Nanosecond, 44 | DurationNanosecond, 45 | DurationMillisecond, 46 | Object, 47 | } 48 | 49 | impl ExDataFrameRef { 50 | pub fn new(df: DataFrame) -> Self { 51 | Self(RwLock::new(df)) 52 | } 53 | } 54 | 55 | impl ExSeriesRef { 56 | pub fn new(s: Series) -> Self { 57 | Self(s) 58 | } 59 | } 60 | 61 | impl ExDataFrame { 62 | pub fn new(df: DataFrame) -> Self { 63 | Self { 64 | inner: ResourceArc::new(ExDataFrameRef::new(df)) 65 | } 66 | } 67 | } 68 | 69 | 70 | impl ExSeries { 71 | pub fn new(s: Series) -> Self { 72 | Self { 73 | inner: ResourceArc::new(ExSeriesRef::new(s)) 74 | } 75 | } 76 | } 77 | 78 | impl From<&ArrowDataType> for DataType { 79 | fn from(dt: &ArrowDataType) -> Self { 80 | use DataType::*; 81 | match dt { 82 | ArrowDataType::Int8 => Int8, 83 | ArrowDataType::Int16 => Int16, 84 | ArrowDataType::Int32 => Int32, 85 | ArrowDataType::Int64 => Int64, 86 | ArrowDataType::UInt8 => UInt8, 87 | ArrowDataType::UInt16 => UInt16, 88 | ArrowDataType::UInt32 => UInt32, 89 | ArrowDataType::UInt64 => UInt64, 90 | ArrowDataType::Float32 => Float32, 91 | ArrowDataType::Float64 => Float64, 92 | ArrowDataType::Boolean => Bool, 93 | ArrowDataType::Utf8 => Utf8, 94 | ArrowDataType::List(_) => List, 95 | ArrowDataType::Date32(_) => Date32, 96 | ArrowDataType::Date64(_) => Date64, 97 | ArrowDataType::Time64(TimeUnit::Nanosecond) => Time64Nanosecond, 98 | ArrowDataType::Duration(TimeUnit::Nanosecond) => DurationNanosecond, 99 | ArrowDataType::Duration(TimeUnit::Millisecond) => DurationMillisecond, 100 | ArrowDataType::Binary => Object, 101 | dt => panic!(format!("datatype: {:?} not supported", dt)), 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /native/expolars/src/error.rs: -------------------------------------------------------------------------------- 1 | use rustler::{Encoder, Env, Term}; 2 | use std::io; 3 | use thiserror::Error; 4 | 5 | rustler::atoms! { 6 | ok, 7 | error 8 | } 9 | 10 | #[derive(Error, Debug)] 11 | pub enum ExPolarsError { 12 | #[error("IO Error")] 13 | Io(#[from] io::Error), 14 | #[error("Json Serialize/Deserialize Error")] 15 | Json(#[from] serde_json::Error), 16 | #[error("Utf8 Conversion Error")] 17 | Utf8(#[from] std::string::FromUtf8Error), 18 | #[error("Polars Error")] 19 | Polars(#[from] polars::prelude::PolarsError), 20 | #[error("Internal Error: {0}")] 21 | Internal(String), 22 | #[error("Other error: {0}")] 23 | Other(String), 24 | #[error(transparent)] 25 | Unknown(#[from] anyhow::Error), 26 | } 27 | 28 | impl<'a> Encoder for ExPolarsError { 29 | fn encode<'b>(&self, env: Env<'b>) -> Term<'b> { 30 | format!("{:?}", self).encode(env) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /native/expolars/src/lib.rs: -------------------------------------------------------------------------------- 1 | use rustler::{Env, Term}; 2 | 3 | mod dataframe; 4 | mod datatypes; 5 | mod error; 6 | mod series; 7 | 8 | use dataframe::*; 9 | pub use datatypes::{DataType, ExDataFrame, ExDataFrameRef, ExSeries, ExSeriesRef}; 10 | pub use error::ExPolarsError; 11 | use series::*; 12 | 13 | #[macro_export] 14 | macro_rules! df_read { 15 | ($data: ident, $df: ident, $body: block) => { 16 | match $data.inner.0.read() { 17 | Ok($df) => $body, 18 | Err(_) => Err(ExPolarsError::Internal( 19 | "Failed to take read lock for df".into(), 20 | )), 21 | } 22 | }; 23 | } 24 | 25 | #[macro_export] 26 | macro_rules! df_read_read { 27 | ($data: ident, $other: ident, $df: ident, $df1: ident, $body: block) => { 28 | match ($data.inner.0.read(), $other.inner.0.read()) { 29 | (Ok($df), Ok($df1)) => $body, 30 | _ => Err(ExPolarsError::Internal( 31 | "Failed to take read locks for df and df1".into(), 32 | )), 33 | } 34 | }; 35 | } 36 | 37 | #[macro_export] 38 | macro_rules! df_write { 39 | ($data: ident, $df: ident, $body: block) => { 40 | match $data.inner.0.write() { 41 | Ok(mut $df) => $body, 42 | Err(_) => Err(ExPolarsError::Internal( 43 | "Failed to take write lock for df".into(), 44 | )), 45 | } 46 | }; 47 | } 48 | 49 | #[macro_export] 50 | macro_rules! df_write_read { 51 | ($data: ident, $other: ident, $df: ident, $df1: ident, $body: block) => { 52 | match ($data.inner.0.write(), $other.inner.0.read()) { 53 | (Ok(mut $df), Ok($df1)) => $body, 54 | _ => Err(ExPolarsError::Internal( 55 | "Failed to take write and read lock for df and df1".into(), 56 | )), 57 | } 58 | }; 59 | } 60 | 61 | // rustler initialization 62 | 63 | fn on_load(env: Env, _info: Term) -> bool { 64 | rustler::resource!(ExDataFrameRef, env); 65 | rustler::resource!(ExSeriesRef, env); 66 | true 67 | } 68 | 69 | rustler::init!( 70 | "Elixir.ExPolars.Native", 71 | [ 72 | df_read_csv, 73 | df_read_parquet, 74 | df_read_json, 75 | df_to_csv, 76 | df_to_csv_file, 77 | df_as_str, 78 | df_add, 79 | df_sub, 80 | df_mul, 81 | df_div, 82 | df_rem, 83 | df_sample_n, 84 | df_sample_frac, 85 | df_rechunk, 86 | df_fill_none, 87 | df_join, 88 | df_get_columns, 89 | df_columns, 90 | df_set_column_names, 91 | df_dtypes, 92 | df_n_chunks, 93 | df_shape, 94 | df_width, 95 | df_height, 96 | df_hstack_mut, 97 | df_hstack, 98 | df_vstack, 99 | df_drop_in_place, 100 | df_drop_nulls, 101 | df_drop, 102 | df_select_at_idx, 103 | df_find_idx_by_name, 104 | df_column, 105 | df_select, 106 | df_filter, 107 | df_take, 108 | df_take_with_series, 109 | df_sort_new, 110 | df_sort_in_place, 111 | df_replace, 112 | df_replace_at_idx, 113 | df_insert_at_idx, 114 | df_slice, 115 | df_head, 116 | df_tail, 117 | df_is_unique, 118 | df_is_duplicated, 119 | df_frame_equal, 120 | df_groupby, 121 | df_groupby_agg, 122 | df_groupby_quantile, 123 | df_pivot, 124 | df_clone, 125 | df_explode, 126 | df_melt, 127 | df_shift, 128 | df_drop_duplicates, 129 | df_max, 130 | df_min, 131 | df_sum, 132 | df_mean, 133 | df_stdev, 134 | df_var, 135 | df_median, 136 | df_quantile, 137 | df_to_dummies, 138 | // series 139 | s_as_str, 140 | s_new_i8, 141 | s_new_i16, 142 | s_new_i32, 143 | s_new_i64, 144 | s_new_bool, 145 | s_new_u8, 146 | s_new_u16, 147 | s_new_u32, 148 | s_new_u64, 149 | s_new_date32, 150 | s_new_date64, 151 | s_new_duration_ns, 152 | s_new_f32, 153 | s_new_f64, 154 | s_parse_date32_from_str_slice, 155 | s_new_str, 156 | s_rechunk, 157 | s_chunk_lengths, 158 | s_name, 159 | s_rename, 160 | s_dtype, 161 | s_n_chunks, 162 | s_limit, 163 | s_slice, 164 | s_append, 165 | s_filter, 166 | s_add, 167 | s_sub, 168 | s_mul, 169 | s_div, 170 | s_head, 171 | s_tail, 172 | s_sort, 173 | s_argsort, 174 | s_unique, 175 | s_value_counts, 176 | s_arg_unique, 177 | s_take, 178 | s_take_with_series, 179 | s_null_count, 180 | s_is_null, 181 | s_is_not_null, 182 | s_is_unique, 183 | s_arg_true, 184 | s_sample_n, 185 | s_sample_frac, 186 | s_is_duplicated, 187 | s_explode, 188 | s_take_every, 189 | s_series_equal, 190 | s_eq, 191 | s_neq, 192 | s_gt, 193 | s_gt_eq, 194 | s_lt, 195 | s_lt_eq, 196 | s_not, 197 | s_len, 198 | s_to_json, 199 | s_drop_nulls, 200 | s_fill_none, 201 | s_clone, 202 | s_shift, 203 | s_zip_with, 204 | s_str_lengths, 205 | s_str_contains, 206 | s_str_replace, 207 | s_str_replace_all, 208 | s_str_to_uppercase, 209 | s_str_to_lowercase, 210 | s_str_parse_date32, 211 | s_str_parse_date64, 212 | s_datetime_str_fmt, 213 | s_as_duration, 214 | s_to_dummies, 215 | s_get_list, 216 | s_rolling_sum, 217 | s_rolling_mean, 218 | s_rolling_max, 219 | s_rolling_min, 220 | s_year, 221 | s_month, 222 | s_day, 223 | s_ordinal_day, 224 | s_hour, 225 | s_minute, 226 | s_second, 227 | s_nanosecond, 228 | s_set_with_mask_str, 229 | s_set_with_mask_f64, 230 | s_set_with_mask_f32, 231 | s_set_with_mask_u8, 232 | s_set_with_mask_u16, 233 | s_set_with_mask_u32, 234 | s_set_with_mask_u64, 235 | s_set_with_mask_i8, 236 | s_set_with_mask_i16, 237 | s_set_with_mask_i32, 238 | s_set_with_mask_i64, 239 | s_get_f32, 240 | s_get_f64, 241 | s_get_u8, 242 | s_get_u16, 243 | s_get_u32, 244 | s_get_u64, 245 | s_get_i8, 246 | s_get_i16, 247 | s_get_i32, 248 | s_get_i64, 249 | s_get_date32, 250 | s_get_date64, 251 | s_cast_u8, 252 | s_cast_u16, 253 | s_cast_u32, 254 | s_cast_u64, 255 | s_cast_i8, 256 | s_cast_i16, 257 | s_cast_i32, 258 | s_cast_i64, 259 | s_cast_f32, 260 | s_cast_f64, 261 | s_cast_date32, 262 | s_cast_date64, 263 | s_cast_time64ns, 264 | s_cast_duration_ns, 265 | s_cast_str, 266 | s_add_i64, 267 | s_sub_i64, 268 | s_mul_i64, 269 | s_div_i64, 270 | s_add_f64, 271 | s_sub_f64, 272 | s_mul_f64, 273 | s_div_f64, 274 | s_add_i64_rhs, 275 | s_sub_i64_rhs, 276 | s_mul_i64_rhs, 277 | s_div_i64_rhs, 278 | s_add_f64_rhs, 279 | s_sub_f64_rhs, 280 | s_mul_f64_rhs, 281 | s_div_f64_rhs, 282 | s_sum_u8, 283 | s_sum_u16, 284 | s_sum_u32, 285 | s_sum_u64, 286 | s_sum_i8, 287 | s_sum_i16, 288 | s_sum_i32, 289 | s_sum_i64, 290 | s_sum_f32, 291 | s_sum_f64, 292 | s_min_u8, 293 | s_min_u16, 294 | s_min_u32, 295 | s_min_u64, 296 | s_min_i8, 297 | s_min_i16, 298 | s_min_i32, 299 | s_min_i64, 300 | s_min_f32, 301 | s_min_f64, 302 | s_max_u8, 303 | s_max_u16, 304 | s_max_u32, 305 | s_max_u64, 306 | s_max_i8, 307 | s_max_i16, 308 | s_max_i32, 309 | s_max_i64, 310 | s_max_f32, 311 | s_max_f64, 312 | s_mean_u8, 313 | s_mean_u16, 314 | s_mean_u32, 315 | s_mean_u64, 316 | s_mean_i8, 317 | s_mean_i16, 318 | s_mean_i32, 319 | s_mean_i64, 320 | s_mean_f32, 321 | s_mean_f64, 322 | s_eq_u8, 323 | s_neq_u8, 324 | s_gt_u8, 325 | s_lt_u8, 326 | s_gt_eq_u8, 327 | s_lt_eq_u8, 328 | s_eq_u16, 329 | s_neq_u16, 330 | s_gt_u16, 331 | s_lt_u16, 332 | s_gt_eq_u16, 333 | s_lt_eq_u16, 334 | s_eq_u32, 335 | s_neq_u32, 336 | s_gt_u32, 337 | s_lt_u32, 338 | s_gt_eq_u32, 339 | s_lt_eq_u32, 340 | s_eq_u64, 341 | s_neq_u64, 342 | s_gt_u64, 343 | s_lt_u64, 344 | s_gt_eq_u64, 345 | s_lt_eq_u64, 346 | s_eq_i8, 347 | s_neq_i8, 348 | s_gt_i8, 349 | s_lt_i8, 350 | s_gt_eq_i8, 351 | s_lt_eq_i8, 352 | s_eq_i16, 353 | s_neq_i16, 354 | s_gt_i16, 355 | s_lt_i16, 356 | s_gt_eq_i16, 357 | s_lt_eq_i16, 358 | s_eq_i32, 359 | s_neq_i32, 360 | s_gt_i32, 361 | s_lt_i32, 362 | s_gt_eq_i32, 363 | s_lt_eq_i32, 364 | s_eq_i64, 365 | s_neq_i64, 366 | s_gt_i64, 367 | s_lt_i64, 368 | s_gt_eq_i64, 369 | s_lt_eq_i64, 370 | s_eq_f32, 371 | s_neq_f32, 372 | s_gt_f32, 373 | s_lt_f32, 374 | s_gt_eq_f32, 375 | s_lt_eq_f32, 376 | s_eq_f64, 377 | s_neq_f64, 378 | s_gt_f64, 379 | s_lt_f64, 380 | s_gt_eq_f64, 381 | s_lt_eq_f64, 382 | s_eq_str, 383 | s_neq_str, 384 | s_gt_str, 385 | s_lt_str, 386 | s_gt_eq_str, 387 | s_lt_eq_str, 388 | ], 389 | load = on_load 390 | ); 391 | 392 | #[cfg(test)] 393 | mod test { 394 | use serde_json::Value; 395 | use std::fs::File; 396 | #[test] 397 | fn read_json() { 398 | let f = File::open("crimea.json").unwrap(); 399 | let v: Value = serde_json::from_reader(f).unwrap(); 400 | let items: Vec = v 401 | .as_array() 402 | .unwrap() 403 | .iter() 404 | .map(|item| serde_json::to_string(&item).unwrap()) 405 | .collect(); 406 | for line in items { 407 | println!("{}", line); 408 | } 409 | } 410 | } 411 | -------------------------------------------------------------------------------- /priv/dataset_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "airports" : { 3 | "description" : "This dataset lists US airports, including airport code, city, state, latitude, and longitude. This dataset is a subset of the data compiled and published at http://ourairports.com/data/, and is in the public domain." 4 | }, 5 | "anscombe" : { 6 | "description" : "Anscombe's Quartet is a famous dataset constructed by Francis Anscombe [1]_. Common summary statistics are identical for each subset of the data, despite the subsets having vastly different characteristics.", 7 | "references" : [ 8 | "Anscombe, F. J. (1973). 'Graphs in Statistical Analysis'. American Statistician. 27 (1): 17-21. JSTOR 2682899." 9 | ] 10 | }, 11 | "barley" : { 12 | "description" : "This dataset contains crop yields over different regions and different years in the 1930s. It was originally published by Immer in 1934 [1]_, and was popularized by Fisher (1947) [2]_ and Cleveland (1993) [3]_.", 13 | "references" : [ 14 | "Immer, F.R., Hayes, H.D. and LeRoy Powers (1934) Statistical determination of barley varietal adaptation. Journal of the American Society for Agronomy 26, 403-419.", 15 | "Fisher, R.A. (1947) The Design of Experiments. 4th edition. Edinburgh: Oliver and Boyd.", 16 | "Cleveland, WS (1993) Visualizing data. Hobart Press" 17 | ] 18 | }, 19 | "burtin" : { 20 | "description": "This is a famous dataset gathered by Will Burtin to explore the effectiveness of various antibiotics in treating a variety of bacterial infections. The data was first published in 1951; this dataset comes from https://github.com/mbostock/protovis, and is published there under a BSD license." 21 | }, 22 | "cars" : { 23 | "description": "Acceleration, horsepower, fuel efficiency, weight, and other characteristics of different makes and models of cars. This dataset was originally published by Donoho et al (1982) [1]_, and was made public at http://lib.stat.cmu.edu/datasets/", 24 | "references": [ 25 | "Donoho, David and Ramos, Ernesto (1982), ``PRIMDATA: Data Sets for Use With PRIM-H'' (DRAFT)." 26 | ] 27 | }, 28 | "crimea" : { 29 | "description": "This is a dataset containing monthly casualty counts from the Crimean war. It was originally published in 1858 by Florence Nightingale [1]_ in connection with her famous 'Coxcomb' charts.", 30 | "references": [ 31 | "Nightingale, F. (1858) 'Notes on Matters Affecting the Health, Efficiency and Hospital Administration of the British Army'. RCIN 1075240" 32 | ] 33 | }, 34 | "driving" : { 35 | "description": "This dataset tracks miles driven per capita along with gas prices annually from 1956 to 2010. It is based on the May 2, 2010 New York Times article 'Driving Shifts Into Reverse'. See http://mbostock.github.io/protovis/ex/driving.html.", 36 | "references": [ 37 | "Fairfield, Hannah. 'Driving Shifts Into Reverse.' New York Times, May 2, 2010" 38 | ] 39 | }, 40 | "iowa-electricity" : { 41 | "description": "The state of Iowa has dramatically increased its production of renewable wind power in recent years. This file contains the annual net generation of electricity in the state by source in thousand megawatthours. The dataset was published in the public domain by the U.S. Energy Information Administration [1]_ and downloaded on May 6, 2018. It is useful for illustrating stacked area charts.", 42 | "references": [ 43 | "https://www.eia.gov/beta/electricity/data/browser/#/topic/0?agg=2,0,1&fuel=vvg&geo=00000g&sec=g&linechart=ELEC.GEN.OTH-IA-99.A~ELEC.GEN.COW-IA-99.A~ELEC.GEN.PEL-IA-99.A~ELEC.GEN.PC-IA-99.A~ELEC.GEN.NG-IA-99.A~~ELEC.GEN.NUC-IA-99.A~ELEC.GEN.HYC-IA-99.A~ELEC.GEN.AOR-IA-99.A~ELEC.GEN.HPS-IA-99.A~&columnchart=ELEC.GEN.ALL-IA-99.A&map=ELEC.GEN.ALL-IA-99.A&freq=A&start=2001&end=2017&ctype=linechart<ype=pin&tab=overview&maptype=0&rse=0&pin=" 44 | ] 45 | }, 46 | "iris" : { 47 | "description" : "This classic dataset contains lengths and widths of petals and sepals for 150 iris flowers, drawn from three species. It was introduced by R.A. Fisher in 1936 [1]_.", 48 | "references" : [ 49 | "R. A. Fisher (1936). 'The use of multiple measurements in taxonomic problems'. Annals of Eugenics. 7 (2): 179-188." 50 | ] 51 | }, 52 | "la-riots" : { 53 | "description" : "More than 60 people lost their lives amid the looting and fires that ravaged Los Angeles for five days starting on April 29, 1992. This dataset contains metadata about each person, including the geographic coordinates of their death. It was compiled and published by the Los Angeles Times Data Desk [1]_.", 54 | "references" : [ 55 | "http://spreadsheets.latimes.com/la-riots-deaths/" 56 | ] 57 | }, 58 | "ohlc" : { 59 | "description" : "This dataset contains the performance of the Chicago Board Options Exchange `Volatility Index `_ in the summer of 2009." 60 | }, 61 | "seattle-temps" : { 62 | "description" : "This dataset contains hourly temperatures in Seattle during the full year of 2010. The dataset is drawn from public-domain `NOAA data `_, and transformed using scripts available at http://github.com/vega/vega_datasets/." 63 | }, 64 | "seattle-weather" : { 65 | "description" : "This dataset contains precipitation totals, temperature extremes, wind speed, and weather type recorded daily in Seattle from 2012 to 2015. The dataset is drawn from public-domain `NOAA data `_, and transformed using scripts available at http://github.com/vega/vega_datasets/." 66 | }, 67 | "sf-temps" : { 68 | "description" : "This dataset contains hourly temperatures in San Francisco during the full year of 2010. The dataset is drawn from public-domain `NOAA data `_, and transformed using scripts available at http://github.com/vega/vega_datasets/." 69 | }, 70 | "stocks" : { 71 | "description" : "Daily closing stock prices for AAPL, AMZN, GOOG, IBM, and MSFT between 2000 and 2010." 72 | }, 73 | "us-employment": { 74 | "description": "In the mid 2000s the global economy was hit by a crippling recession. One result: Massive job losses across the United States. The downturn in employment, and the slow recovery in hiring that followed, was tracked each month by the Current Employment Statistics [1]_ program at the U.S. Bureau of Labor Statistics. This file contains the monthly employment total in a variety of job categories from January 2006 through December 2015. The numbers are seasonally adjusted and reported in thousands. The data were downloaded on Nov. 11, 2018, and reformatted for use in this library. Because it was initially published by the U.S. government, it is in the public domain. Totals are included for the 22 'supersectors' [2]_ tracked by the BLS. The 'nonfarm' total is the category typically used by economists and journalists as a stand-in for the country's employment total. A calculated 'nonfarm_change' column has been appended with the month-to-month change in that supersector's employment. It is useful for illustrating how to make bar charts that report both negative and positive values.", 75 | "references": [ 76 | "https://www.bls.gov/ces/", 77 | "https://download.bls.gov/pub/time.series/ce/ce.supersector" 78 | ] 79 | }, 80 | "us-state-capitals": { 81 | "description": "US state capitals with latitude and longitude." 82 | }, 83 | "wheat": { 84 | "description": "In an 1822 letter to Parliament, William Playfair[1]_, a Scottish engineer who is often credited as the founder of statistical graphics, published an elegant chart on the price of wheat[2]_. It plots 250 years of prices alongside weekly wages and the reigning monarch. He intended to demonstrate that 'never at any former period was wheat so cheap, in proportion to mechanical labour, as it is at the present time.' The electronic dataset was created by Mike Bostock and released into the public domain.", 85 | "references": [ 86 | "https://en.wikipedia.org/wiki/William_Playfair", 87 | "http://dh101.humanities.ucla.edu/wp-content/uploads/2014/08/Vis_2.jpg" 88 | ] 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /priv/datasets/anscombe.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"Series":"I", "X":10.0, "Y":8.04}, 3 | {"Series":"I", "X":8.0, "Y":6.95}, 4 | {"Series":"I", "X":13.0, "Y":7.58}, 5 | {"Series":"I", "X":9.0, "Y":8.81}, 6 | {"Series":"I", "X":11.0, "Y":8.33}, 7 | {"Series":"I", "X":14.0, "Y":9.96}, 8 | {"Series":"I", "X":6.0, "Y":7.24}, 9 | {"Series":"I", "X":4.0, "Y":4.26}, 10 | {"Series":"I", "X":12.0, "Y":10.84}, 11 | {"Series":"I", "X":7.0, "Y":4.81}, 12 | {"Series":"I", "X":5.0, "Y":5.68}, 13 | 14 | {"Series":"II", "X":10.0, "Y":9.14}, 15 | {"Series":"II", "X":8.0, "Y":8.14}, 16 | {"Series":"II", "X":13.0, "Y":8.74}, 17 | {"Series":"II", "X":9.0, "Y":8.77}, 18 | {"Series":"II", "X":11.0, "Y":9.26}, 19 | {"Series":"II", "X":14.0, "Y":8.10}, 20 | {"Series":"II", "X":6.0, "Y":6.13}, 21 | {"Series":"II", "X":4.0, "Y":3.10}, 22 | {"Series":"II", "X":12.0, "Y":9.13}, 23 | {"Series":"II", "X":7.0, "Y":7.26}, 24 | {"Series":"II", "X":5.0, "Y":4.74}, 25 | 26 | {"Series":"III", "X":10.0, "Y":7.46}, 27 | {"Series":"III", "X":8.0, "Y":6.77}, 28 | {"Series":"III", "X":13.0, "Y":12.74}, 29 | {"Series":"III", "X":9.0, "Y":7.11}, 30 | {"Series":"III", "X":11.0, "Y":7.81}, 31 | {"Series":"III", "X":14.0, "Y":8.84}, 32 | {"Series":"III", "X":6.0, "Y":6.08}, 33 | {"Series":"III", "X":4.0, "Y":5.39}, 34 | {"Series":"III", "X":12.0, "Y":8.15}, 35 | {"Series":"III", "X":7.0, "Y":6.42}, 36 | {"Series":"III", "X":5.0, "Y":5.73}, 37 | 38 | {"Series":"IV", "X":8.0, "Y":6.58}, 39 | {"Series":"IV", "X":8.0, "Y":5.76}, 40 | {"Series":"IV", "X":8.0, "Y":7.71}, 41 | {"Series":"IV", "X":8.0, "Y":8.84}, 42 | {"Series":"IV", "X":8.0, "Y":8.47}, 43 | {"Series":"IV", "X":8.0, "Y":7.04}, 44 | {"Series":"IV", "X":8.0, "Y":5.25}, 45 | {"Series":"IV", "X":19.0, "Y":12.50}, 46 | {"Series":"IV", "X":8.0, "Y":5.56}, 47 | {"Series":"IV", "X":8.0, "Y":7.91}, 48 | {"Series":"IV", "X":8.0, "Y":6.89} 49 | ] 50 | -------------------------------------------------------------------------------- /priv/datasets/barley.json: -------------------------------------------------------------------------------- 1 | [{"yield":27,"variety":"Manchuria","year":1931,"site":"University Farm"}, 2 | {"yield":48.86667,"variety":"Manchuria","year":1931,"site":"Waseca"}, 3 | {"yield":27.43334,"variety":"Manchuria","year":1931,"site":"Morris"}, 4 | {"yield":39.93333,"variety":"Manchuria","year":1931,"site":"Crookston"}, 5 | {"yield":32.96667,"variety":"Manchuria","year":1931,"site":"Grand Rapids"}, 6 | {"yield":28.96667,"variety":"Manchuria","year":1931,"site":"Duluth"}, 7 | {"yield":43.06666,"variety":"Glabron","year":1931,"site":"University Farm"}, 8 | {"yield":55.2,"variety":"Glabron","year":1931,"site":"Waseca"}, 9 | {"yield":28.76667,"variety":"Glabron","year":1931,"site":"Morris"}, 10 | {"yield":38.13333,"variety":"Glabron","year":1931,"site":"Crookston"}, 11 | {"yield":29.13333,"variety":"Glabron","year":1931,"site":"Grand Rapids"}, 12 | {"yield":29.66667,"variety":"Glabron","year":1931,"site":"Duluth"}, 13 | {"yield":35.13333,"variety":"Svansota","year":1931,"site":"University Farm"}, 14 | {"yield":47.33333,"variety":"Svansota","year":1931,"site":"Waseca"}, 15 | {"yield":25.76667,"variety":"Svansota","year":1931,"site":"Morris"}, 16 | {"yield":40.46667,"variety":"Svansota","year":1931,"site":"Crookston"}, 17 | {"yield":29.66667,"variety":"Svansota","year":1931,"site":"Grand Rapids"}, 18 | {"yield":25.7,"variety":"Svansota","year":1931,"site":"Duluth"}, 19 | {"yield":39.9,"variety":"Velvet","year":1931,"site":"University Farm"}, 20 | {"yield":50.23333,"variety":"Velvet","year":1931,"site":"Waseca"}, 21 | {"yield":26.13333,"variety":"Velvet","year":1931,"site":"Morris"}, 22 | {"yield":41.33333,"variety":"Velvet","year":1931,"site":"Crookston"}, 23 | {"yield":23.03333,"variety":"Velvet","year":1931,"site":"Grand Rapids"}, 24 | {"yield":26.3,"variety":"Velvet","year":1931,"site":"Duluth"}, 25 | {"yield":36.56666,"variety":"Trebi","year":1931,"site":"University Farm"}, 26 | {"yield":63.8333,"variety":"Trebi","year":1931,"site":"Waseca"}, 27 | {"yield":43.76667,"variety":"Trebi","year":1931,"site":"Morris"}, 28 | {"yield":46.93333,"variety":"Trebi","year":1931,"site":"Crookston"}, 29 | {"yield":29.76667,"variety":"Trebi","year":1931,"site":"Grand Rapids"}, 30 | {"yield":33.93333,"variety":"Trebi","year":1931,"site":"Duluth"}, 31 | {"yield":43.26667,"variety":"No. 457","year":1931,"site":"University Farm"}, 32 | {"yield":58.1,"variety":"No. 457","year":1931,"site":"Waseca"}, 33 | {"yield":28.7,"variety":"No. 457","year":1931,"site":"Morris"}, 34 | {"yield":45.66667,"variety":"No. 457","year":1931,"site":"Crookston"}, 35 | {"yield":32.16667,"variety":"No. 457","year":1931,"site":"Grand Rapids"}, 36 | {"yield":33.6,"variety":"No. 457","year":1931,"site":"Duluth"}, 37 | {"yield":36.6,"variety":"No. 462","year":1931,"site":"University Farm"}, 38 | {"yield":65.7667,"variety":"No. 462","year":1931,"site":"Waseca"}, 39 | {"yield":30.36667,"variety":"No. 462","year":1931,"site":"Morris"}, 40 | {"yield":48.56666,"variety":"No. 462","year":1931,"site":"Crookston"}, 41 | {"yield":24.93334,"variety":"No. 462","year":1931,"site":"Grand Rapids"}, 42 | {"yield":28.1,"variety":"No. 462","year":1931,"site":"Duluth"}, 43 | {"yield":32.76667,"variety":"Peatland","year":1931,"site":"University Farm"}, 44 | {"yield":48.56666,"variety":"Peatland","year":1931,"site":"Waseca"}, 45 | {"yield":29.86667,"variety":"Peatland","year":1931,"site":"Morris"}, 46 | {"yield":41.6,"variety":"Peatland","year":1931,"site":"Crookston"}, 47 | {"yield":34.7,"variety":"Peatland","year":1931,"site":"Grand Rapids"}, 48 | {"yield":32,"variety":"Peatland","year":1931,"site":"Duluth"}, 49 | {"yield":24.66667,"variety":"No. 475","year":1931,"site":"University Farm"}, 50 | {"yield":46.76667,"variety":"No. 475","year":1931,"site":"Waseca"}, 51 | {"yield":22.6,"variety":"No. 475","year":1931,"site":"Morris"}, 52 | {"yield":44.1,"variety":"No. 475","year":1931,"site":"Crookston"}, 53 | {"yield":19.7,"variety":"No. 475","year":1931,"site":"Grand Rapids"}, 54 | {"yield":33.06666,"variety":"No. 475","year":1931,"site":"Duluth"}, 55 | {"yield":39.3,"variety":"Wisconsin No. 38","year":1931,"site":"University Farm"}, 56 | {"yield":58.8,"variety":"Wisconsin No. 38","year":1931,"site":"Waseca"}, 57 | {"yield":29.46667,"variety":"Wisconsin No. 38","year":1931,"site":"Morris"}, 58 | {"yield":49.86667,"variety":"Wisconsin No. 38","year":1931,"site":"Crookston"}, 59 | {"yield":34.46667,"variety":"Wisconsin No. 38","year":1931,"site":"Grand Rapids"}, 60 | {"yield":31.6,"variety":"Wisconsin No. 38","year":1931,"site":"Duluth"}, 61 | {"yield":26.9,"variety":"Manchuria","year":1932,"site":"University Farm"}, 62 | {"yield":33.46667,"variety":"Manchuria","year":1932,"site":"Waseca"}, 63 | {"yield":34.36666,"variety":"Manchuria","year":1932,"site":"Morris"}, 64 | {"yield":32.96667,"variety":"Manchuria","year":1932,"site":"Crookston"}, 65 | {"yield":22.13333,"variety":"Manchuria","year":1932,"site":"Grand Rapids"}, 66 | {"yield":22.56667,"variety":"Manchuria","year":1932,"site":"Duluth"}, 67 | {"yield":36.8,"variety":"Glabron","year":1932,"site":"University Farm"}, 68 | {"yield":37.73333,"variety":"Glabron","year":1932,"site":"Waseca"}, 69 | {"yield":35.13333,"variety":"Glabron","year":1932,"site":"Morris"}, 70 | {"yield":26.16667,"variety":"Glabron","year":1932,"site":"Crookston"}, 71 | {"yield":14.43333,"variety":"Glabron","year":1932,"site":"Grand Rapids"}, 72 | {"yield":25.86667,"variety":"Glabron","year":1932,"site":"Duluth"}, 73 | {"yield":27.43334,"variety":"Svansota","year":1932,"site":"University Farm"}, 74 | {"yield":38.5,"variety":"Svansota","year":1932,"site":"Waseca"}, 75 | {"yield":35.03333,"variety":"Svansota","year":1932,"site":"Morris"}, 76 | {"yield":20.63333,"variety":"Svansota","year":1932,"site":"Crookston"}, 77 | {"yield":16.63333,"variety":"Svansota","year":1932,"site":"Grand Rapids"}, 78 | {"yield":22.23333,"variety":"Svansota","year":1932,"site":"Duluth"}, 79 | {"yield":26.8,"variety":"Velvet","year":1932,"site":"University Farm"}, 80 | {"yield":37.4,"variety":"Velvet","year":1932,"site":"Waseca"}, 81 | {"yield":38.83333,"variety":"Velvet","year":1932,"site":"Morris"}, 82 | {"yield":32.06666,"variety":"Velvet","year":1932,"site":"Crookston"}, 83 | {"yield":32.23333,"variety":"Velvet","year":1932,"site":"Grand Rapids"}, 84 | {"yield":22.46667,"variety":"Velvet","year":1932,"site":"Duluth"}, 85 | {"yield":29.06667,"variety":"Trebi","year":1932,"site":"University Farm"}, 86 | {"yield":49.2333,"variety":"Trebi","year":1932,"site":"Waseca"}, 87 | {"yield":46.63333,"variety":"Trebi","year":1932,"site":"Morris"}, 88 | {"yield":41.83333,"variety":"Trebi","year":1932,"site":"Crookston"}, 89 | {"yield":20.63333,"variety":"Trebi","year":1932,"site":"Grand Rapids"}, 90 | {"yield":30.6,"variety":"Trebi","year":1932,"site":"Duluth"}, 91 | {"yield":26.43334,"variety":"No. 457","year":1932,"site":"University Farm"}, 92 | {"yield":42.2,"variety":"No. 457","year":1932,"site":"Waseca"}, 93 | {"yield":43.53334,"variety":"No. 457","year":1932,"site":"Morris"}, 94 | {"yield":34.33333,"variety":"No. 457","year":1932,"site":"Crookston"}, 95 | {"yield":19.46667,"variety":"No. 457","year":1932,"site":"Grand Rapids"}, 96 | {"yield":22.7,"variety":"No. 457","year":1932,"site":"Duluth"}, 97 | {"yield":25.56667,"variety":"No. 462","year":1932,"site":"University Farm"}, 98 | {"yield":44.7,"variety":"No. 462","year":1932,"site":"Waseca"}, 99 | {"yield":47,"variety":"No. 462","year":1932,"site":"Morris"}, 100 | {"yield":30.53333,"variety":"No. 462","year":1932,"site":"Crookston"}, 101 | {"yield":19.9,"variety":"No. 462","year":1932,"site":"Grand Rapids"}, 102 | {"yield":22.5,"variety":"No. 462","year":1932,"site":"Duluth"}, 103 | {"yield":28.06667,"variety":"Peatland","year":1932,"site":"University Farm"}, 104 | {"yield":36.03333,"variety":"Peatland","year":1932,"site":"Waseca"}, 105 | {"yield":43.2,"variety":"Peatland","year":1932,"site":"Morris"}, 106 | {"yield":25.23333,"variety":"Peatland","year":1932,"site":"Crookston"}, 107 | {"yield":26.76667,"variety":"Peatland","year":1932,"site":"Grand Rapids"}, 108 | {"yield":31.36667,"variety":"Peatland","year":1932,"site":"Duluth"}, 109 | {"yield":30,"variety":"No. 475","year":1932,"site":"University Farm"}, 110 | {"yield":41.26667,"variety":"No. 475","year":1932,"site":"Waseca"}, 111 | {"yield":44.23333,"variety":"No. 475","year":1932,"site":"Morris"}, 112 | {"yield":32.13333,"variety":"No. 475","year":1932,"site":"Crookston"}, 113 | {"yield":15.23333,"variety":"No. 475","year":1932,"site":"Grand Rapids"}, 114 | {"yield":27.36667,"variety":"No. 475","year":1932,"site":"Duluth"}, 115 | {"yield":38,"variety":"Wisconsin No. 38","year":1932,"site":"University Farm"}, 116 | {"yield":58.16667,"variety":"Wisconsin No. 38","year":1932,"site":"Waseca"}, 117 | {"yield":47.16667,"variety":"Wisconsin No. 38","year":1932,"site":"Morris"}, 118 | {"yield":35.9,"variety":"Wisconsin No. 38","year":1932,"site":"Crookston"}, 119 | {"yield":20.66667,"variety":"Wisconsin No. 38","year":1932,"site":"Grand Rapids"}, 120 | {"yield":29.33333,"variety":"Wisconsin No. 38","year":1932,"site":"Duluth"}] -------------------------------------------------------------------------------- /priv/datasets/burtin.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Bacteria":"Aerobacter aerogenes", 4 | "Penicillin":870, 5 | "Streptomycin":1, 6 | "Neomycin":1.6, 7 | "Gram_Staining":"negative", 8 | "Genus": "other" 9 | }, 10 | { 11 | "Bacteria":"Bacillus anthracis", 12 | "Penicillin":0.001, 13 | "Streptomycin":0.01, 14 | "Neomycin":0.007, 15 | "Gram_Staining":"positive", 16 | "Genus": "other" 17 | }, 18 | { 19 | "Bacteria":"Brucella abortus", 20 | "Penicillin":1, 21 | "Streptomycin":2, 22 | "Neomycin":0.02, 23 | "Gram_Staining":"negative", 24 | "Genus": "other" 25 | }, 26 | { 27 | "Bacteria":"Diplococcus pneumoniae", 28 | "Penicillin":0.005, 29 | "Streptomycin":11, 30 | "Neomycin":10, 31 | "Gram_Staining":"positive", 32 | "Genus": "other" 33 | }, 34 | { 35 | "Bacteria":"Escherichia coli", 36 | "Penicillin":100, 37 | "Streptomycin":0.4, 38 | "Neomycin":0.1, 39 | "Gram_Staining":"negative", 40 | "Genus": "other" 41 | }, 42 | { 43 | "Bacteria":"Klebsiella pneumoniae", 44 | "Penicillin":850, 45 | "Streptomycin":1.2, 46 | "Neomycin":1, 47 | "Gram_Staining":"negative", 48 | "Genus": "other" 49 | }, 50 | { 51 | "Bacteria":"Mycobacterium tuberculosis", 52 | "Penicillin":800, 53 | "Streptomycin":5, 54 | "Neomycin":2, 55 | "Gram_Staining":"negative", 56 | "Genus": "other" 57 | }, 58 | { 59 | "Bacteria":"Proteus vulgaris", 60 | "Penicillin":3, 61 | "Streptomycin":0.1, 62 | "Neomycin":0.1, 63 | "Gram_Staining":"negative", 64 | "Genus": "other" 65 | }, 66 | { 67 | "Bacteria":"Pseudomonas aeruginosa", 68 | "Penicillin":850, 69 | "Streptomycin":2, 70 | "Neomycin":0.4, 71 | "Gram_Staining":"negative", 72 | "Genus": "other" 73 | }, 74 | { 75 | "Bacteria":"Salmonella (Eberthella) typhosa", 76 | "Penicillin":1, 77 | "Streptomycin":0.4, 78 | "Neomycin":0.008, 79 | "Gram_Staining":"negative", 80 | "Genus": "Salmonella" 81 | }, 82 | { 83 | "Bacteria":"Salmonella schottmuelleri", 84 | "Penicillin":10, 85 | "Streptomycin":0.8, 86 | "Neomycin":0.09, 87 | "Gram_Staining":"negative", 88 | "Genus": "Salmonella" 89 | }, 90 | { 91 | "Bacteria":"Staphylococcus albus", 92 | "Penicillin":0.007, 93 | "Streptomycin":0.1, 94 | "Neomycin":0.001, 95 | "Gram_Staining":"positive", 96 | "Genus": "Staphylococcus" 97 | }, 98 | { 99 | "Bacteria":"Staphylococcus aureus", 100 | "Penicillin":0.03, 101 | "Streptomycin":0.03, 102 | "Neomycin":0.001, 103 | "Gram_Staining":"positive", 104 | "Genus": "Staphylococcus" 105 | }, 106 | { 107 | "Bacteria":"Streptococcus fecalis", 108 | "Penicillin":1, 109 | "Streptomycin":1, 110 | "Neomycin":0.1, 111 | "Gram_Staining":"positive", 112 | "Genus": "Streptococcus" 113 | }, 114 | { 115 | "Bacteria":"Streptococcus hemolyticus", 116 | "Penicillin":0.001, 117 | "Streptomycin":14, 118 | "Neomycin":10, 119 | "Gram_Staining":"positive", 120 | "Genus": "Streptococcus" 121 | }, 122 | { 123 | "Bacteria":"Streptococcus viridans", 124 | "Penicillin":0.005, 125 | "Streptomycin":10, 126 | "Neomycin":40, 127 | "Gram_Staining":"positive", 128 | "Genus": "Streptococcus" 129 | } 130 | ] 131 | -------------------------------------------------------------------------------- /priv/datasets/crimea.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "date": "1854-04-01", "wounds": 0, "other": 110, "disease": 110 }, 3 | { "date": "1854-05-01", "wounds": 0, "other": 95, "disease": 105 }, 4 | { "date": "1854-06-01", "wounds": 0, "other": 40, "disease": 95 }, 5 | { "date": "1854-07-01", "wounds": 0, "other": 140, "disease": 520 }, 6 | { "date": "1854-08-01", "wounds": 20, "other": 150, "disease": 800 }, 7 | { "date": "1854-09-01", "wounds": 220, "other": 230, "disease": 740 }, 8 | { "date": "1854-10-01", "wounds": 305, "other": 310, "disease": 600 }, 9 | { "date": "1854-11-01", "wounds": 480, "other": 290, "disease": 820 }, 10 | { "date": "1854-12-01", "wounds": 295, "other": 310, "disease": 1100 }, 11 | { "date": "1855-01-01", "wounds": 230, "other": 460, "disease": 1440 }, 12 | { "date": "1855-02-01", "wounds": 180, "other": 520, "disease": 1270 }, 13 | { "date": "1855-03-01", "wounds": 155, "other": 350, "disease": 935 }, 14 | { "date": "1855-04-01", "wounds": 195, "other": 195, "disease": 560 }, 15 | { "date": "1855-05-01", "wounds": 180, "other": 155, "disease": 550 }, 16 | { "date": "1855-06-01", "wounds": 330, "other": 130, "disease": 650 }, 17 | { "date": "1855-07-01", "wounds": 260, "other": 130, "disease": 430 }, 18 | { "date": "1855-08-01", "wounds": 290, "other": 110, "disease": 490 }, 19 | { "date": "1855-09-01", "wounds": 355, "other": 100, "disease": 290 }, 20 | { "date": "1855-10-01", "wounds": 135, "other": 95, "disease": 245 }, 21 | { "date": "1855-11-01", "wounds": 100, "other": 140, "disease": 325 }, 22 | { "date": "1855-12-01", "wounds": 40, "other": 120, "disease": 215 }, 23 | { "date": "1856-01-01", "wounds": 0, "other": 160, "disease": 160 }, 24 | { "date": "1856-02-01", "wounds": 0, "other": 100, "disease": 100 }, 25 | { "date": "1856-03-01", "wounds": 0, "other": 125, "disease": 90 } 26 | ] 27 | -------------------------------------------------------------------------------- /priv/datasets/driving.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"side": "left", "year": 1956, "miles": 3675, "gas": 2.38}, 3 | {"side": "right", "year": 1957, "miles": 3706, "gas": 2.40}, 4 | {"side": "bottom", "year": 1958, "miles": 3766, "gas": 2.26}, 5 | {"side": "top", "year": 1959, "miles": 3905, "gas": 2.31}, 6 | {"side": "right", "year": 1960, "miles": 3935, "gas": 2.27}, 7 | {"side": "bottom", "year": 1961, "miles": 3977, "gas": 2.25}, 8 | {"side": "right", "year": 1962, "miles": 4085, "gas": 2.22}, 9 | {"side": "bottom", "year": 1963, "miles": 4218, "gas": 2.12}, 10 | {"side": "bottom", "year": 1964, "miles": 4369, "gas": 2.11}, 11 | {"side": "bottom", "year": 1965, "miles": 4538, "gas": 2.14}, 12 | {"side": "top", "year": 1966, "miles": 4676, "gas": 2.14}, 13 | {"side": "bottom", "year": 1967, "miles": 4827, "gas": 2.14}, 14 | {"side": "right", "year": 1968, "miles": 5038, "gas": 2.13}, 15 | {"side": "right", "year": 1969, "miles": 5207, "gas": 2.07}, 16 | {"side": "right", "year": 1970, "miles": 5376, "gas": 2.01}, 17 | {"side": "bottom", "year": 1971, "miles": 5617, "gas": 1.93}, 18 | {"side": "bottom", "year": 1972, "miles": 5973, "gas": 1.87}, 19 | {"side": "right", "year": 1973, "miles": 6154, "gas": 1.90}, 20 | {"side": "left", "year": 1974, "miles": 5943, "gas": 2.34}, 21 | {"side": "bottom", "year": 1975, "miles": 6111, "gas": 2.31}, 22 | {"side": "bottom", "year": 1976, "miles": 6389, "gas": 2.32}, 23 | {"side": "top", "year": 1977, "miles": 6630, "gas": 2.36}, 24 | {"side": "bottom", "year": 1978, "miles": 6883, "gas": 2.23}, 25 | {"side": "left", "year": 1979, "miles": 6744, "gas": 2.68}, 26 | {"side": "left", "year": 1980, "miles": 6672, "gas": 3.30}, 27 | {"side": "right", "year": 1981, "miles": 6732, "gas": 3.30}, 28 | {"side": "right", "year": 1982, "miles": 6835, "gas": 2.92}, 29 | {"side": "right", "year": 1983, "miles": 6943, "gas": 2.66}, 30 | {"side": "right", "year": 1984, "miles": 7130, "gas": 2.48}, 31 | {"side": "right", "year": 1985, "miles": 7323, "gas": 2.36}, 32 | {"side": "left", "year": 1986, "miles": 7558, "gas": 1.76}, 33 | {"side": "top", "year": 1987, "miles": 7770, "gas": 1.76}, 34 | {"side": "bottom", "year": 1988, "miles": 8089, "gas": 1.68}, 35 | {"side": "left", "year": 1989, "miles": 8397, "gas": 1.75}, 36 | {"side": "top", "year": 1990, "miles": 8529, "gas": 1.88}, 37 | {"side": "right", "year": 1991, "miles": 8535, "gas": 1.78}, 38 | {"side": "right", "year": 1992, "miles": 8662, "gas": 1.69}, 39 | {"side": "left", "year": 1993, "miles": 8855, "gas": 1.60}, 40 | {"side": "bottom", "year": 1994, "miles": 8909, "gas": 1.59}, 41 | {"side": "bottom", "year": 1995, "miles": 9150, "gas": 1.60}, 42 | {"side": "top", "year": 1996, "miles": 9192, "gas": 1.67}, 43 | {"side": "right", "year": 1997, "miles": 9416, "gas": 1.65}, 44 | {"side": "bottom", "year": 1998, "miles": 9590, "gas": 1.39}, 45 | {"side": "right", "year": 1999, "miles": 9687, "gas": 1.50}, 46 | {"side": "top", "year": 2000, "miles": 9717, "gas": 1.89}, 47 | {"side": "left", "year": 2001, "miles": 9699, "gas": 1.77}, 48 | {"side": "bottom", "year": 2002, "miles": 9814, "gas": 1.64}, 49 | {"side": "right", "year": 2003, "miles": 9868, "gas": 1.86}, 50 | {"side": "left", "year": 2004, "miles": 9994, "gas": 2.14}, 51 | {"side": "left", "year": 2005, "miles": 10067, "gas": 2.53}, 52 | {"side": "right", "year": 2006, "miles": 10037, "gas": 2.79}, 53 | {"side": "right", "year": 2007, "miles": 10025, "gas": 2.95}, 54 | {"side": "left", "year": 2008, "miles": 9880, "gas": 3.31}, 55 | {"side": "bottom", "year": 2009, "miles": 9657, "gas": 2.38}, 56 | {"side": "left", "year": 2010, "miles": 9596, "gas": 2.61} 57 | ] -------------------------------------------------------------------------------- /priv/datasets/iowa-electricity.csv: -------------------------------------------------------------------------------- 1 | year,source,net_generation 2 | 2001-01-01,Fossil Fuels,35361 3 | 2002-01-01,Fossil Fuels,35991 4 | 2003-01-01,Fossil Fuels,36234 5 | 2004-01-01,Fossil Fuels,36205 6 | 2005-01-01,Fossil Fuels,36883 7 | 2006-01-01,Fossil Fuels,37014 8 | 2007-01-01,Fossil Fuels,41389 9 | 2008-01-01,Fossil Fuels,42734 10 | 2009-01-01,Fossil Fuels,38620 11 | 2010-01-01,Fossil Fuels,42750 12 | 2011-01-01,Fossil Fuels,39361 13 | 2012-01-01,Fossil Fuels,37379 14 | 2013-01-01,Fossil Fuels,34873 15 | 2014-01-01,Fossil Fuels,35250 16 | 2015-01-01,Fossil Fuels,32319 17 | 2016-01-01,Fossil Fuels,28437 18 | 2017-01-01,Fossil Fuels,29329 19 | 2001-01-01,Nuclear Energy,3853 20 | 2002-01-01,Nuclear Energy,4574 21 | 2003-01-01,Nuclear Energy,3988 22 | 2004-01-01,Nuclear Energy,4929 23 | 2005-01-01,Nuclear Energy,4538 24 | 2006-01-01,Nuclear Energy,5095 25 | 2007-01-01,Nuclear Energy,4519 26 | 2008-01-01,Nuclear Energy,5282 27 | 2009-01-01,Nuclear Energy,4679 28 | 2010-01-01,Nuclear Energy,4451 29 | 2011-01-01,Nuclear Energy,5215 30 | 2012-01-01,Nuclear Energy,4347 31 | 2013-01-01,Nuclear Energy,5321 32 | 2014-01-01,Nuclear Energy,4152 33 | 2015-01-01,Nuclear Energy,5243 34 | 2016-01-01,Nuclear Energy,4703 35 | 2017-01-01,Nuclear Energy,5214 36 | 2001-01-01,Renewables,1437 37 | 2002-01-01,Renewables,1963 38 | 2003-01-01,Renewables,1885 39 | 2004-01-01,Renewables,2102 40 | 2005-01-01,Renewables,2724 41 | 2006-01-01,Renewables,3364 42 | 2007-01-01,Renewables,3870 43 | 2008-01-01,Renewables,5070 44 | 2009-01-01,Renewables,8560 45 | 2010-01-01,Renewables,10308 46 | 2011-01-01,Renewables,11795 47 | 2012-01-01,Renewables,14949 48 | 2013-01-01,Renewables,16476 49 | 2014-01-01,Renewables,17452 50 | 2015-01-01,Renewables,19091 51 | 2016-01-01,Renewables,21241 52 | 2017-01-01,Renewables,21933 53 | -------------------------------------------------------------------------------- /priv/datasets/iris.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"sepalLength": 5.1, "sepalWidth": 3.5, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"}, 3 | {"sepalLength": 4.9, "sepalWidth": 3.0, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"}, 4 | {"sepalLength": 4.7, "sepalWidth": 3.2, "petalLength": 1.3, "petalWidth": 0.2, "species": "setosa"}, 5 | {"sepalLength": 4.6, "sepalWidth": 3.1, "petalLength": 1.5, "petalWidth": 0.2, "species": "setosa"}, 6 | {"sepalLength": 5.0, "sepalWidth": 3.6, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"}, 7 | {"sepalLength": 5.4, "sepalWidth": 3.9, "petalLength": 1.7, "petalWidth": 0.4, "species": "setosa"}, 8 | {"sepalLength": 4.6, "sepalWidth": 3.4, "petalLength": 1.4, "petalWidth": 0.3, "species": "setosa"}, 9 | {"sepalLength": 5.0, "sepalWidth": 3.4, "petalLength": 1.5, "petalWidth": 0.2, "species": "setosa"}, 10 | {"sepalLength": 4.4, "sepalWidth": 2.9, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"}, 11 | {"sepalLength": 4.9, "sepalWidth": 3.1, "petalLength": 1.5, "petalWidth": 0.1, "species": "setosa"}, 12 | {"sepalLength": 5.4, "sepalWidth": 3.7, "petalLength": 1.5, "petalWidth": 0.2, "species": "setosa"}, 13 | {"sepalLength": 4.8, "sepalWidth": 3.4, "petalLength": 1.6, "petalWidth": 0.2, "species": "setosa"}, 14 | {"sepalLength": 4.8, "sepalWidth": 3.0, "petalLength": 1.4, "petalWidth": 0.1, "species": "setosa"}, 15 | {"sepalLength": 4.3, "sepalWidth": 3.0, "petalLength": 1.1, "petalWidth": 0.1, "species": "setosa"}, 16 | {"sepalLength": 5.8, "sepalWidth": 4.0, "petalLength": 1.2, "petalWidth": 0.2, "species": "setosa"}, 17 | {"sepalLength": 5.7, "sepalWidth": 4.4, "petalLength": 1.5, "petalWidth": 0.4, "species": "setosa"}, 18 | {"sepalLength": 5.4, "sepalWidth": 3.9, "petalLength": 1.3, "petalWidth": 0.4, "species": "setosa"}, 19 | {"sepalLength": 5.1, "sepalWidth": 3.5, "petalLength": 1.4, "petalWidth": 0.3, "species": "setosa"}, 20 | {"sepalLength": 5.7, "sepalWidth": 3.8, "petalLength": 1.7, "petalWidth": 0.3, "species": "setosa"}, 21 | {"sepalLength": 5.1, "sepalWidth": 3.8, "petalLength": 1.5, "petalWidth": 0.3, "species": "setosa"}, 22 | {"sepalLength": 5.4, "sepalWidth": 3.4, "petalLength": 1.7, "petalWidth": 0.2, "species": "setosa"}, 23 | {"sepalLength": 5.1, "sepalWidth": 3.7, "petalLength": 1.5, "petalWidth": 0.4, "species": "setosa"}, 24 | {"sepalLength": 4.6, "sepalWidth": 3.6, "petalLength": 1.0, "petalWidth": 0.2, "species": "setosa"}, 25 | {"sepalLength": 5.1, "sepalWidth": 3.3, "petalLength": 1.7, "petalWidth": 0.5, "species": "setosa"}, 26 | {"sepalLength": 4.8, "sepalWidth": 3.4, "petalLength": 1.9, "petalWidth": 0.2, "species": "setosa"}, 27 | {"sepalLength": 5.0, "sepalWidth": 3.0, "petalLength": 1.6, "petalWidth": 0.2, "species": "setosa"}, 28 | {"sepalLength": 5.0, "sepalWidth": 3.4, "petalLength": 1.6, "petalWidth": 0.4, "species": "setosa"}, 29 | {"sepalLength": 5.2, "sepalWidth": 3.5, "petalLength": 1.5, "petalWidth": 0.2, "species": "setosa"}, 30 | {"sepalLength": 5.2, "sepalWidth": 3.4, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"}, 31 | {"sepalLength": 4.7, "sepalWidth": 3.2, "petalLength": 1.6, "petalWidth": 0.2, "species": "setosa"}, 32 | {"sepalLength": 4.8, "sepalWidth": 3.1, "petalLength": 1.6, "petalWidth": 0.2, "species": "setosa"}, 33 | {"sepalLength": 5.4, "sepalWidth": 3.4, "petalLength": 1.5, "petalWidth": 0.4, "species": "setosa"}, 34 | {"sepalLength": 5.2, "sepalWidth": 4.1, "petalLength": 1.5, "petalWidth": 0.1, "species": "setosa"}, 35 | {"sepalLength": 5.5, "sepalWidth": 4.2, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"}, 36 | {"sepalLength": 4.9, "sepalWidth": 3.1, "petalLength": 1.5, "petalWidth": 0.2, "species": "setosa"}, 37 | {"sepalLength": 5.0, "sepalWidth": 3.2, "petalLength": 1.2, "petalWidth": 0.2, "species": "setosa"}, 38 | {"sepalLength": 5.5, "sepalWidth": 3.5, "petalLength": 1.3, "petalWidth": 0.2, "species": "setosa"}, 39 | {"sepalLength": 4.9, "sepalWidth": 3.6, "petalLength": 1.4, "petalWidth": 0.1, "species": "setosa"}, 40 | {"sepalLength": 4.4, "sepalWidth": 3.0, "petalLength": 1.3, "petalWidth": 0.2, "species": "setosa"}, 41 | {"sepalLength": 5.1, "sepalWidth": 3.4, "petalLength": 1.5, "petalWidth": 0.2, "species": "setosa"}, 42 | {"sepalLength": 5.0, "sepalWidth": 3.5, "petalLength": 1.3, "petalWidth": 0.3, "species": "setosa"}, 43 | {"sepalLength": 4.5, "sepalWidth": 2.3, "petalLength": 1.3, "petalWidth": 0.3, "species": "setosa"}, 44 | {"sepalLength": 4.4, "sepalWidth": 3.2, "petalLength": 1.3, "petalWidth": 0.2, "species": "setosa"}, 45 | {"sepalLength": 5.0, "sepalWidth": 3.5, "petalLength": 1.6, "petalWidth": 0.6, "species": "setosa"}, 46 | {"sepalLength": 5.1, "sepalWidth": 3.8, "petalLength": 1.9, "petalWidth": 0.4, "species": "setosa"}, 47 | {"sepalLength": 4.8, "sepalWidth": 3.0, "petalLength": 1.4, "petalWidth": 0.3, "species": "setosa"}, 48 | {"sepalLength": 5.1, "sepalWidth": 3.8, "petalLength": 1.6, "petalWidth": 0.2, "species": "setosa"}, 49 | {"sepalLength": 4.6, "sepalWidth": 3.2, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"}, 50 | {"sepalLength": 5.3, "sepalWidth": 3.7, "petalLength": 1.5, "petalWidth": 0.2, "species": "setosa"}, 51 | {"sepalLength": 5.0, "sepalWidth": 3.3, "petalLength": 1.4, "petalWidth": 0.2, "species": "setosa"}, 52 | {"sepalLength": 7.0, "sepalWidth": 3.2, "petalLength": 4.7, "petalWidth": 1.4, "species": "versicolor"}, 53 | {"sepalLength": 6.4, "sepalWidth": 3.2, "petalLength": 4.5, "petalWidth": 1.5, "species": "versicolor"}, 54 | {"sepalLength": 6.9, "sepalWidth": 3.1, "petalLength": 4.9, "petalWidth": 1.5, "species": "versicolor"}, 55 | {"sepalLength": 5.5, "sepalWidth": 2.3, "petalLength": 4.0, "petalWidth": 1.3, "species": "versicolor"}, 56 | {"sepalLength": 6.5, "sepalWidth": 2.8, "petalLength": 4.6, "petalWidth": 1.5, "species": "versicolor"}, 57 | {"sepalLength": 5.7, "sepalWidth": 2.8, "petalLength": 4.5, "petalWidth": 1.3, "species": "versicolor"}, 58 | {"sepalLength": 6.3, "sepalWidth": 3.3, "petalLength": 4.7, "petalWidth": 1.6, "species": "versicolor"}, 59 | {"sepalLength": 4.9, "sepalWidth": 2.4, "petalLength": 3.3, "petalWidth": 1.0, "species": "versicolor"}, 60 | {"sepalLength": 6.6, "sepalWidth": 2.9, "petalLength": 4.6, "petalWidth": 1.3, "species": "versicolor"}, 61 | {"sepalLength": 5.2, "sepalWidth": 2.7, "petalLength": 3.9, "petalWidth": 1.4, "species": "versicolor"}, 62 | {"sepalLength": 5.0, "sepalWidth": 2.0, "petalLength": 3.5, "petalWidth": 1.0, "species": "versicolor"}, 63 | {"sepalLength": 5.9, "sepalWidth": 3.0, "petalLength": 4.2, "petalWidth": 1.5, "species": "versicolor"}, 64 | {"sepalLength": 6.0, "sepalWidth": 2.2, "petalLength": 4.0, "petalWidth": 1.0, "species": "versicolor"}, 65 | {"sepalLength": 6.1, "sepalWidth": 2.9, "petalLength": 4.7, "petalWidth": 1.4, "species": "versicolor"}, 66 | {"sepalLength": 5.6, "sepalWidth": 2.9, "petalLength": 3.6, "petalWidth": 1.3, "species": "versicolor"}, 67 | {"sepalLength": 6.7, "sepalWidth": 3.1, "petalLength": 4.4, "petalWidth": 1.4, "species": "versicolor"}, 68 | {"sepalLength": 5.6, "sepalWidth": 3.0, "petalLength": 4.5, "petalWidth": 1.5, "species": "versicolor"}, 69 | {"sepalLength": 5.8, "sepalWidth": 2.7, "petalLength": 4.1, "petalWidth": 1.0, "species": "versicolor"}, 70 | {"sepalLength": 6.2, "sepalWidth": 2.2, "petalLength": 4.5, "petalWidth": 1.5, "species": "versicolor"}, 71 | {"sepalLength": 5.6, "sepalWidth": 2.5, "petalLength": 3.9, "petalWidth": 1.1, "species": "versicolor"}, 72 | {"sepalLength": 5.9, "sepalWidth": 3.2, "petalLength": 4.8, "petalWidth": 1.8, "species": "versicolor"}, 73 | {"sepalLength": 6.1, "sepalWidth": 2.8, "petalLength": 4.0, "petalWidth": 1.3, "species": "versicolor"}, 74 | {"sepalLength": 6.3, "sepalWidth": 2.5, "petalLength": 4.9, "petalWidth": 1.5, "species": "versicolor"}, 75 | {"sepalLength": 6.1, "sepalWidth": 2.8, "petalLength": 4.7, "petalWidth": 1.2, "species": "versicolor"}, 76 | {"sepalLength": 6.4, "sepalWidth": 2.9, "petalLength": 4.3, "petalWidth": 1.3, "species": "versicolor"}, 77 | {"sepalLength": 6.6, "sepalWidth": 3.0, "petalLength": 4.4, "petalWidth": 1.4, "species": "versicolor"}, 78 | {"sepalLength": 6.8, "sepalWidth": 2.8, "petalLength": 4.8, "petalWidth": 1.4, "species": "versicolor"}, 79 | {"sepalLength": 6.7, "sepalWidth": 3.0, "petalLength": 5.0, "petalWidth": 1.7, "species": "versicolor"}, 80 | {"sepalLength": 6.0, "sepalWidth": 2.9, "petalLength": 4.5, "petalWidth": 1.5, "species": "versicolor"}, 81 | {"sepalLength": 5.7, "sepalWidth": 2.6, "petalLength": 3.5, "petalWidth": 1.0, "species": "versicolor"}, 82 | {"sepalLength": 5.5, "sepalWidth": 2.4, "petalLength": 3.8, "petalWidth": 1.1, "species": "versicolor"}, 83 | {"sepalLength": 5.5, "sepalWidth": 2.4, "petalLength": 3.7, "petalWidth": 1.0, "species": "versicolor"}, 84 | {"sepalLength": 5.8, "sepalWidth": 2.7, "petalLength": 3.9, "petalWidth": 1.2, "species": "versicolor"}, 85 | {"sepalLength": 6.0, "sepalWidth": 2.7, "petalLength": 5.1, "petalWidth": 1.6, "species": "versicolor"}, 86 | {"sepalLength": 5.4, "sepalWidth": 3.0, "petalLength": 4.5, "petalWidth": 1.5, "species": "versicolor"}, 87 | {"sepalLength": 6.0, "sepalWidth": 3.4, "petalLength": 4.5, "petalWidth": 1.6, "species": "versicolor"}, 88 | {"sepalLength": 6.7, "sepalWidth": 3.1, "petalLength": 4.7, "petalWidth": 1.5, "species": "versicolor"}, 89 | {"sepalLength": 6.3, "sepalWidth": 2.3, "petalLength": 4.4, "petalWidth": 1.3, "species": "versicolor"}, 90 | {"sepalLength": 5.6, "sepalWidth": 3.0, "petalLength": 4.1, "petalWidth": 1.3, "species": "versicolor"}, 91 | {"sepalLength": 5.5, "sepalWidth": 2.5, "petalLength": 4.0, "petalWidth": 1.3, "species": "versicolor"}, 92 | {"sepalLength": 5.5, "sepalWidth": 2.6, "petalLength": 4.4, "petalWidth": 1.2, "species": "versicolor"}, 93 | {"sepalLength": 6.1, "sepalWidth": 3.0, "petalLength": 4.6, "petalWidth": 1.4, "species": "versicolor"}, 94 | {"sepalLength": 5.8, "sepalWidth": 2.6, "petalLength": 4.0, "petalWidth": 1.2, "species": "versicolor"}, 95 | {"sepalLength": 5.0, "sepalWidth": 2.3, "petalLength": 3.3, "petalWidth": 1.0, "species": "versicolor"}, 96 | {"sepalLength": 5.6, "sepalWidth": 2.7, "petalLength": 4.2, "petalWidth": 1.3, "species": "versicolor"}, 97 | {"sepalLength": 5.7, "sepalWidth": 3.0, "petalLength": 4.2, "petalWidth": 1.2, "species": "versicolor"}, 98 | {"sepalLength": 5.7, "sepalWidth": 2.9, "petalLength": 4.2, "petalWidth": 1.3, "species": "versicolor"}, 99 | {"sepalLength": 6.2, "sepalWidth": 2.9, "petalLength": 4.3, "petalWidth": 1.3, "species": "versicolor"}, 100 | {"sepalLength": 5.1, "sepalWidth": 2.5, "petalLength": 3.0, "petalWidth": 1.1, "species": "versicolor"}, 101 | {"sepalLength": 5.7, "sepalWidth": 2.8, "petalLength": 4.1, "petalWidth": 1.3, "species": "versicolor"}, 102 | {"sepalLength": 6.3, "sepalWidth": 3.3, "petalLength": 6.0, "petalWidth": 2.5, "species": "virginica"}, 103 | {"sepalLength": 5.8, "sepalWidth": 2.7, "petalLength": 5.1, "petalWidth": 1.9, "species": "virginica"}, 104 | {"sepalLength": 7.1, "sepalWidth": 3.0, "petalLength": 5.9, "petalWidth": 2.1, "species": "virginica"}, 105 | {"sepalLength": 6.3, "sepalWidth": 2.9, "petalLength": 5.6, "petalWidth": 1.8, "species": "virginica"}, 106 | {"sepalLength": 6.5, "sepalWidth": 3.0, "petalLength": 5.8, "petalWidth": 2.2, "species": "virginica"}, 107 | {"sepalLength": 7.6, "sepalWidth": 3.0, "petalLength": 6.6, "petalWidth": 2.1, "species": "virginica"}, 108 | {"sepalLength": 4.9, "sepalWidth": 2.5, "petalLength": 4.5, "petalWidth": 1.7, "species": "virginica"}, 109 | {"sepalLength": 7.3, "sepalWidth": 2.9, "petalLength": 6.3, "petalWidth": 1.8, "species": "virginica"}, 110 | {"sepalLength": 6.7, "sepalWidth": 2.5, "petalLength": 5.8, "petalWidth": 1.8, "species": "virginica"}, 111 | {"sepalLength": 7.2, "sepalWidth": 3.6, "petalLength": 6.1, "petalWidth": 2.5, "species": "virginica"}, 112 | {"sepalLength": 6.5, "sepalWidth": 3.2, "petalLength": 5.1, "petalWidth": 2.0, "species": "virginica"}, 113 | {"sepalLength": 6.4, "sepalWidth": 2.7, "petalLength": 5.3, "petalWidth": 1.9, "species": "virginica"}, 114 | {"sepalLength": 6.8, "sepalWidth": 3.0, "petalLength": 5.5, "petalWidth": 2.1, "species": "virginica"}, 115 | {"sepalLength": 5.7, "sepalWidth": 2.5, "petalLength": 5.0, "petalWidth": 2.0, "species": "virginica"}, 116 | {"sepalLength": 5.8, "sepalWidth": 2.8, "petalLength": 5.1, "petalWidth": 2.4, "species": "virginica"}, 117 | {"sepalLength": 6.4, "sepalWidth": 3.2, "petalLength": 5.3, "petalWidth": 2.3, "species": "virginica"}, 118 | {"sepalLength": 6.5, "sepalWidth": 3.0, "petalLength": 5.5, "petalWidth": 1.8, "species": "virginica"}, 119 | {"sepalLength": 7.7, "sepalWidth": 3.8, "petalLength": 6.7, "petalWidth": 2.2, "species": "virginica"}, 120 | {"sepalLength": 7.7, "sepalWidth": 2.6, "petalLength": 6.9, "petalWidth": 2.3, "species": "virginica"}, 121 | {"sepalLength": 6.0, "sepalWidth": 2.2, "petalLength": 5.0, "petalWidth": 1.5, "species": "virginica"}, 122 | {"sepalLength": 6.9, "sepalWidth": 3.2, "petalLength": 5.7, "petalWidth": 2.3, "species": "virginica"}, 123 | {"sepalLength": 5.6, "sepalWidth": 2.8, "petalLength": 4.9, "petalWidth": 2.0, "species": "virginica"}, 124 | {"sepalLength": 7.7, "sepalWidth": 2.8, "petalLength": 6.7, "petalWidth": 2.0, "species": "virginica"}, 125 | {"sepalLength": 6.3, "sepalWidth": 2.7, "petalLength": 4.9, "petalWidth": 1.8, "species": "virginica"}, 126 | {"sepalLength": 6.7, "sepalWidth": 3.3, "petalLength": 5.7, "petalWidth": 2.1, "species": "virginica"}, 127 | {"sepalLength": 7.2, "sepalWidth": 3.2, "petalLength": 6.0, "petalWidth": 1.8, "species": "virginica"}, 128 | {"sepalLength": 6.2, "sepalWidth": 2.8, "petalLength": 4.8, "petalWidth": 1.8, "species": "virginica"}, 129 | {"sepalLength": 6.1, "sepalWidth": 3.0, "petalLength": 4.9, "petalWidth": 1.8, "species": "virginica"}, 130 | {"sepalLength": 6.4, "sepalWidth": 2.8, "petalLength": 5.6, "petalWidth": 2.1, "species": "virginica"}, 131 | {"sepalLength": 7.2, "sepalWidth": 3.0, "petalLength": 5.8, "petalWidth": 1.6, "species": "virginica"}, 132 | {"sepalLength": 7.4, "sepalWidth": 2.8, "petalLength": 6.1, "petalWidth": 1.9, "species": "virginica"}, 133 | {"sepalLength": 7.9, "sepalWidth": 3.8, "petalLength": 6.4, "petalWidth": 2.0, "species": "virginica"}, 134 | {"sepalLength": 6.4, "sepalWidth": 2.8, "petalLength": 5.6, "petalWidth": 2.2, "species": "virginica"}, 135 | {"sepalLength": 6.3, "sepalWidth": 2.8, "petalLength": 5.1, "petalWidth": 1.5, "species": "virginica"}, 136 | {"sepalLength": 6.1, "sepalWidth": 2.6, "petalLength": 5.6, "petalWidth": 1.4, "species": "virginica"}, 137 | {"sepalLength": 7.7, "sepalWidth": 3.0, "petalLength": 6.1, "petalWidth": 2.3, "species": "virginica"}, 138 | {"sepalLength": 6.3, "sepalWidth": 3.4, "petalLength": 5.6, "petalWidth": 2.4, "species": "virginica"}, 139 | {"sepalLength": 6.4, "sepalWidth": 3.1, "petalLength": 5.5, "petalWidth": 1.8, "species": "virginica"}, 140 | {"sepalLength": 6.0, "sepalWidth": 3.0, "petalLength": 4.8, "petalWidth": 1.8, "species": "virginica"}, 141 | {"sepalLength": 6.9, "sepalWidth": 3.1, "petalLength": 5.4, "petalWidth": 2.1, "species": "virginica"}, 142 | {"sepalLength": 6.7, "sepalWidth": 3.1, "petalLength": 5.6, "petalWidth": 2.4, "species": "virginica"}, 143 | {"sepalLength": 6.9, "sepalWidth": 3.1, "petalLength": 5.1, "petalWidth": 2.3, "species": "virginica"}, 144 | {"sepalLength": 5.8, "sepalWidth": 2.7, "petalLength": 5.1, "petalWidth": 1.9, "species": "virginica"}, 145 | {"sepalLength": 6.8, "sepalWidth": 3.2, "petalLength": 5.9, "petalWidth": 2.3, "species": "virginica"}, 146 | {"sepalLength": 6.7, "sepalWidth": 3.3, "petalLength": 5.7, "petalWidth": 2.5, "species": "virginica"}, 147 | {"sepalLength": 6.7, "sepalWidth": 3.0, "petalLength": 5.2, "petalWidth": 2.3, "species": "virginica"}, 148 | {"sepalLength": 6.3, "sepalWidth": 2.5, "petalLength": 5.0, "petalWidth": 1.9, "species": "virginica"}, 149 | {"sepalLength": 6.5, "sepalWidth": 3.0, "petalLength": 5.2, "petalWidth": 2.0, "species": "virginica"}, 150 | {"sepalLength": 6.2, "sepalWidth": 3.4, "petalLength": 5.4, "petalWidth": 2.3, "species": "virginica"}, 151 | {"sepalLength": 5.9, "sepalWidth": 3.0, "petalLength": 5.1, "petalWidth": 1.8, "species": "virginica"} 152 | ] -------------------------------------------------------------------------------- /priv/datasets/la-riots.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,age,gender,race,death_date,address,neighborhood,type,longitude,latitude 2 | Cesar A.,Aguilar,18,Male,Latino,1992-04-30,2009 W. 6th St.,Westlake,Officer-involved shooting,-118.2739756,34.0592814 3 | George,Alvarez,42,Male,Latino,1992-05-01,Main & College streets,Chinatown,Not riot-related,-118.2340982,34.0626901 4 | Wilson,Alvarez,40,Male,Latino,1992-05-23,3100 Rosecrans Ave.,Hawthorne,Homicide,-118.326816,33.901662 5 | Brian E.,Andrew,30,Male,Black,1992-04-30,Rosecrans & Chester avenues,Compton,Officer-involved shooting,-118.2153903,33.9034569 6 | Vivian,Austin,87,Female,Black,1992-05-03,1600 W. 60th St.,Harvard Park,Death,-118.304741,33.985667 7 | Franklin,Benavidez,27,Male,Latino,1992-04-30,4404 S. Western Ave.,Vermont Square,Officer-involved shooting,-118.3088215,34.0034731 8 | Carol,Benson,42,Female,Black,1992-05-02,Harbor Freeway near Slauson Avenue,South Park,Death,-118.2805037,33.98916756 9 | Patrick,Bettan,30,Male,White,1992-04-30,2740 W. Olympic Blvd.,Koreatown,Homicide,-118.293181,34.052068 10 | Hector,Castro,49,Male,Latino,1992-04-30,Vermont & Leeward avenues,Koreatown,Homicide,-118.291654,34.0587022 11 | Jerel L.,Channell,26,Male,Black,1992-04-30,Santa Monica Boulevard & Seward Street,Hollywood,Death,-118.3323783,34.09129756 12 | Gregory,Davis Jr.,15,Male,Black,1992-04-30,Vermont Avenue & 43rd Street,Vermont Square,Homicide,-118.2915492,34.005485 13 | John,Doe #80,,Male,White,1992-05-02,5800 block of South Vermont Avenue,Vermont-Slauson,Homicide,-118.2914954,33.98939885 14 | Harry,Doller,56,Male,White,1992-05-01,3500 block of Winslow Drive,Silver Lake,Not riot-related,-118.278763,34.08778849 15 | Kevin J.,Edwards,35,Male,Black,1992-04-30,614 S. Locust Ave.,Compton,Not riot-related,-118.2002522,33.892421 16 | Howard,Epstein,45,Male,White,1992-04-30,Slauson & 7th avenues,Hyde Park,Homicide,-118.3247424,33.9890486 17 | Juana,Espinosa,65,Female,Latino,1992-05-02,7608 S. Compton Ave.,Compton,Homicide,-118.2461881,33.9198205 18 | Kevin A.,Evanahen,24,Male,White,1992-05-01,Braddock Drive & Inglewood Boulevard,Del Rey,Homicide,-118.4144533,33.99267241 19 | Jose L.,Garcia,15,Male,Latino,1992-04-30,1005 S. Fresno St.,Boyle Heights,Not riot-related,-118.2070419,34.0275527 20 | Mark,Garcia,15,Male,Latino,1992-04-30,10700 block of Burin Avenue,Lennox,Officer-involved shooting,-118.3537656,33.93895407 21 | Elias,Garcia Rivera,32,Male,Latino,1992-12-16,12834 Vanowen St.,Valley Glen,Homicide,-118.4137912,34.1939342 22 | Andreas,Garnica,36,Male,Latino,1992-04-30,2034 W. Pico Blvd.,Pico-Union,Not riot-related,-118.2818793,34.0468443 23 | Meeker,Gibson,35,Male,Black,1992-05-01,Holt & Loranne avenues,Pomona,Homicide,-117.7306469,34.0628458 24 | Matthew D.,Haines,32,Male,White,1992-04-30,Lemon Avenue & Pacific Coast Highway,Long Beach,Homicide,-118.1785114,33.7898575 25 | Jimmie,Harris,38,Male,Black,1992-04-29,Avalon Boulevard & Slauson Avenue,South Park,Death,-118.2651995,33.989245 26 | DeAndre,Harrison,17,Male,Black,1992-04-30,Central Avenue & 112th Street,Green Meadows,Officer-involved shooting,-118.2542949,33.9294721 27 | Paul D.,Horace,38,Male,Black,1992-05-01,1439 E. Walnut,Central-Alameda,Homicide,-118.2474139,34.0217355 28 | Betty,Jackson,56,Female,Black,1992-05-01,Main & 51st streets,South Park,Death,-118.2739305,33.9965216 29 | Dennis Ray,Jackson,38,Male,Black,1992-04-30,11322 Alvaro St.,Watts,Officer-involved shooting,-118.2537567,33.93229185 30 | Tranh,Lam,25,Male,Asian,1992-04-30,Willowbrook Avenue & Alondra Boulevard,Compton,Homicide,-118.2238673,33.8885943 31 | Edward Song,Lee,18,Male,Asian,1992-04-30,Hobart Boulevard & 3rd Street,Koreatown,Homicide,-118.3054392,34.0689851 32 | Frank D.,Lopez,36,Male,Latino,1992-04-30,16th Street & Central Avenue,Downtown,Homicide,-118.2487649,34.0264271 33 | Darnell R.,Mallory,18,Male,Black,1992-04-30,Santa Monica Boulevard & Seward Street,Hollywood,Death,-118.3341384,34.09097156 34 | Lucie R.,Maronian,51,Female,White,1992-05-01,1800 block of East New York Drive,Altadena,Homicide,-118.1134357,34.1785051 35 | Howard Eugene,Martin,22,Male,Black,1992-05-03,near North Los Robles Avenue & Claremont Street,Pasadena,Officer-involved shooting,-118.141613,34.1668637 36 | Ira F.,McCurry,45,Male,White,1992-04-30,Avalon Boulevard & 102nd Street,Green Meadows,Homicide,-118.265163,33.9437558 37 | Alfred V.,Miller,32,Male,Black,1992-05-01,Florence Avenue & Cimarron Street,Chesterfield Square,Homicide,-118.3157372,33.9745911 38 | Arturo C.,Miranda,23,Male,Latino,1992-04-29,120th Street & Central Avenue,Green Meadows,Homicide,-118.2543429,33.9237304 39 | Suzanne R.,Morgan,24,Female,Black,1992-05-01,2137 E. 115th St.,Watts,Not riot-related,-118.2344108,33.9304917 40 | Nissar,Mustafa,20,Male,White,1992-08-12,1601 S. Western Ave.,Harvard Heights,Homicide,-118.3090341,34.0435539 41 | Ernest,Neal Jr.,27,Male,Black,1992-04-30,Western Avenue & 92nd Street,Gramercy Park,Homicide,-118.309006,33.952709 42 | Anthony,Netherly,21,Male,Black,1992-04-30,San Pedro & 78th streets,Florence,Homicide,-118.2695156,33.9687806 43 | Charles W.,Orebo,21,Male,Black,1992-05-01,Florence Avenue & Flower Street,Florence,Officer-involved shooting,-118.2812901,33.9746575 44 | Juanita,Pettaway,37,Female,Black,1992-04-30,Santa Monica Boulevard & Seward Street,Hollywood,Death,-118.3331771,34.090696 45 | Juan A.,Pineda,20,Male,Latino,1992-04-30,4028 Santa Monica Blvd.,Silver Lake,Homicide,-118.281326,34.092221 46 | Hugo G.,Ramirez,23,Male,Latino,1992-05-03,12732 Bess St.,Baldwin Park,Not riot-related,-117.997106,34.070238 47 | Aaron,Ratinoff,68,Male,White,1992-05-01,11690 Gateway Blvd.,Sawtelle,Homicide,-118.4431,34.0286551 48 | Victor R.,Rivas,26,Male,Latino,1992-05-03,Pico Boulevard & Vermont Avenue,Pico-Union,Officer-involved shooting,-118.291583,34.0472563 49 | William,Ross,33,Male,White,1992-05-01,2882 W. 9th St.,Koreatown,Homicide,-118.291274,34.05569 50 | Juan V.,Salgado,20,Male,Latino,1992-05-20,3100 block of South Main Street,Historic South-Central,Homicide,-118.2713789,34.02062153 51 | Imad,Sharaf,31,Male,Black,1992-05-03,San Diego Freeway & San Fernando Mission Boulevard,Mission Hills,Not riot-related,-118.4717452,34.27185555 52 | Jose,Solorzano,25,Male,Latino,1992-05-01,Vermont Avenue & Santa Monica Boulevard,East Hollywood,Homicide,-118.291755,34.0908675 53 | George A.,Sosa,20,Male,Latino,1992-04-30,2600 block of Florence Avenue,Huntington Park,Homicide,-118.22518059,33.97418 54 | Anthony J.,Taylor,31,Male,Black,1992-04-30,11322 Alvaro St.,Watts,Officer-involved shooting,-118.2531966,33.9314634 55 | Dwight,Taylor,42,Male,Black,1992-04-29,4365 S. Vermont Ave.,Vermont Square,Homicide,-118.292169,34.004453 56 | James L.,Taylor,26,Male,Black,1992-04-30,5213 Sunset Blvd.,East Hollywood,Homicide,-118.3037557,34.0982485 57 | Wallace,Tope,54,Male,White,1993-11-24,5510 W. Sunset Blvd.,Hollywood,Homicide,-118.3098224,34.0980819 58 | Edward Anthony,Travens,15,Male,White,1992-04-29,San Fernando Road & San Fernando Mission Boulevard,San Fernando,Not riot-related,-118.4430027,34.28418731 59 | Eduardo C.,Vela,33,Male,Latino,1992-04-29,5100 block of West Slauson Avenue,Ladera Heights,Homicide,-118.3687199,33.9876036 60 | Fredrick,Ward,20,Male,Black,1992-05-02,11932 Cometa Ave.,Pacoima,Homicide,-118.412778,34.287098 61 | Louis A.,Watson,18,Male,Black,1992-04-29,4365 S. Vermont Ave.,Vermont Square,Homicide,-118.2915566,34.00524354 62 | Elbert O.,Wilkins,33,Male,Black,1992-04-30,Western Avenue & 92nd Street,Gramercy Park,Homicide,-118.3100043,33.95276731 63 | John H.,Willers,37,Male,White,1992-04-29,10621 Sepulveda Blvd.,Mission Hills,Homicide,-118.46777,34.263184 64 | Willie Bernard,Williams,29,Male,Black,1992-04-29,Gage & Western avenues,Chesterfield Square,Death,-118.3089517,33.9823625 65 | -------------------------------------------------------------------------------- /priv/datasets/ohlc.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "date": "2009-06-01", "open": 28.7, "high": 30.05, "low": 28.45, "close": 30.04, "signal": "short", "ret": -4.89396411092985 }, 3 | { "date": "2009-06-02", "open": 30.04, "high": 30.13, "low": 28.3, "close": 29.63, "signal": "short", "ret": -0.322580645161295 }, 4 | { "date": "2009-06-03", "open": 29.62, "high": 31.79, "low": 29.62, "close": 31.02, "signal": "short", "ret": 3.68663594470045 }, 5 | { "date": "2009-06-04", "open": 31.02, "high": 31.02, "low": 29.92, "close": 30.18, "signal": "short", "ret": 4.51010886469673 }, 6 | { "date": "2009-06-05", "open": 29.39, "high": 30.81, "low": 28.85, "close": 29.62, "signal": "short", "ret": 6.08424336973478 }, 7 | { "date": "2009-06-08", "open": 30.84, "high": 31.82, "low": 26.41, "close": 29.77, "signal": "short", "ret": 1.2539184952978 }, 8 | { "date": "2009-06-09", "open": 29.77, "high": 29.77, "low": 27.79, "close": 28.27, "signal": "short", "ret": -5.02431118314424 }, 9 | { "date": "2009-06-10", "open": 26.9, "high": 29.74, "low": 26.9, "close": 28.46, "signal": "short", "ret": -5.46623794212217 }, 10 | { "date": "2009-06-11", "open": 27.36, "high": 28.11, "low": 26.81, "close": 28.11, "signal": "short", "ret": -8.3743842364532 }, 11 | { "date": "2009-06-12", "open": 28.08, "high": 28.5, "low": 27.73, "close": 28.15, "signal": "short", "ret": -5.52763819095477 }, 12 | { "date": "2009-06-15", "open": 29.7, "high": 31.09, "low": 29.64, "close": 30.81, "signal": "long", "ret": 3.4920634920635 }, 13 | { "date": "2009-06-16", "open": 30.81, "high": 32.75, "low": 30.07, "close": 32.68, "signal": "short", "ret": 0.155038759689914 }, 14 | { "date": "2009-06-17", "open": 31.19, "high": 32.77, "low": 30.64, "close": 31.54, "signal": "short", "ret": 5.82822085889571 }, 15 | { "date": "2009-06-18", "open": 31.54, "high": 31.54, "low": 29.6, "close": 30.03, "signal": "short", "ret": 8.17610062893082 }, 16 | { "date": "2009-06-19", "open": 29.16, "high": 29.32, "low": 27.56, "close": 27.99, "signal": "short", "ret": 8.59872611464968 }, 17 | { "date": "2009-06-22", "open": 30.4, "high": 32.05, "low": 30.3, "close": 31.17, "signal": "short", "ret": 15.4907975460123 }, 18 | { "date": "2009-06-23", "open": 31.3, "high": 31.54, "low": 27.83, "close": 30.58, "signal": "short", "ret": 11.7370892018779 }, 19 | { "date": "2009-06-24", "open": 30.58, "high": 30.58, "low": 28.79, "close": 29.05, "signal": "long", "ret": -10.4234527687296 }, 20 | { "date": "2009-06-25", "open": 29.45, "high": 29.56, "low": 26.3, "close": 26.36, "signal": "long", "ret": 0 }, 21 | { "date": "2009-06-26", "open": 27.09, "high": 27.22, "low": 25.76, "close": 25.93, "signal": "long", "ret": 0 }, 22 | { "date": "2009-06-29", "open": 25.93, "high": 27.18, "low": 25.29, "close": 25.35, "signal": "long", "ret": 5.26315789473684 }, 23 | { "date": "2009-06-30", "open": 25.36, "high": 27.38, "low": 25.02, "close": 26.35, "signal": "long", "ret": 6.73758865248228 }, 24 | { "date": "2009-07-01", "open": 25.73, "high": 26.31, "low": 24.8, "close": 26.22, "signal": "long", "ret": 7.83645655877341 }, 25 | { "date": "2009-07-02", "open": 26.22, "high": 28.62, "low": 26.22, "close": 27.95, "signal": "long", "ret": 2.76422764227643 }, 26 | { "date": "2009-07-06", "open": 30.32, "high": 30.6, "low": 28.99, "close": 29, "signal": "short", "ret": -2.14521452145214 }, 27 | { "date": "2009-07-07", "open": 29, "high": 30.94, "low": 28.9, "close": 30.85, "signal": "short", "ret": 3.03514376996805 }, 28 | { "date": "2009-07-08", "open": 30.85, "high": 33.05, "low": 30.43, "close": 31.3, "signal": "short", "ret": 5.68720379146919 }, 29 | { "date": "2009-07-09", "open": 30.23, "high": 30.49, "low": 29.28, "close": 29.78, "signal": "short", "ret": 8.22784810126583 }, 30 | { "date": "2009-07-10", "open": 29.78, "high": 30.34, "low": 28.82, "close": 29.02, "signal": "short", "ret": 8.64779874213836 }, 31 | { "date": "2009-07-13", "open": 28.36, "high": 29.24, "low": 25.42, "close": 26.31, "signal": "short", "ret": 7.32899022801303 }, 32 | { "date": "2009-07-14", "open": 26.31, "high": 26.84, "low": 24.99, "close": 25.02, "signal": "short", "ret": 7.30897009966778 }, 33 | { "date": "2009-07-15", "open": 25.05, "high": 26.06, "low": 23.83, "close": 25.89, "signal": "neutral", "ret": 0 }, 34 | { "date": "2009-07-16", "open": 25.96, "high": 26.18, "low": 24.51, "close": 25.42, "signal": "long", "ret": -9.82758620689656 }, 35 | { "date": "2009-07-17", "open": 25.42, "high": 25.55, "low": 23.88, "close": 24.34, "signal": "long", "ret": -10.8433734939759 }, 36 | { "date": "2009-07-20", "open": 25.06, "high": 25.42, "low": 24.26, "close": 24.4, "signal": "long", "ret": -7.55711775043936 }, 37 | { "date": "2009-07-21", "open": 24.28, "high": 25.14, "low": 23.81, "close": 23.87, "signal": "long", "ret": -2.5089605734767 }, 38 | { "date": "2009-07-22", "open": 24.05, "high": 24.14, "low": 23.24, "close": 23.47, "signal": "long", "ret": 0.915750915750916 }, 39 | { "date": "2009-07-23", "open": 23.71, "high": 24.05, "low": 23.21, "close": 23.43, "signal": "long", "ret": 2.47148288973383 }, 40 | { "date": "2009-07-24", "open": 23.87, "high": 23.87, "low": 23, "close": 23.09, "signal": "long", "ret": 4.22264875239922 }, 41 | { "date": "2009-07-27", "open": 24.06, "high": 24.86, "low": 24.02, "close": 24.28, "signal": "long", "ret": -0.189393939393929 }, 42 | { "date": "2009-07-28", "open": 24.28, "high": 25.61, "low": 24.28, "close": 25.01, "signal": "long", "ret": -4.37956204379562 }, 43 | { "date": "2009-07-29", "open": 25.47, "high": 26.18, "low": 25.41, "close": 25.61, "signal": "long", "ret": -4.48504983388705 }, 44 | { "date": "2009-07-30", "open": 25.4, "high": 25.76, "low": 24.85, "close": 25.4, "signal": "long", "ret": -1.70357751277683 }, 45 | { "date": "2009-07-31", "open": 25.4, "high": 26.22, "low": 24.93, "close": 25.92, "signal": "short", "ret": 5.06756756756757 } 46 | ] 47 | -------------------------------------------------------------------------------- /priv/datasets/stocks.csv: -------------------------------------------------------------------------------- 1 | symbol,date,price 2 | MSFT,Jan 1 2000,39.81 3 | MSFT,Feb 1 2000,36.35 4 | MSFT,Mar 1 2000,43.22 5 | MSFT,Apr 1 2000,28.37 6 | MSFT,May 1 2000,25.45 7 | MSFT,Jun 1 2000,32.54 8 | MSFT,Jul 1 2000,28.4 9 | MSFT,Aug 1 2000,28.4 10 | MSFT,Sep 1 2000,24.53 11 | MSFT,Oct 1 2000,28.02 12 | MSFT,Nov 1 2000,23.34 13 | MSFT,Dec 1 2000,17.65 14 | MSFT,Jan 1 2001,24.84 15 | MSFT,Feb 1 2001,24 16 | MSFT,Mar 1 2001,22.25 17 | MSFT,Apr 1 2001,27.56 18 | MSFT,May 1 2001,28.14 19 | MSFT,Jun 1 2001,29.7 20 | MSFT,Jul 1 2001,26.93 21 | MSFT,Aug 1 2001,23.21 22 | MSFT,Sep 1 2001,20.82 23 | MSFT,Oct 1 2001,23.65 24 | MSFT,Nov 1 2001,26.12 25 | MSFT,Dec 1 2001,26.95 26 | MSFT,Jan 1 2002,25.92 27 | MSFT,Feb 1 2002,23.73 28 | MSFT,Mar 1 2002,24.53 29 | MSFT,Apr 1 2002,21.26 30 | MSFT,May 1 2002,20.71 31 | MSFT,Jun 1 2002,22.25 32 | MSFT,Jul 1 2002,19.52 33 | MSFT,Aug 1 2002,19.97 34 | MSFT,Sep 1 2002,17.79 35 | MSFT,Oct 1 2002,21.75 36 | MSFT,Nov 1 2002,23.46 37 | MSFT,Dec 1 2002,21.03 38 | MSFT,Jan 1 2003,19.31 39 | MSFT,Feb 1 2003,19.34 40 | MSFT,Mar 1 2003,19.76 41 | MSFT,Apr 1 2003,20.87 42 | MSFT,May 1 2003,20.09 43 | MSFT,Jun 1 2003,20.93 44 | MSFT,Jul 1 2003,21.56 45 | MSFT,Aug 1 2003,21.65 46 | MSFT,Sep 1 2003,22.69 47 | MSFT,Oct 1 2003,21.45 48 | MSFT,Nov 1 2003,21.1 49 | MSFT,Dec 1 2003,22.46 50 | MSFT,Jan 1 2004,22.69 51 | MSFT,Feb 1 2004,21.77 52 | MSFT,Mar 1 2004,20.46 53 | MSFT,Apr 1 2004,21.45 54 | MSFT,May 1 2004,21.53 55 | MSFT,Jun 1 2004,23.44 56 | MSFT,Jul 1 2004,23.38 57 | MSFT,Aug 1 2004,22.47 58 | MSFT,Sep 1 2004,22.76 59 | MSFT,Oct 1 2004,23.02 60 | MSFT,Nov 1 2004,24.6 61 | MSFT,Dec 1 2004,24.52 62 | MSFT,Jan 1 2005,24.11 63 | MSFT,Feb 1 2005,23.15 64 | MSFT,Mar 1 2005,22.24 65 | MSFT,Apr 1 2005,23.28 66 | MSFT,May 1 2005,23.82 67 | MSFT,Jun 1 2005,22.93 68 | MSFT,Jul 1 2005,23.64 69 | MSFT,Aug 1 2005,25.35 70 | MSFT,Sep 1 2005,23.83 71 | MSFT,Oct 1 2005,23.8 72 | MSFT,Nov 1 2005,25.71 73 | MSFT,Dec 1 2005,24.29 74 | MSFT,Jan 1 2006,26.14 75 | MSFT,Feb 1 2006,25.04 76 | MSFT,Mar 1 2006,25.36 77 | MSFT,Apr 1 2006,22.5 78 | MSFT,May 1 2006,21.19 79 | MSFT,Jun 1 2006,21.8 80 | MSFT,Jul 1 2006,22.51 81 | MSFT,Aug 1 2006,24.13 82 | MSFT,Sep 1 2006,25.68 83 | MSFT,Oct 1 2006,26.96 84 | MSFT,Nov 1 2006,27.66 85 | MSFT,Dec 1 2006,28.13 86 | MSFT,Jan 1 2007,29.07 87 | MSFT,Feb 1 2007,26.63 88 | MSFT,Mar 1 2007,26.35 89 | MSFT,Apr 1 2007,28.3 90 | MSFT,May 1 2007,29.11 91 | MSFT,Jun 1 2007,27.95 92 | MSFT,Jul 1 2007,27.5 93 | MSFT,Aug 1 2007,27.34 94 | MSFT,Sep 1 2007,28.04 95 | MSFT,Oct 1 2007,35.03 96 | MSFT,Nov 1 2007,32.09 97 | MSFT,Dec 1 2007,34 98 | MSFT,Jan 1 2008,31.13 99 | MSFT,Feb 1 2008,26.07 100 | MSFT,Mar 1 2008,27.21 101 | MSFT,Apr 1 2008,27.34 102 | MSFT,May 1 2008,27.25 103 | MSFT,Jun 1 2008,26.47 104 | MSFT,Jul 1 2008,24.75 105 | MSFT,Aug 1 2008,26.36 106 | MSFT,Sep 1 2008,25.78 107 | MSFT,Oct 1 2008,21.57 108 | MSFT,Nov 1 2008,19.66 109 | MSFT,Dec 1 2008,18.91 110 | MSFT,Jan 1 2009,16.63 111 | MSFT,Feb 1 2009,15.81 112 | MSFT,Mar 1 2009,17.99 113 | MSFT,Apr 1 2009,19.84 114 | MSFT,May 1 2009,20.59 115 | MSFT,Jun 1 2009,23.42 116 | MSFT,Jul 1 2009,23.18 117 | MSFT,Aug 1 2009,24.43 118 | MSFT,Sep 1 2009,25.49 119 | MSFT,Oct 1 2009,27.48 120 | MSFT,Nov 1 2009,29.27 121 | MSFT,Dec 1 2009,30.34 122 | MSFT,Jan 1 2010,28.05 123 | MSFT,Feb 1 2010,28.67 124 | MSFT,Mar 1 2010,28.8 125 | AMZN,Jan 1 2000,64.56 126 | AMZN,Feb 1 2000,68.87 127 | AMZN,Mar 1 2000,67 128 | AMZN,Apr 1 2000,55.19 129 | AMZN,May 1 2000,48.31 130 | AMZN,Jun 1 2000,36.31 131 | AMZN,Jul 1 2000,30.12 132 | AMZN,Aug 1 2000,41.5 133 | AMZN,Sep 1 2000,38.44 134 | AMZN,Oct 1 2000,36.62 135 | AMZN,Nov 1 2000,24.69 136 | AMZN,Dec 1 2000,15.56 137 | AMZN,Jan 1 2001,17.31 138 | AMZN,Feb 1 2001,10.19 139 | AMZN,Mar 1 2001,10.23 140 | AMZN,Apr 1 2001,15.78 141 | AMZN,May 1 2001,16.69 142 | AMZN,Jun 1 2001,14.15 143 | AMZN,Jul 1 2001,12.49 144 | AMZN,Aug 1 2001,8.94 145 | AMZN,Sep 1 2001,5.97 146 | AMZN,Oct 1 2001,6.98 147 | AMZN,Nov 1 2001,11.32 148 | AMZN,Dec 1 2001,10.82 149 | AMZN,Jan 1 2002,14.19 150 | AMZN,Feb 1 2002,14.1 151 | AMZN,Mar 1 2002,14.3 152 | AMZN,Apr 1 2002,16.69 153 | AMZN,May 1 2002,18.23 154 | AMZN,Jun 1 2002,16.25 155 | AMZN,Jul 1 2002,14.45 156 | AMZN,Aug 1 2002,14.94 157 | AMZN,Sep 1 2002,15.93 158 | AMZN,Oct 1 2002,19.36 159 | AMZN,Nov 1 2002,23.35 160 | AMZN,Dec 1 2002,18.89 161 | AMZN,Jan 1 2003,21.85 162 | AMZN,Feb 1 2003,22.01 163 | AMZN,Mar 1 2003,26.03 164 | AMZN,Apr 1 2003,28.69 165 | AMZN,May 1 2003,35.89 166 | AMZN,Jun 1 2003,36.32 167 | AMZN,Jul 1 2003,41.64 168 | AMZN,Aug 1 2003,46.32 169 | AMZN,Sep 1 2003,48.43 170 | AMZN,Oct 1 2003,54.43 171 | AMZN,Nov 1 2003,53.97 172 | AMZN,Dec 1 2003,52.62 173 | AMZN,Jan 1 2004,50.4 174 | AMZN,Feb 1 2004,43.01 175 | AMZN,Mar 1 2004,43.28 176 | AMZN,Apr 1 2004,43.6 177 | AMZN,May 1 2004,48.5 178 | AMZN,Jun 1 2004,54.4 179 | AMZN,Jul 1 2004,38.92 180 | AMZN,Aug 1 2004,38.14 181 | AMZN,Sep 1 2004,40.86 182 | AMZN,Oct 1 2004,34.13 183 | AMZN,Nov 1 2004,39.68 184 | AMZN,Dec 1 2004,44.29 185 | AMZN,Jan 1 2005,43.22 186 | AMZN,Feb 1 2005,35.18 187 | AMZN,Mar 1 2005,34.27 188 | AMZN,Apr 1 2005,32.36 189 | AMZN,May 1 2005,35.51 190 | AMZN,Jun 1 2005,33.09 191 | AMZN,Jul 1 2005,45.15 192 | AMZN,Aug 1 2005,42.7 193 | AMZN,Sep 1 2005,45.3 194 | AMZN,Oct 1 2005,39.86 195 | AMZN,Nov 1 2005,48.46 196 | AMZN,Dec 1 2005,47.15 197 | AMZN,Jan 1 2006,44.82 198 | AMZN,Feb 1 2006,37.44 199 | AMZN,Mar 1 2006,36.53 200 | AMZN,Apr 1 2006,35.21 201 | AMZN,May 1 2006,34.61 202 | AMZN,Jun 1 2006,38.68 203 | AMZN,Jul 1 2006,26.89 204 | AMZN,Aug 1 2006,30.83 205 | AMZN,Sep 1 2006,32.12 206 | AMZN,Oct 1 2006,38.09 207 | AMZN,Nov 1 2006,40.34 208 | AMZN,Dec 1 2006,39.46 209 | AMZN,Jan 1 2007,37.67 210 | AMZN,Feb 1 2007,39.14 211 | AMZN,Mar 1 2007,39.79 212 | AMZN,Apr 1 2007,61.33 213 | AMZN,May 1 2007,69.14 214 | AMZN,Jun 1 2007,68.41 215 | AMZN,Jul 1 2007,78.54 216 | AMZN,Aug 1 2007,79.91 217 | AMZN,Sep 1 2007,93.15 218 | AMZN,Oct 1 2007,89.15 219 | AMZN,Nov 1 2007,90.56 220 | AMZN,Dec 1 2007,92.64 221 | AMZN,Jan 1 2008,77.7 222 | AMZN,Feb 1 2008,64.47 223 | AMZN,Mar 1 2008,71.3 224 | AMZN,Apr 1 2008,78.63 225 | AMZN,May 1 2008,81.62 226 | AMZN,Jun 1 2008,73.33 227 | AMZN,Jul 1 2008,76.34 228 | AMZN,Aug 1 2008,80.81 229 | AMZN,Sep 1 2008,72.76 230 | AMZN,Oct 1 2008,57.24 231 | AMZN,Nov 1 2008,42.7 232 | AMZN,Dec 1 2008,51.28 233 | AMZN,Jan 1 2009,58.82 234 | AMZN,Feb 1 2009,64.79 235 | AMZN,Mar 1 2009,73.44 236 | AMZN,Apr 1 2009,80.52 237 | AMZN,May 1 2009,77.99 238 | AMZN,Jun 1 2009,83.66 239 | AMZN,Jul 1 2009,85.76 240 | AMZN,Aug 1 2009,81.19 241 | AMZN,Sep 1 2009,93.36 242 | AMZN,Oct 1 2009,118.81 243 | AMZN,Nov 1 2009,135.91 244 | AMZN,Dec 1 2009,134.52 245 | AMZN,Jan 1 2010,125.41 246 | AMZN,Feb 1 2010,118.4 247 | AMZN,Mar 1 2010,128.82 248 | IBM,Jan 1 2000,100.52 249 | IBM,Feb 1 2000,92.11 250 | IBM,Mar 1 2000,106.11 251 | IBM,Apr 1 2000,99.95 252 | IBM,May 1 2000,96.31 253 | IBM,Jun 1 2000,98.33 254 | IBM,Jul 1 2000,100.74 255 | IBM,Aug 1 2000,118.62 256 | IBM,Sep 1 2000,101.19 257 | IBM,Oct 1 2000,88.5 258 | IBM,Nov 1 2000,84.12 259 | IBM,Dec 1 2000,76.47 260 | IBM,Jan 1 2001,100.76 261 | IBM,Feb 1 2001,89.98 262 | IBM,Mar 1 2001,86.63 263 | IBM,Apr 1 2001,103.7 264 | IBM,May 1 2001,100.82 265 | IBM,Jun 1 2001,102.35 266 | IBM,Jul 1 2001,94.87 267 | IBM,Aug 1 2001,90.25 268 | IBM,Sep 1 2001,82.82 269 | IBM,Oct 1 2001,97.58 270 | IBM,Nov 1 2001,104.5 271 | IBM,Dec 1 2001,109.36 272 | IBM,Jan 1 2002,97.54 273 | IBM,Feb 1 2002,88.82 274 | IBM,Mar 1 2002,94.15 275 | IBM,Apr 1 2002,75.82 276 | IBM,May 1 2002,72.97 277 | IBM,Jun 1 2002,65.31 278 | IBM,Jul 1 2002,63.86 279 | IBM,Aug 1 2002,68.52 280 | IBM,Sep 1 2002,53.01 281 | IBM,Oct 1 2002,71.76 282 | IBM,Nov 1 2002,79.16 283 | IBM,Dec 1 2002,70.58 284 | IBM,Jan 1 2003,71.22 285 | IBM,Feb 1 2003,71.13 286 | IBM,Mar 1 2003,71.57 287 | IBM,Apr 1 2003,77.47 288 | IBM,May 1 2003,80.48 289 | IBM,Jun 1 2003,75.42 290 | IBM,Jul 1 2003,74.28 291 | IBM,Aug 1 2003,75.12 292 | IBM,Sep 1 2003,80.91 293 | IBM,Oct 1 2003,81.96 294 | IBM,Nov 1 2003,83.08 295 | IBM,Dec 1 2003,85.05 296 | IBM,Jan 1 2004,91.06 297 | IBM,Feb 1 2004,88.7 298 | IBM,Mar 1 2004,84.41 299 | IBM,Apr 1 2004,81.04 300 | IBM,May 1 2004,81.59 301 | IBM,Jun 1 2004,81.19 302 | IBM,Jul 1 2004,80.19 303 | IBM,Aug 1 2004,78.17 304 | IBM,Sep 1 2004,79.13 305 | IBM,Oct 1 2004,82.84 306 | IBM,Nov 1 2004,87.15 307 | IBM,Dec 1 2004,91.16 308 | IBM,Jan 1 2005,86.39 309 | IBM,Feb 1 2005,85.78 310 | IBM,Mar 1 2005,84.66 311 | IBM,Apr 1 2005,70.77 312 | IBM,May 1 2005,70.18 313 | IBM,Jun 1 2005,68.93 314 | IBM,Jul 1 2005,77.53 315 | IBM,Aug 1 2005,75.07 316 | IBM,Sep 1 2005,74.7 317 | IBM,Oct 1 2005,76.25 318 | IBM,Nov 1 2005,82.98 319 | IBM,Dec 1 2005,76.73 320 | IBM,Jan 1 2006,75.89 321 | IBM,Feb 1 2006,75.09 322 | IBM,Mar 1 2006,77.17 323 | IBM,Apr 1 2006,77.05 324 | IBM,May 1 2006,75.04 325 | IBM,Jun 1 2006,72.15 326 | IBM,Jul 1 2006,72.7 327 | IBM,Aug 1 2006,76.35 328 | IBM,Sep 1 2006,77.26 329 | IBM,Oct 1 2006,87.06 330 | IBM,Nov 1 2006,86.95 331 | IBM,Dec 1 2006,91.9 332 | IBM,Jan 1 2007,93.79 333 | IBM,Feb 1 2007,88.18 334 | IBM,Mar 1 2007,89.44 335 | IBM,Apr 1 2007,96.98 336 | IBM,May 1 2007,101.54 337 | IBM,Jun 1 2007,100.25 338 | IBM,Jul 1 2007,105.4 339 | IBM,Aug 1 2007,111.54 340 | IBM,Sep 1 2007,112.6 341 | IBM,Oct 1 2007,111 342 | IBM,Nov 1 2007,100.9 343 | IBM,Dec 1 2007,103.7 344 | IBM,Jan 1 2008,102.75 345 | IBM,Feb 1 2008,109.64 346 | IBM,Mar 1 2008,110.87 347 | IBM,Apr 1 2008,116.23 348 | IBM,May 1 2008,125.14 349 | IBM,Jun 1 2008,114.6 350 | IBM,Jul 1 2008,123.74 351 | IBM,Aug 1 2008,118.16 352 | IBM,Sep 1 2008,113.53 353 | IBM,Oct 1 2008,90.24 354 | IBM,Nov 1 2008,79.65 355 | IBM,Dec 1 2008,82.15 356 | IBM,Jan 1 2009,89.46 357 | IBM,Feb 1 2009,90.32 358 | IBM,Mar 1 2009,95.09 359 | IBM,Apr 1 2009,101.29 360 | IBM,May 1 2009,104.85 361 | IBM,Jun 1 2009,103.01 362 | IBM,Jul 1 2009,116.34 363 | IBM,Aug 1 2009,117 364 | IBM,Sep 1 2009,118.55 365 | IBM,Oct 1 2009,119.54 366 | IBM,Nov 1 2009,125.79 367 | IBM,Dec 1 2009,130.32 368 | IBM,Jan 1 2010,121.85 369 | IBM,Feb 1 2010,127.16 370 | IBM,Mar 1 2010,125.55 371 | GOOG,Aug 1 2004,102.37 372 | GOOG,Sep 1 2004,129.6 373 | GOOG,Oct 1 2004,190.64 374 | GOOG,Nov 1 2004,181.98 375 | GOOG,Dec 1 2004,192.79 376 | GOOG,Jan 1 2005,195.62 377 | GOOG,Feb 1 2005,187.99 378 | GOOG,Mar 1 2005,180.51 379 | GOOG,Apr 1 2005,220 380 | GOOG,May 1 2005,277.27 381 | GOOG,Jun 1 2005,294.15 382 | GOOG,Jul 1 2005,287.76 383 | GOOG,Aug 1 2005,286 384 | GOOG,Sep 1 2005,316.46 385 | GOOG,Oct 1 2005,372.14 386 | GOOG,Nov 1 2005,404.91 387 | GOOG,Dec 1 2005,414.86 388 | GOOG,Jan 1 2006,432.66 389 | GOOG,Feb 1 2006,362.62 390 | GOOG,Mar 1 2006,390 391 | GOOG,Apr 1 2006,417.94 392 | GOOG,May 1 2006,371.82 393 | GOOG,Jun 1 2006,419.33 394 | GOOG,Jul 1 2006,386.6 395 | GOOG,Aug 1 2006,378.53 396 | GOOG,Sep 1 2006,401.9 397 | GOOG,Oct 1 2006,476.39 398 | GOOG,Nov 1 2006,484.81 399 | GOOG,Dec 1 2006,460.48 400 | GOOG,Jan 1 2007,501.5 401 | GOOG,Feb 1 2007,449.45 402 | GOOG,Mar 1 2007,458.16 403 | GOOG,Apr 1 2007,471.38 404 | GOOG,May 1 2007,497.91 405 | GOOG,Jun 1 2007,522.7 406 | GOOG,Jul 1 2007,510 407 | GOOG,Aug 1 2007,515.25 408 | GOOG,Sep 1 2007,567.27 409 | GOOG,Oct 1 2007,707 410 | GOOG,Nov 1 2007,693 411 | GOOG,Dec 1 2007,691.48 412 | GOOG,Jan 1 2008,564.3 413 | GOOG,Feb 1 2008,471.18 414 | GOOG,Mar 1 2008,440.47 415 | GOOG,Apr 1 2008,574.29 416 | GOOG,May 1 2008,585.8 417 | GOOG,Jun 1 2008,526.42 418 | GOOG,Jul 1 2008,473.75 419 | GOOG,Aug 1 2008,463.29 420 | GOOG,Sep 1 2008,400.52 421 | GOOG,Oct 1 2008,359.36 422 | GOOG,Nov 1 2008,292.96 423 | GOOG,Dec 1 2008,307.65 424 | GOOG,Jan 1 2009,338.53 425 | GOOG,Feb 1 2009,337.99 426 | GOOG,Mar 1 2009,348.06 427 | GOOG,Apr 1 2009,395.97 428 | GOOG,May 1 2009,417.23 429 | GOOG,Jun 1 2009,421.59 430 | GOOG,Jul 1 2009,443.05 431 | GOOG,Aug 1 2009,461.67 432 | GOOG,Sep 1 2009,495.85 433 | GOOG,Oct 1 2009,536.12 434 | GOOG,Nov 1 2009,583 435 | GOOG,Dec 1 2009,619.98 436 | GOOG,Jan 1 2010,529.94 437 | GOOG,Feb 1 2010,526.8 438 | GOOG,Mar 1 2010,560.19 439 | AAPL,Jan 1 2000,25.94 440 | AAPL,Feb 1 2000,28.66 441 | AAPL,Mar 1 2000,33.95 442 | AAPL,Apr 1 2000,31.01 443 | AAPL,May 1 2000,21 444 | AAPL,Jun 1 2000,26.19 445 | AAPL,Jul 1 2000,25.41 446 | AAPL,Aug 1 2000,30.47 447 | AAPL,Sep 1 2000,12.88 448 | AAPL,Oct 1 2000,9.78 449 | AAPL,Nov 1 2000,8.25 450 | AAPL,Dec 1 2000,7.44 451 | AAPL,Jan 1 2001,10.81 452 | AAPL,Feb 1 2001,9.12 453 | AAPL,Mar 1 2001,11.03 454 | AAPL,Apr 1 2001,12.74 455 | AAPL,May 1 2001,9.98 456 | AAPL,Jun 1 2001,11.62 457 | AAPL,Jul 1 2001,9.4 458 | AAPL,Aug 1 2001,9.27 459 | AAPL,Sep 1 2001,7.76 460 | AAPL,Oct 1 2001,8.78 461 | AAPL,Nov 1 2001,10.65 462 | AAPL,Dec 1 2001,10.95 463 | AAPL,Jan 1 2002,12.36 464 | AAPL,Feb 1 2002,10.85 465 | AAPL,Mar 1 2002,11.84 466 | AAPL,Apr 1 2002,12.14 467 | AAPL,May 1 2002,11.65 468 | AAPL,Jun 1 2002,8.86 469 | AAPL,Jul 1 2002,7.63 470 | AAPL,Aug 1 2002,7.38 471 | AAPL,Sep 1 2002,7.25 472 | AAPL,Oct 1 2002,8.03 473 | AAPL,Nov 1 2002,7.75 474 | AAPL,Dec 1 2002,7.16 475 | AAPL,Jan 1 2003,7.18 476 | AAPL,Feb 1 2003,7.51 477 | AAPL,Mar 1 2003,7.07 478 | AAPL,Apr 1 2003,7.11 479 | AAPL,May 1 2003,8.98 480 | AAPL,Jun 1 2003,9.53 481 | AAPL,Jul 1 2003,10.54 482 | AAPL,Aug 1 2003,11.31 483 | AAPL,Sep 1 2003,10.36 484 | AAPL,Oct 1 2003,11.44 485 | AAPL,Nov 1 2003,10.45 486 | AAPL,Dec 1 2003,10.69 487 | AAPL,Jan 1 2004,11.28 488 | AAPL,Feb 1 2004,11.96 489 | AAPL,Mar 1 2004,13.52 490 | AAPL,Apr 1 2004,12.89 491 | AAPL,May 1 2004,14.03 492 | AAPL,Jun 1 2004,16.27 493 | AAPL,Jul 1 2004,16.17 494 | AAPL,Aug 1 2004,17.25 495 | AAPL,Sep 1 2004,19.38 496 | AAPL,Oct 1 2004,26.2 497 | AAPL,Nov 1 2004,33.53 498 | AAPL,Dec 1 2004,32.2 499 | AAPL,Jan 1 2005,38.45 500 | AAPL,Feb 1 2005,44.86 501 | AAPL,Mar 1 2005,41.67 502 | AAPL,Apr 1 2005,36.06 503 | AAPL,May 1 2005,39.76 504 | AAPL,Jun 1 2005,36.81 505 | AAPL,Jul 1 2005,42.65 506 | AAPL,Aug 1 2005,46.89 507 | AAPL,Sep 1 2005,53.61 508 | AAPL,Oct 1 2005,57.59 509 | AAPL,Nov 1 2005,67.82 510 | AAPL,Dec 1 2005,71.89 511 | AAPL,Jan 1 2006,75.51 512 | AAPL,Feb 1 2006,68.49 513 | AAPL,Mar 1 2006,62.72 514 | AAPL,Apr 1 2006,70.39 515 | AAPL,May 1 2006,59.77 516 | AAPL,Jun 1 2006,57.27 517 | AAPL,Jul 1 2006,67.96 518 | AAPL,Aug 1 2006,67.85 519 | AAPL,Sep 1 2006,76.98 520 | AAPL,Oct 1 2006,81.08 521 | AAPL,Nov 1 2006,91.66 522 | AAPL,Dec 1 2006,84.84 523 | AAPL,Jan 1 2007,85.73 524 | AAPL,Feb 1 2007,84.61 525 | AAPL,Mar 1 2007,92.91 526 | AAPL,Apr 1 2007,99.8 527 | AAPL,May 1 2007,121.19 528 | AAPL,Jun 1 2007,122.04 529 | AAPL,Jul 1 2007,131.76 530 | AAPL,Aug 1 2007,138.48 531 | AAPL,Sep 1 2007,153.47 532 | AAPL,Oct 1 2007,189.95 533 | AAPL,Nov 1 2007,182.22 534 | AAPL,Dec 1 2007,198.08 535 | AAPL,Jan 1 2008,135.36 536 | AAPL,Feb 1 2008,125.02 537 | AAPL,Mar 1 2008,143.5 538 | AAPL,Apr 1 2008,173.95 539 | AAPL,May 1 2008,188.75 540 | AAPL,Jun 1 2008,167.44 541 | AAPL,Jul 1 2008,158.95 542 | AAPL,Aug 1 2008,169.53 543 | AAPL,Sep 1 2008,113.66 544 | AAPL,Oct 1 2008,107.59 545 | AAPL,Nov 1 2008,92.67 546 | AAPL,Dec 1 2008,85.35 547 | AAPL,Jan 1 2009,90.13 548 | AAPL,Feb 1 2009,89.31 549 | AAPL,Mar 1 2009,105.12 550 | AAPL,Apr 1 2009,125.83 551 | AAPL,May 1 2009,135.81 552 | AAPL,Jun 1 2009,142.43 553 | AAPL,Jul 1 2009,163.39 554 | AAPL,Aug 1 2009,168.21 555 | AAPL,Sep 1 2009,185.35 556 | AAPL,Oct 1 2009,188.5 557 | AAPL,Nov 1 2009,199.91 558 | AAPL,Dec 1 2009,210.73 559 | AAPL,Jan 1 2010,192.06 560 | AAPL,Feb 1 2010,204.62 561 | AAPL,Mar 1 2010,223.02 -------------------------------------------------------------------------------- /priv/datasets/us-employment.csv: -------------------------------------------------------------------------------- 1 | month,nonfarm,private,goods_producing,service_providing,private_service_providing,mining_and_logging,construction,manufacturing,durable_goods,nondurable_goods,trade_transportation_utilties,wholesale_trade,retail_trade,transportation_and_warehousing,utilities,information,financial_activities,professional_and_business_services,education_and_health_services,leisure_and_hospitality,other_services,government,nonfarm_change 2 | 2006-01-01,135450,113603,22467,112983,91136,656,7601,14210,8982,5228,26162,5840.4,15351.5,4420,549.8,3052,8307,17299,17946,12945,5425,21847,282 3 | 2006-02-01,135762,113884,22535,113227,91349,662,7664,14209,8986,5223,26196,5854.8,15361.3,4429.4,550.1,3052,8332,17365,17998,12980,5426,21878,312 4 | 2006-03-01,136059,114156,22572,113487,91584,669,7689,14214,9000,5214,26239,5873.3,15388,4429.7,547.5,3055,8348,17438,18045,13034,5425,21903,297 5 | 2006-04-01,136227,114308,22631,113596,91677,679,7726,14226,9020,5206,26230,5886.9,15348.5,4445.4,548.9,3046,8369,17462,18070,13074,5426,21919,168 6 | 2006-05-01,136258,114332,22597,113661,91735,681,7713,14203,9017,5186,26223,5897.2,15318.1,4459.4,548.3,3039,8376,17512,18100,13052,5433,21926,31 7 | 2006-06-01,136337,114415,22598,113739,91817,686,7699,14213,9028,5185,26241,5903,15325.5,4465.1,547.6,3036,8362,17583,18102,13061,5432,21922,79 8 | 2006-07-01,136543,114570,22590,113953,91980,690,7712,14188,9008,5180,26264,5911.2,15326,4479.3,547.9,3031,8366,17632,18128,13130,5429,21973,206 9 | 2006-08-01,136722,114711,22572,114150,92139,693,7720,14159,8992,5167,26283,5918.2,15337.5,4479.5,548,3035,8374,17681,18182,13152,5432,22011,179 10 | 2006-09-01,136870,114788,22537,114333,92251,694,7718,14125,8972,5153,26311,5927.6,15347.8,4486.6,548.5,3028,8390,17676,18248,13150,5448,22082,148 11 | 2006-10-01,136882,114814,22456,114426,92358,699,7682,14075,8945,5130,26335,5925.8,15366.2,4496.1,546.9,3024,8385,17685,18288,13187,5454,22068,12 12 | 2006-11-01,137090,115007,22408,114682,92599,701,7666,14041,8918,5123,26392,5942.7,15391.5,4509.3,548,3025,8394,17745,18337,13251,5455,22083,208 13 | 2006-12-01,137263,115175,22405,114858,92770,705,7685,14015,8913,5102,26437,5964.6,15394.2,4529.2,548.5,3032,8394,17771,18378,13292,5466,22088,173 14 | 2007-01-01,137497,115402,22439,115058,92963,706,7725,14008,8890,5118,26491,5969.3,15443.3,4530.2,548.6,3029,8389,17834,18415,13338,5467,22095,234 15 | 2007-02-01,137582,115451,22334,115248,93117,711,7626,13997,8889,5108,26540,5986.7,15474.7,4530.1,548.5,3033,8390,17868,18451,13361,5474,22131,85 16 | 2007-03-01,137796,115647,22391,115405,93256,715,7706,13970,8871,5099,26614,5987.4,15542.2,4535.3,549.1,3029,8379,17880,18507,13363,5484,22149,214 17 | 2007-04-01,137855,115680,22350,115505,93330,719,7686,13945,8860,5085,26601,6003.6,15508.5,4537.6,551.4,3034,8360,17906,18563,13375,5491,22175,59 18 | 2007-05-01,138008,115815,22323,115685,93492,721,7673,13929,8846,5083,26634,6010.4,15528.7,4541.1,553.7,3040,8371,17939,18608,13404,5496,22193,153 19 | 2007-06-01,138085,115878,22323,115762,93555,725,7687,13911,8830,5081,26626,6024.4,15507.9,4538.3,554.9,3038,8369,17949,18661,13413,5499,22207,77 20 | 2007-07-01,138055,115884,22277,115778,93607,728,7660,13889,8815,5074,26633,6029.8,15509.2,4539.1,555,3037,8370,17959,18691,13417,5500,22171,-30 21 | 2007-08-01,138027,115801,22165,115862,93636,727,7610,13828,8778,5050,26629,6031,15507.2,4534.7,555.8,3029,8341,17967,18755,13419,5496,22226,-28 22 | 2007-09-01,138123,115844,22093,116030,93751,726,7577,13790,8752,5038,26658,6028.3,15514.7,4559.9,555.4,3030,8319,17979,18812,13461,5492,22279,96 23 | 2007-10-01,138201,115904,22056,116145,93848,727,7565,13764,8727,5037,26662,6035.8,15515.3,4555.1,555.8,3028,8306,18010,18849,13499,5494,22297,78 24 | 2007-11-01,138307,115973,22015,116292,93958,735,7523,13757,8724,5033,26717,6041.8,15568.7,4551.1,555.5,3025,8292,18009,18875,13535,5505,22334,106 25 | 2007-12-01,138411,116035,21976,116435,94059,740,7490,13746,8707,5039,26712,6037.8,15568.8,4548,557.1,3024,8282,18051,18924,13550,5516,22376,104 26 | 2008-01-01,138419,116031,21947,116472,94084,746,7476,13725,8693,5032,26710,6035.7,15565.6,4551.4,557,3025,8277,18030,18978,13542,5522,22388,8 27 | 2008-02-01,138338,115921,21897,116441,94024,748,7453,13696,8673,5023,26658,6026.2,15523,4552.3,556.3,3019,8268,17985,19018,13543,5533,22417,-81 28 | 2008-03-01,138283,115840,21820,116463,94020,755,7406,13659,8646,5013,26653,6015.4,15526.2,4554.8,556.4,3021,8266,17942,19068,13531,5539,22443,-55 29 | 2008-04-01,138054,115604,21681,116373,93923,755,7327,13599,8597,5002,26537,5993,15426.1,4560.6,556.9,3012,8258,17939,19126,13511,5540,22450,-229 30 | 2008-05-01,137870,115387,21599,116271,93788,761,7274,13564,8579,4985,26452,5980.2,15370.9,4543.8,556.8,3008,8246,17882,19166,13498,5536,22483,-184 31 | 2008-06-01,137716,115199,21483,116233,93716,766,7213,13504,8542,4962,26398,5965.8,15337.4,4536.6,557.8,3001,8236,17850,19224,13482,5525,22517,-154 32 | 2008-07-01,137503,114935,21360,116143,93575,770,7160,13430,8488,4942,26333,5946.3,15300,4527.3,559.6,2987,8219,17777,19275,13463,5521,22568,-213 33 | 2008-08-01,137226,114659,21250,115976,93409,778,7114,13358,8430,4928,26238,5926.3,15241.1,4511.2,558.9,2973,8204,17713,19337,13431,5513,22567,-277 34 | 2008-09-01,136783,114246,21101,115682,93145,782,7044,13275,8372,4903,26123,5914,15171.9,4477.6,559.4,2961,8170,17657,19343,13379,5512,22537,-443 35 | 2008-10-01,136308,113759,20895,115413,92864,781,6967,13147,8275,4872,26002,5876.3,15101.4,4463.4,560.9,2950,8138,17543,19363,13352,5516,22549,-475 36 | 2008-11-01,135549,112989,20623,114926,92366,776,6813,13034,8193,4841,25808,5838.2,14986.6,4420.9,562.5,2932,8101,17348,19401,13300,5476,22560,-759 37 | 2008-12-01,134842,112286,20322,114520,91964,771,6701,12850,8065,4785,25622,5797,14866.7,4395.2,562.9,2909,8070,17219,19442,13256,5446,22556,-707 38 | 2009-01-01,134055,111476,19889,114166,91587,761,6567,12561,7832,4729,25485,5762.7,14788.4,4371.1,563,2891,8018,17061,19482,13222,5428,22579,-787 39 | 2009-02-01,133351,110775,19575,113776,91200,749,6446,12380,7699,4681,25345,5717.9,14716.7,4346.8,563.6,2878,7970,16896,19507,13193,5411,22576,-704 40 | 2009-03-01,132549,109989,19227,113322,90762,728,6291,12208,7577,4631,25192,5673,14641.6,4314.3,563,2864,7927,16755,19514,13127,5383,22560,-802 41 | 2009-04-01,131845,109168,18894,112951,90274,710,6154,12030,7428,4602,25014,5627.5,14556.1,4268.7,561.3,2833,7870,16608,19521,13056,5372,22677,-704 42 | 2009-05-01,131491,108874,18655,112836,90219,693,6100,11862,7289,4573,24965,5602.9,14553.5,4249.2,559.8,2807,7844,16546,19582,13106,5369,22617,-354 43 | 2009-06-01,131022,108446,18422,112600,90024,686,6010,11726,7182,4544,24909,5577.4,14537.2,4233.8,560.1,2796,7821,16436,19614,13076,5372,22576,-469 44 | 2009-07-01,130680,108159,18278,112402,89881,678,5932,11668,7146,4522,24808,5552.5,14486.3,4210,558.8,2780,7807,16411,19629,13078,5368,22521,-342 45 | 2009-08-01,130484,107947,18151,112333,89796,670,5855,11626,7113,4513,24769,5535,14477.3,4198.9,557.9,2767,7782,16392,19681,13046,5359,22537,-196 46 | 2009-09-01,130255,107804,18043,112212,89761,665,5787,11591,7084,4507,24716,5518.8,14445.9,4192,558.8,2768,7769,16409,19692,13054,5353,22451,-229 47 | 2009-10-01,130046,107522,17915,112131,89607,661,5716,11538,7044,4494,24612,5500.1,14379.2,4173.9,558.6,2763,7754,16414,19736,12995,5333,22524,-209 48 | 2009-11-01,130058,107525,17869,112189,89656,664,5696,11509,7020,4489,24590,5489.4,14374.8,4168.7,557.5,2752,7756,16478,19770,12986,5324,22533,12 49 | 2009-12-01,129781,107299,17792,111989,89507,663,5654,11475,6999,4476,24475,5475.1,14326.4,4117.2,556,2743,7743,16478,19804,12944,5320,22482,-277 50 | 2010-01-01,129799,107308,17707,112092,89601,667,5580,11460,6989,4471,24543,5455.3,14393.1,4138.7,556,2737,7733,16513,19820,12932,5323,22491,18 51 | 2010-02-01,129726,107250,17627,112099,89623,674,5500,11453,6985,4468,24534,5443.6,14395.7,4140,554.8,2737,7724,16546,19839,12927,5316,22476,-73 52 | 2010-03-01,129919,107401,17672,112247,89729,682,5537,11453,6996,4457,24594,5444.3,14442.7,4152.1,554.5,2718,7708,16541,19896,12943,5329,22518,193 53 | 2010-04-01,130140,107571,17729,112411,89842,687,5553,11489,7026,4463,24580,5443.4,14423.3,4158.9,554.2,2715,7713,16618,19902,12979,5335,22569,221 54 | 2010-05-01,130662,107666,17742,112920,89924,697,5520,11525,7053,4472,24597,5439,14435.6,4169.1,553.6,2709,7699,16643,19934,13012,5330,22996,522 55 | 2010-06-01,130522,107782,17763,112759,90019,702,5516,11545,7072,4473,24621,5442.9,14436.1,4190,552,2703,7689,16702,19955,13034,5315,22740,-140 56 | 2010-07-01,130444,107875,17777,112667,90098,708,5508,11561,7083,4478,24650,5445.9,14445.6,4206.7,551.4,2703,7676,16715,19980,13048,5326,22569,-78 57 | 2010-08-01,130428,108008,17793,112635,90215,716,5524,11553,7090,4463,24648,5446.4,14450,4200,551.5,2702,7676,16768,20017,13081,5323,22420,-16 58 | 2010-09-01,130365,108118,17787,112578,90331,723,5501,11563,7105,4458,24696,5454.4,14472.6,4219.3,549.4,2697,7683,16785,20001,13137,5332,22247,-63 59 | 2010-10-01,130632,108335,17801,112831,90534,731,5508,11562,7109,4453,24748,5463.5,14503.7,4229.3,551.6,2695,7682,16851,20074,13127,5357,22297,267 60 | 2010-11-01,130761,108474,17827,112934,90647,736,5506,11585,7125,4460,24735,5469.7,14480,4234.1,551.1,2689,7679,16953,20119,13126,5346,22287,129 61 | 2010-12-01,130834,108568,17796,113038,90772,734,5467,11595,7137,4458,24759,5476.4,14467.4,4261.5,553.3,2682,7683,17020,20134,13157,5337,22266,73 62 | 2011-01-01,130878,108620,17784,113094,90836,736,5427,11621,7168,4453,24795,5481.4,14531.4,4230.5,551.5,2678,7680,17054,20153,13149,5327,22258,44 63 | 2011-02-01,131060,108845,17844,113216,91001,739,5451,11654,7195,4459,24864,5493.9,14553.6,4263.6,553.3,2673,7676,17100,20163,13188,5337,22215,182 64 | 2011-03-01,131314,109122,17906,113408,91216,754,5477,11675,7214,4461,24922,5512.4,14584.2,4272.5,552.7,2672,7681,17184,20177,13247,5333,22192,254 65 | 2011-04-01,131637,109453,17957,113680,91496,768,5485,11704,7240,4464,25014,5527.7,14641.7,4291,553.7,2674,7685,17246,20237,13298,5342,22184,323 66 | 2011-05-01,131718,109589,18007,113711,91582,778,5516,11713,7257,4456,25024,5531.4,14640.2,4299.3,553.1,2679,7701,17287,20252,13293,5346,22129,81 67 | 2011-06-01,131952,109788,18045,113907,91743,790,5528,11727,7275,4452,25084,5540.9,14675.7,4314.2,553,2685,7691,17300,20288,13343,5352,22164,234 68 | 2011-07-01,132024,109975,18094,113930,91881,801,5547,11746,7289,4457,25129,5545.5,14717.5,4314.8,551.6,2676,7694,17326,20327,13370,5359,22049,72 69 | 2011-08-01,132136,110119,18120,114016,91999,804,5552,11764,7303,4461,25141,5554.1,14714.9,4320,552.1,2634,7698,17388,20367,13395,5376,22017,112 70 | 2011-09-01,132369,110386,18167,114202,92219,814,5584,11769,7313,4456,25180,5559.4,14738.7,4329,552.6,2677,7693,17447,20415,13426,5381,21983,233 71 | 2011-10-01,132578,110580,18188,114390,92392,820,5588,11780,7330,4450,25209,5576.5,14743.8,4336.3,552.1,2677,7706,17497,20457,13464,5382,21998,209 72 | 2011-11-01,132723,110752,18187,114536,92565,824,5593,11770,7331,4439,25232,5588.5,14751.3,4339.4,552.6,2676,7719,17541,20496,13511,5390,21971,145 73 | 2011-12-01,132924,110970,18244,114680,92726,831,5611,11802,7368,4434,25247,5605.1,14745.5,4344.3,552.2,2678,7727,17603,20530,13538,5403,21954,201 74 | 2012-01-01,133272,111326,18304,114968,93022,840,5626,11838,7398,4440,25347,5620.5,14813.1,4360.3,553.3,2665,7736,17686,20574,13600,5414,21946,348 75 | 2012-02-01,133505,111558,18334,115171,93224,845,5629,11860,7420,4440,25352,5630.3,14784.4,4384.5,553.2,2676,7744,17739,20657,13641,5415,21947,233 76 | 2012-03-01,133769,111826,18372,115397,93454,849,5625,11898,7446,4452,25407,5640.1,14820,4393.5,553.6,2678,7768,17784,20689,13706,5422,21943,264 77 | 2012-04-01,133841,111910,18384,115457,93526,850,5618,11916,7461,4455,25411,5652.3,14831.3,4374.2,553.4,2679,7771,17832,20707,13709,5417,21931,72 78 | 2012-05-01,133958,112047,18386,115572,93661,855,5604,11927,7471,4456,25457,5663.1,14829.4,4411,553.2,2685,7781,17869,20747,13705,5417,21911,117 79 | 2012-06-01,134026,112096,18411,115615,93685,854,5621,11936,7480,4456,25445,5671.9,14810,4409.2,554,2674,7781,17921,20738,13702,5424,21930,68 80 | 2012-07-01,134182,112269,18447,115735,93822,851,5632,11964,7503,4461,25450,5679.2,14803.7,4420.4,546.6,2680,7779,17972,20773,13735,5433,21913,156 81 | 2012-08-01,134355,112439,18459,115896,93980,851,5648,11960,7492,4468,25483,5685.1,14811,4432.5,554.2,2676,7787,17998,20801,13804,5431,21916,173 82 | 2012-09-01,134549,112624,18461,116088,94163,846,5661,11954,7483,4471,25514,5676.3,14845.9,4437,554.4,2670,7801,18023,20841,13872,5442,21925,194 83 | 2012-10-01,134702,112799,18472,116230,94327,837,5674,11961,7485,4476,25560,5691.6,14867.1,4447.8,553.9,2667,7809,18081,20881,13883,5446,21903,153 84 | 2012-11-01,134832,112949,18477,116355,94472,843,5684,11950,7488,4462,25614,5693.5,14930.1,4439.2,551.5,2674,7816,18122,20887,13910,5449,21883,130 85 | 2012-12-01,135075,113188,18532,116543,94656,848,5724,11960,7505,4455,25633,5704,14905.1,4472.6,551.5,2675,7826,18157,20935,13978,5452,21887,243 86 | 2013-01-01,135282,113413,18580,116702,94833,851,5746,11983,7515,4468,25679,5715.5,14928.6,4482.7,551.8,2661,7836,18206,20956,14037,5458,21869,207 87 | 2013-02-01,135547,113666,18638,116909,95028,858,5784,11996,7523,4473,25679,5711.1,14941.7,4474.3,552.2,2699,7852,18302,20958,14082,5456,21881,265 88 | 2013-03-01,135703,113833,18660,117043,95173,859,5802,11999,7531,4468,25680,5713.7,14941.4,4473.9,550.6,2699,7857,18366,21007,14113,5451,21870,156 89 | 2013-04-01,135882,114013,18653,117229,95360,857,5796,12000,7534,4466,25710,5714.9,14961.7,4480.7,552.3,2696,7872,18421,21054,14152,5455,21869,179 90 | 2013-05-01,136122,114258,18691,117431,95567,862,5829,12000,7533,4467,25749,5721,14996.2,4479.1,553,2711,7885,18488,21071,14193,5470,21864,240 91 | 2013-06-01,136280,114440,18724,117556,95716,865,5855,12004,7539,4465,25803,5723.9,15039.8,4484.8,554.7,2707,7887,18517,21070,14252,5480,21840,158 92 | 2013-07-01,136391,114576,18705,117686,95871,862,5859,11984,7517,4467,25837,5734.6,15080.5,4470.6,551.4,2720,7903,18566,21074,14288,5483,21815,111 93 | 2013-08-01,136651,114820,18756,117895,96064,864,5878,12014,7547,4467,25906,5743.7,15123.2,4488.2,551,2690,7901,18603,21143,14327,5494,21831,260 94 | 2013-09-01,136852,115017,18810,118042,96207,868,5910,12032,7564,4468,25979,5752.8,15156.7,4518.4,551.4,2707,7904,18643,21133,14339,5502,21835,201 95 | 2013-10-01,137062,115232,18857,118205,96375,870,5931,12056,7576,4480,26018,5748.7,15195.6,4522.8,551.1,2719,7910,18666,21158,14395,5509,21830,210 96 | 2013-11-01,137283,115440,18911,118372,96529,869,5963,12079,7589,4490,26054,5760,15199.8,4541.5,552.2,2724,7912,18700,21194,14432,5513,21843,221 97 | 2013-12-01,137376,115556,18881,118495,96675,866,5932,12083,7591,4492,26148,5762.8,15285.6,4549.5,550.5,2726,7914,18712,21196,14454,5525,21820,93 98 | 2014-01-01,137550,115740,18934,118616,96806,871,5981,12082,7584,4498,26151,5776.2,15256.3,4569.7,549.2,2723,7915,18773,21225,14486,5533,21810,174 99 | 2014-02-01,137732,115909,18986,118746,96923,874,6007,12105,7604,4501,26132,5782.7,15229.9,4570.5,549,2719,7932,18844,21246,14516,5534,21823,182 100 | 2014-03-01,137993,116162,19041,118952,97121,879,6041,12121,7622,4499,26170,5785.8,15248.8,4584.6,551.1,2724,7933,18887,21292,14562,5553,21831,261 101 | 2014-04-01,138304,116447,19102,119202,97345,886,6081,12135,7633,4502,26247,5802.9,15295.6,4598.4,550.2,2722,7945,18943,21314,14610,5564,21857,311 102 | 2014-05-01,138556,116693,19145,119411,97548,887,6111,12147,7649,4498,26293,5807.7,15307.5,4627.4,550.1,2718,7953,18984,21370,14663,5567,21863,252 103 | 2014-06-01,138862,116967,19194,119668,97773,892,6131,12171,7670,4501,26368,5818.6,15347.9,4650.8,551,2724,7965,19048,21416,14689,5563,21895,306 104 | 2014-07-01,139058,117180,19261,119797,97919,897,6174,12190,7687,4503,26415,5824.3,15369.5,4669.7,551.2,2727,7978,19083,21449,14702,5565,21878,196 105 | 2014-08-01,139284,117421,19307,119977,98114,897,6204,12206,7698,4508,26437,5824.6,15374.7,4685,553.1,2734,7993,19143,21499,14727,5581,21863,226 106 | 2014-09-01,139568,117672,19364,120204,98308,904,6236,12224,7708,4516,26483,5823.5,15406.3,4701.5,551.3,2732,8008,19200,21540,14771,5574,21896,284 107 | 2014-10-01,139823,117906,19411,120412,98495,901,6254,12256,7729,4527,26555,5832.3,15447.6,4722.7,552,2728,8020,19219,21575,14818,5580,21917,255 108 | 2014-11-01,140130,118196,19451,120679,98745,899,6270,12282,7746,4536,26629,5835.5,15501.9,4739.4,552.4,2736,8034,19283,21625,14847,5591,21934,307 109 | 2014-12-01,140381,118432,19482,120899,98950,896,6295,12291,7751,4540,26663,5844,15495.5,4769.1,554.1,2737,8042,19350,21676,14890,5592,21949,251 110 | 2015-01-01,140592,118637,19516,121076,99121,888,6332,12296,7754,4542,26697,5848.9,15501.7,4791.6,554.6,2737,8060,19371,21741,14916,5599,21955,211 111 | 2015-02-01,140859,118884,19532,121327,99352,875,6356,12301,7761,4540,26733,5857.7,15521.6,4799.6,554.2,2741,8072,19424,21787,14990,5605,21975,267 112 | 2015-03-01,140937,118973,19512,121425,99461,859,6340,12313,7766,4547,26772,5858.7,15545.1,4813.6,554.7,2735,8082,19447,21829,14990,5606,21964,78 113 | 2015-04-01,141219,119219,19551,121668,99668,843,6390,12318,7764,4554,26803,5854.8,15568.8,4824,555.1,2742,8087,19499,21905,15019,5613,22000,282 114 | 2015-05-01,141545,119535,19584,121961,99951,820,6428,12336,7774,4562,26857,5859.6,15597.2,4843.7,556.2,2750,8096,19571,21952,15101,5624,22010,326 115 | 2015-06-01,141736,119724,19601,122135,100123,817,6444,12340,7776,4564,26897,5857.1,15615,4869.7,555.6,2751,8112,19634,22002,15109,5618,22012,191 116 | 2015-07-01,141992,119958,19629,122363,100329,808,6466,12355,7776,4579,26942,5857.4,15635.6,4892,557.2,2754,8134,19665,22051,15154,5629,22034,256 117 | 2015-08-01,142156,120084,19628,122528,100456,797,6485,12346,7774,4572,26946,5854.8,15629.7,4903.8,557.8,2754,8146,19697,22093,15201,5619,22072,164 118 | 2015-09-01,142244,120203,19622,122622,100581,779,6498,12345,7770,4575,26930,5842.1,15620.5,4910.9,556.7,2761,8152,19717,22138,15263,5620,22041,88 119 | 2015-10-01,142595,120536,19669,122926,100867,771,6540,12358,7768,4590,26970,5849.6,15661.9,4903,555.9,2768,8168,19791,22217,15324,5629,22059,351 120 | 2015-11-01,142859,120775,19701,123158,101074,755,6592,12354,7753,4601,27037,5851.8,15704.2,4924.7,556.6,2754,8181,19835,22263,15366,5638,22084,264 121 | 2015-12-01,143093,120993,19737,123356,101256,745,6632,12360,7747,4613,27036,5850.5,15677.8,4950.9,556.5,2762,8188,19892,22318,15408,5652,22100,234 122 | -------------------------------------------------------------------------------- /priv/datasets/wheat.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"year":"1565","wheat":41,"wages":5}, 3 | {"year":"1570","wheat":45,"wages":5.05}, 4 | {"year":"1575","wheat":42,"wages":5.08}, 5 | {"year":"1580","wheat":49,"wages":5.12}, 6 | {"year":"1585","wheat":41.5,"wages":5.15}, 7 | {"year":"1590","wheat":47,"wages":5.25}, 8 | {"year":"1595","wheat":64,"wages":5.54}, 9 | {"year":"1600","wheat":27,"wages":5.61}, 10 | {"year":"1605","wheat":33,"wages":5.69}, 11 | {"year":"1610","wheat":32,"wages":5.78}, 12 | {"year":"1615","wheat":33,"wages":5.94}, 13 | {"year":"1620","wheat":35,"wages":6.01}, 14 | {"year":"1625","wheat":33,"wages":6.12}, 15 | {"year":"1630","wheat":45,"wages":6.22}, 16 | {"year":"1635","wheat":33,"wages":6.3}, 17 | {"year":"1640","wheat":39,"wages":6.37}, 18 | {"year":"1645","wheat":53,"wages":6.45}, 19 | {"year":"1650","wheat":42,"wages":6.5}, 20 | {"year":"1655","wheat":40.5,"wages":6.6}, 21 | {"year":"1660","wheat":46.5,"wages":6.75}, 22 | {"year":"1665","wheat":32,"wages":6.8}, 23 | {"year":"1670","wheat":37,"wages":6.9}, 24 | {"year":"1675","wheat":43,"wages":7}, 25 | {"year":"1680","wheat":35,"wages":7.3}, 26 | {"year":"1685","wheat":27,"wages":7.6}, 27 | {"year":"1690","wheat":40,"wages":8}, 28 | {"year":"1695","wheat":50,"wages":8.5}, 29 | {"year":"1700","wheat":30,"wages":9}, 30 | {"year":"1705","wheat":32,"wages":10}, 31 | {"year":"1710","wheat":44,"wages":11}, 32 | {"year":"1715","wheat":33,"wages":11.75}, 33 | {"year":"1720","wheat":29,"wages":12.5}, 34 | {"year":"1725","wheat":39,"wages":13}, 35 | {"year":"1730","wheat":26,"wages":13.3}, 36 | {"year":"1735","wheat":32,"wages":13.6}, 37 | {"year":"1740","wheat":27,"wages":14}, 38 | {"year":"1745","wheat":27.5,"wages":14.5}, 39 | {"year":"1750","wheat":31,"wages":15}, 40 | {"year":"1755","wheat":35.5,"wages":15.7}, 41 | {"year":"1760","wheat":31,"wages":16.5}, 42 | {"year":"1765","wheat":43,"wages":17.6}, 43 | {"year":"1770","wheat":47,"wages":18.5}, 44 | {"year":"1775","wheat":44,"wages":19.5}, 45 | {"year":"1780","wheat":46,"wages":21}, 46 | {"year":"1785","wheat":42,"wages":23}, 47 | {"year":"1790","wheat":47.5,"wages":25.5}, 48 | {"year":"1795","wheat":76,"wages":27.5}, 49 | {"year":"1800","wheat":79,"wages":28.5}, 50 | {"year":"1805","wheat":81,"wages":29.5}, 51 | {"year":"1810","wheat":99,"wages":30}, 52 | {"year":"1815","wheat":78}, 53 | {"year":"1820","wheat":54} 54 | ] -------------------------------------------------------------------------------- /priv/local_datasets.json: -------------------------------------------------------------------------------- 1 | { 2 | "airports": "datasets/airports.csv", 3 | "anscombe": "datasets/anscombe.json", 4 | "barley": "datasets/barley.json", 5 | "burtin": "datasets/burtin.json", 6 | "cars": { 7 | "file": "datasets/cars.json", 8 | "date": "Year", 9 | "format": "%Y-%m-%d" 10 | }, 11 | "crimea": { 12 | "file": "datasets/crimea.json", 13 | "date": "date", 14 | "format": "%Y-%m-%d" 15 | }, 16 | "driving": "datasets/driving.json", 17 | "iowa-electricity": { 18 | "file": "datasets/iowa-electricity.csv", 19 | "date": "year", 20 | "format": "%Y-%m-%d" 21 | }, 22 | "iris": "datasets/iris.json", 23 | "la-riots": { 24 | "file": "datasets/la-riots.csv", 25 | "date": "death_date", 26 | "format": "%Y-%m-%d" 27 | }, 28 | "ohlc": { 29 | "file": "datasets/ohlc.json", 30 | "date": "date", 31 | "format": "%Y-%m-%d" 32 | }, 33 | "seattle-temps": { 34 | "file": "datasets/seattle-temps.csv", 35 | "date": "date", 36 | "format": "%Y/%m/%d %H:%M" 37 | }, 38 | "seattle-weather": { 39 | "file": "datasets/seattle-weather.csv", 40 | "date": "date", 41 | "format": "%Y/%m/%d" 42 | }, 43 | "sf-temps": { 44 | "file": "datasets/sf-temps.csv", 45 | "date": "Date", 46 | "format": "%Y/%m/%d %H:%M:%S" 47 | }, 48 | "stocks": { 49 | "file": "datasets/stocks.csv", 50 | "date": "date", 51 | "format": "%b %e %Y" 52 | }, 53 | "us-employment": { 54 | "file": "datasets/us-employment.csv", 55 | "date": "month", 56 | "format": "%Y-%m-%d" 57 | }, 58 | "wheat": "datasets/wheat.json", 59 | "movies": "datasets/movies.json", 60 | "btc": { 61 | "file": "datasets/btc.csv", 62 | "date": "Date", 63 | "format": "%Y-%m-%d" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /slides/assets/custom.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=BioRhyme&display=swap'); 2 | /* @import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro&display=swap'); */ 3 | /* @import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap'); */ 4 | @import url('https://fonts.googleapis.com/css?family=Cairo&display=swap'); 5 | 6 | 7 | 8 | /*! 9 | * Marp / Marpit Uncover theme 10 | * 11 | * @theme uncover 12 | * @author Yuki Hattori 13 | * 14 | * @auto-scaling fittingHeader,math 15 | * @size 4:3 960px 720px 16 | */ 17 | section { 18 | display: flex; 19 | flex-direction: column; 20 | font-family: 'Cairo', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 21 | flex-wrap: nowrap; 22 | font-size: 40px; 23 | height: 720px; 24 | justify-content: center; 25 | /* letter-spacing: 3px; */ 26 | line-height: 1.5; 27 | padding: 30px 70px; 28 | position: relative; 29 | text-align: center; 30 | width: 1280px; 31 | z-index: 0; 32 | background: #fdfcff; 33 | color: #202228; 34 | } 35 | 36 | section::after { 37 | align-items: flex-end; 38 | display: flex; 39 | font-size: 0.6em; 40 | height: 80px; 41 | justify-content: flex-end; 42 | padding: 30px; 43 | text-align: right; 44 | width: 80px; 45 | } 46 | 47 | section::after { 48 | /* 49 | * Gradient with hard stops has incorrect rendering in Firefox's PDF.js 50 | * @see https://github.com/mozilla/pdf.js/issues/10572 51 | */ 52 | background: url("data:image/svg+xml;utf8,") no-repeat center center; 53 | background-size: cover; 54 | color: #202228; 55 | text-shadow: 0 0 5px #fdfcff; 56 | } 57 | section pre, section code { 58 | background: #f2f1f4; 59 | color: #202228; 60 | } 61 | section a { 62 | color: #009dd5; 63 | } 64 | section a:hover { 65 | color: #087eaa; 66 | } 67 | section h1 strong, section h2 strong, section h3 strong, section h4 strong, section h5 strong, section h6 strong { 68 | color: #33b1dd; 69 | } 70 | section header, section footer { 71 | color: rgba(32, 34, 40, 0.4); 72 | text-shadow: 0 1px 0 rgba(253, 252, 255, 0.8); 73 | text-align: left; 74 | } 75 | section mark { 76 | color: #009dd5; 77 | background: transparent; 78 | } 79 | section:not(.invert) { 80 | @import url('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/styles/color-brewer.min.css'); 81 | } 82 | section.invert { 83 | background: #202228; 84 | color: #fff; 85 | @import url('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/styles/codepen-embed.min.css'); 86 | } 87 | section.invert::after { 88 | /* 89 | * Gradient with hard stops has incorrect rendering in Firefox's PDF.js 90 | * @see https://github.com/mozilla/pdf.js/issues/10572 91 | */ 92 | background: url("data:image/svg+xml;utf8,") no-repeat center center; 93 | background-size: cover; 94 | color: #fff; 95 | text-shadow: 0 0 5px #202228; 96 | } 97 | section.invert pre, section.invert code { 98 | background: #2b2d33; 99 | color: #fff; 100 | } 101 | section.invert a { 102 | color: #60d0f0; 103 | } 104 | section.invert a:hover { 105 | color: #88dcf4; 106 | } 107 | section.invert h1 strong, section.invert h2 strong, section.invert h3 strong, section.invert h4 strong, section.invert h5 strong, section.invert h6 strong { 108 | color: #80d9f3; 109 | } 110 | section.invert header, section.invert footer { 111 | color: rgba(255, 255, 255, 0.4); 112 | text-shadow: 0 1px 0 rgba(32, 34, 40, 0.8); 113 | } 114 | section.invert mark { 115 | color: #60d0f0; 116 | background: transparent; 117 | } 118 | section > *:first-child, section[data-header] > :nth-child(2) { 119 | margin-top: 0; 120 | } 121 | section > *:last-child, section[data-footer] > :nth-last-child(2) { 122 | margin-bottom: 0; 123 | } 124 | section svg[data-marp-fitting='svg'] { 125 | max-height: 660px; 126 | --preserve-aspect-ratio: xMidYMid meet; 127 | } 128 | section p, section blockquote { 129 | margin: 0 0 15px 0; 130 | } 131 | section h1, section h2, section h3, section h4, section h5, section h6 { 132 | margin: 15px 0 30px 0; 133 | font-family: 'BioRhyme'; 134 | } 135 | section h1 strong, section h2 strong, section h3 strong, section h4 strong, section h5 strong, section h6 strong { 136 | font-weight: inherit; 137 | } 138 | section h1 { 139 | font-size: 2em; 140 | } 141 | section h2 { 142 | font-size: 1.7em; 143 | } 144 | section h3 { 145 | font-size: 1.4em; 146 | letter-spacing: 2px; 147 | } 148 | section h4 { 149 | font-size: 1.2em; 150 | letter-spacing: 2px; 151 | } 152 | section h5 { 153 | font-size: 1em; 154 | letter-spacing: 1px; 155 | } 156 | section h6 { 157 | font-size: 0.7em; 158 | letter-spacing: 0px; 159 | margin: 0px auto; 160 | text-align: left; 161 | } 162 | section header, section footer { 163 | position: absolute; 164 | z-index: 1; 165 | left: 70px; 166 | right: 70px; 167 | font-size: 0.45em; 168 | letter-spacing: 1px; 169 | } 170 | section header { 171 | top: 30px; 172 | } 173 | section footer { 174 | bottom: 30px; 175 | } 176 | section a { 177 | text-decoration: none; 178 | } 179 | section a:hover { 180 | text-decoration: underline; 181 | } 182 | section ul, section ol { 183 | margin: 0 auto; 184 | text-align: left; 185 | font-size: 20px; 186 | } 187 | section > ul, section > ol { 188 | margin-bottom: 15px; 189 | margin-top: 15px; 190 | font-size: 28px; 191 | } 192 | 193 | 194 | section pre, section code { 195 | font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; 196 | letter-spacing: 0; 197 | margin: -0.1em 0.1em 0.1em; 198 | padding: 0.1em; 199 | } 200 | section pre { 201 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); 202 | font-size: 18px; 203 | line-height: 1.15; 204 | margin: 11px auto 6px auto; 205 | min-width: 95%; 206 | max-width: 95%; 207 | overflow: scroll; 208 | padding: 0.4em 0.6em; 209 | text-align: left; 210 | } 211 | section pre > code { 212 | margin: 0; 213 | padding: 0; 214 | } 215 | section table { 216 | border-collapse: collapse; 217 | margin: 0 auto 15px auto; 218 | } 219 | section table > thead > tr > td, section table > tbody > tr > td, section table > thead > tr > th, section table > tbody > tr > th { 220 | padding: 0.15em 0.5em; 221 | } 222 | section table > thead > tr > td, section table > thead > tr > th { 223 | border-bottom: 3px solid currentColor; 224 | } 225 | section table > tbody > tr:not(:last-child) > td, section table > tbody > tr:not(:last-child) > th { 226 | border-bottom: 1px solid currentColor; 227 | } 228 | section blockquote { 229 | font-size: 90%; 230 | line-height: 1.3; 231 | padding: 0 2em; 232 | position: relative; 233 | z-index: 0; 234 | color: gray 235 | } 236 | section blockquote::before, section blockquote::after { 237 | content: url('./assets/uncover-quote.svg'); 238 | height: auto; 239 | pointer-events: none; 240 | position: absolute; 241 | width: 1em; 242 | z-index: -1; 243 | } 244 | section blockquote::before { 245 | left: 0; 246 | top: 0; 247 | } 248 | section blockquote::after { 249 | bottom: 0; 250 | right: 0; 251 | transform: rotate(180deg); 252 | } 253 | section blockquote > *:last-child { 254 | margin-bottom: 0; 255 | } 256 | strong { 257 | color: #33b1dd; 258 | } 259 | 260 | em { 261 | color: #6e2142; 262 | font-weight: bold; 263 | font-style: normal; 264 | } 265 | 266 | /* @import url('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/styles/default.min.css'); */ 267 | -------------------------------------------------------------------------------- /slides/ex-polars-lessons-learned.md: -------------------------------------------------------------------------------- 1 | --- 2 | marp: true 3 | title: 'ExPolars/Deneb Lessons Learned' 4 | paginate: false 5 | _paginate: false 6 | theme: uncover 7 | --- 8 | 9 | 10 | 11 | ![bg](images/tubi.png) 12 | ![](#fff) 13 | 14 | ## 15 | ## 16 | ## 17 | ## 18 | ## 19 | ## 20 | ## 21 | ## 22 | 23 | ### ExPolars/Deneb Lessons Learned 24 | 25 | --- 26 | 27 | ## The Vision: Bring the beauty of _pandas_ into Elixir world 28 | 29 | --- 30 | 31 | ## The plan 32 | 33 | - use [polars](https://github.com/ritchie46/polars) for data manipulation 34 | - use [vega-lite](https://vega.github.io/vega-lite/) for data visualization 35 | - use jupyter and IElixir for notebook 36 | 37 | --- 38 | 39 | ## The tools / pre-knowledge 40 | 41 | - basic understanding of rust 42 | - basic understanding how erlang NIF works 43 | - rustler: bridge elixir/rust 44 | - basic understanding how vega-lite works 45 | 46 | --- 47 | 48 | #### First Output 49 | ## ex_polars (pandas alternative) 50 | 51 | --- 52 | 53 | ![bg](images/ex_polars.jpg) 54 | 55 | --- 56 | 57 | #### Second output 58 | ## Deneb (altair alternative) 59 | 60 | --- 61 | 62 | ![bg](images/deneb.png) 63 | 64 | --- 65 | 66 | ![bg](images/deneb1.jpg) 67 | 68 | --- 69 | 70 | ![bg](images/deneb2.jpg) 71 | 72 | --- 73 | 74 | #### Third output 75 | 76 | ## PR to IElixir 77 | 78 | https://github.com/pprzetacznik/IElixir/pull/57 79 | 80 | --- 81 | 82 | ## Meet the brick walls 83 | 84 | > The brick walls aren't there to keep us out, they're there to give us a chance to _show how badly we want something._ 85 | > 86 | > by Randy Pausch 87 | 88 | --- 89 | 90 | 91 | ## Brick wall #1: Rust compiler won't let you DRY! 92 | 93 | ```rust 94 | // the dataframe passed between elixir and rust is a ResourceArc> 95 | // take read lock and process 96 | match data.inner.0.read() { 97 | Ok(df) => deal_with_df, 98 | Err(_) => Err(ExPolarsError.Internal(...)) 99 | } 100 | 101 | // I want to DRY, but this won't work. 102 | def get_reader(*self) -> DataFrame { 103 | match data.inner.0.read() { 104 | Ok(df) => (&*df).as_ref(), 105 | Err(_) => Err(ExPolarsError.Internal(...)) 106 | } 107 | } 108 | 109 | let df = data.inner.0.read().map_err(...)?; // won't work 110 | ``` 111 | 112 | --- 113 | 114 | ## Reason and Solution 115 | 116 | - Reason: `Result, PoisonError>>` is a RAII structure 117 | - you can't access it in one function, and utilize the data in another function 118 | - it didn't implement `sync` so you can't do `map_err` 119 | - Solution: use macros 120 | 121 | ```rust 122 | macro_rules! df_read { 123 | ($data: ident, $df: ident, $body: block) => { 124 | match $data.inner.0.read() { 125 | Ok($df) => $body, 126 | Err(_) => Err(ExPolarsError::Internal(...)), 127 | } 128 | }; 129 | } 130 | ``` 131 | 132 | --- 133 | 134 | 135 | 136 | ![bg](images/solved.webp) 137 | 138 | ## Problem solved 139 | 140 | --- 141 | 142 | ## Brick wall #2: call elixir code in rust 143 | 144 | - `groupby_apply(data: ExDataFrame, by: Vec<&str>, lambda: Fun) -> Result` 145 | - I don't know how to execute a user passed elixir function in rust context 146 | - rustler didn't provide the functionality - yes! OSS-a-thon moment! 147 | - however to build it is not easy: I need to wrap the erlang runtime in rust side 148 | - Solution: add a nice `TODO(tchen)` 149 | 150 | --- 151 | 152 | ## Brick wall #3: I want to export more than 1 modules 153 | 154 | - I built `DataFrame` and `Series`, I want to export it to `Elixir.ExPolars.DataFrame` and `Elixir.ExPolars.Series` 155 | - this is a pretty legitimate ask, right? 156 | - `rustler::init!()` can only run once 157 | - heartbroken moment 158 | - it actually makes sense: an erlang module loads the ".so", you don't want the single ".so" being loaded multiple times by multiple modules 159 | - Solution: workaround it 160 | - export to `Elixir.ExPolars.Native`, and prefix the functions with `df_` and `s_` 161 | - write `Elixir.ExPolars.DataFrame` and `Elixir.ExPolars.Series` to proxy to the native functions 162 | 163 | --- 164 | ## Brick wall #4: Convert data types 165 | 166 | - Problem: I need to pass the data as a list back to elixir 167 | - that involves Arrow type to elixir type conversion 168 | - Not able to find an elegant way during the hackathon, so decided to use JSON 169 | - However Arrow types didn't implement Serialize/Deserialize 170 | - Solution: 171 | - Convert Arrow type to primitive type 172 | - serde_json::to_string() 173 | 174 | --- 175 | 176 | ## Brick wall #5: macro_rules! and procedure_macro problem 177 | 178 | ```rust 179 | macro_rules! impl_cmp { 180 | ($name:ident, $type:ty, $operand:ident) => { 181 | #[rustler::nif] // <- this line will have issue 182 | pub fn $name(data: ExSeries, rhs: $type) -> Result { 183 | let s = &data.inner.0; 184 | Ok(ExSeries::new(s.$operand(rhs).into_series())) 185 | } 186 | }; 187 | } 188 | 189 | impl_cmp!(s_eq_u8, u8, eq); 190 | ``` 191 | 192 | --- 193 | 194 | ## Solution 195 | 196 | ```rust 197 | macro_rules! impl_cmp_u8 { 198 | ($name:ident, $operand:ident) => { 199 | #[rustler::nif] 200 | pub fn $name(data: ExSeries, rhs: u8) -> Result { 201 | let s = &data.inner.0; 202 | Ok(ExSeries::new(s.$operand(rhs).into_series())) 203 | } 204 | }; 205 | } 206 | impl_cmp_u8!(s_eq_u8, eq); 207 | ``` 208 | 209 | --- 210 | 211 | ## Brick wall 6: IElixir charting 212 | 213 | - Reason: 214 | - I built deneb with simple vega-lite support 215 | - I wrote jupyter note book to show the chart 216 | - However charts cannot be shown properly 217 | - Solution: 218 | - Fix IElixir: https://github.com/pprzetacznik/IElixir/pull/57 219 | 220 | --- 221 | 222 | 223 | 224 | # May the _Rust_ be with you! 225 | 226 | ![bg left](images/happy.webp) 227 | -------------------------------------------------------------------------------- /slides/images/deneb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrchen/ex_polars/903c2d173b732eece241a7da07e3b38fc0ed3811/slides/images/deneb.png -------------------------------------------------------------------------------- /slides/images/deneb1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrchen/ex_polars/903c2d173b732eece241a7da07e3b38fc0ed3811/slides/images/deneb1.jpg -------------------------------------------------------------------------------- /slides/images/deneb2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrchen/ex_polars/903c2d173b732eece241a7da07e3b38fc0ed3811/slides/images/deneb2.jpg -------------------------------------------------------------------------------- /slides/images/ex_polars.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrchen/ex_polars/903c2d173b732eece241a7da07e3b38fc0ed3811/slides/images/ex_polars.jpg -------------------------------------------------------------------------------- /slides/images/happy.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrchen/ex_polars/903c2d173b732eece241a7da07e3b38fc0ed3811/slides/images/happy.webp -------------------------------------------------------------------------------- /slides/images/solved.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrchen/ex_polars/903c2d173b732eece241a7da07e3b38fc0ed3811/slides/images/solved.webp -------------------------------------------------------------------------------- /slides/images/tubi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrchen/ex_polars/903c2d173b732eece241a7da07e3b38fc0ed3811/slides/images/tubi.png -------------------------------------------------------------------------------- /test/ex_polars_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ExPolarsTest do 2 | use ExUnit.Case 3 | doctest ExPolars 4 | 5 | test "greets the world" do 6 | assert ExPolars.hello() == :world 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | --------------------------------------------------------------------------------