Skip to content

Commit

Permalink
Supports relocate
Browse files Browse the repository at this point in the history
  • Loading branch information
cristineguadelupe committed Apr 26, 2024
1 parent c02f6ff commit fb16b08
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 17 deletions.
22 changes: 16 additions & 6 deletions lib/kino/explorer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ defmodule Kino.Explorer do

@impl true
def get_data(rows_spec, state) do
{records, total_rows, summaries} = get_records(state, rows_spec)
columns = Enum.map(state.columns, &%{&1 | summary: summaries[&1.key]})
{columns, records, total_rows, summaries} = get_records(state, rows_spec)
columns = Enum.map(columns, &%{&1 | summary: summaries[&1.key]})
data = records_to_data(columns, records)
{:ok, %{columns: columns, data: {:columns, data}, total_rows: total_rows}, state}
end
Expand Down Expand Up @@ -98,21 +98,23 @@ defmodule Kino.Explorer do
defp info(columns, lazy, name) do
name = if lazy, do: "Lazy - #{name}", else: name
has_composite_type_column? = Enum.any?(columns, &(&1.type == "list" || &1.type == "struct"))
features = [:export, :pagination, :sorting, :relocate]

formats =
if has_composite_type_column?, do: ["NDJSON", "Parquet"], else: ["CSV", "NDJSON", "Parquet"]

%{name: name, features: [:export, :pagination, :sorting], export: %{formats: formats}}
%{name: name, features: features, export: %{formats: formats}}
end

defp get_records(%{df: df, groups: groups}, rows_spec) do
lazy = lazy?(df)
df = order_by(df, rows_spec[:order])
df = df |> relocate(rows_spec[:relocates]) |> order_by(rows_spec[:order])
columns = columns(df, lazy, groups)
total_rows = if !lazy, do: DataFrame.n_rows(df)
summaries = if total_rows && total_rows > 0, do: summaries(df, groups)
df = DataFrame.slice(df, rows_spec.offset, rows_spec.limit)
records = df |> DataFrame.collect() |> DataFrame.to_columns()
{records, total_rows, summaries}
{columns, records, total_rows, summaries}
end

defp order_by(df, nil), do: df
Expand All @@ -121,6 +123,14 @@ defmodule Kino.Explorer do
DataFrame.sort_with(df, &[{direction, &1[column]}])
end

defp relocate(df, []), do: df

defp relocate(df, [%{from_index: from_index, to_index: to_index} | relocate]) do
position = if from_index > to_index, do: :before, else: :after
df = DataFrame.relocate(df, from_index, [{position, to_index}])
relocate(df, relocate)
end

defp records_to_data(columns, records) do
Enum.map(columns, fn column ->
records |> Map.fetch!(column.key) |> Enum.map(&value_to_string(column.type, &1))
Expand Down Expand Up @@ -217,6 +227,6 @@ defmodule Kino.Explorer do
defp build_top(top), do: to_string(top)

defp df_to_export(df, rows_spec) do
df |> order_by(rows_spec[:order]) |> DataFrame.collect()
df |> relocate(rows_spec[:relocates]) |> order_by(rows_spec[:order]) |> DataFrame.collect()
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ defmodule KinoExplorer.MixProject do

defp deps do
[
{:kino, github: "/livebook-dev/kino"},
{:kino, github: "livebook-dev/kino"},
{:explorer, "~> 0.8.1"},
{:ex_doc, "~> 0.31.0", only: :dev, runtime: false}
]
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"ex_doc": {:hex, :ex_doc, "0.31.0", "06eb1dfd787445d9cab9a45088405593dd3bb7fe99e097eaa71f37ba80c7a676", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "5350cafa6b7f77bdd107aa2199fe277acf29d739aba5aee7e865fc680c62a110"},
"explorer": {:hex, :explorer, "0.8.1", "0b7300030407a1d9c90096205395f112daa078148f9fc0b5616df30469b4e080", [:mix], [{:adbc, "~> 0.1", [hex: :adbc, repo: "hexpm", optional: true]}, {:aws_signature, "~> 0.3", [hex: :aws_signature, repo: "hexpm", optional: false]}, {:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:fss, "~> 0.1", [hex: :fss, repo: "hexpm", optional: false]}, {:nx, "~> 0.4", [hex: :nx, repo: "hexpm", optional: true]}, {:rustler, "~> 0.31.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}, {:table, "~> 0.1.2", [hex: :table, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1 or ~> 4.0.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "4982756e2d1a1ee52a4acc913800a522b7b14ccb43801ed05d839e531724b798"},
"fss": {:hex, :fss, "0.1.1", "9db2344dbbb5d555ce442ac7c2f82dd975b605b50d169314a20f08ed21e08642", [:mix], [], "hexpm", "78ad5955c7919c3764065b21144913df7515d52e228c09427a004afe9c1a16b0"},
"kino": {:git, "https://github.com//livebook-dev/kino.git", "b3f67b036ce76e81794e435259f337b364920efb", []},
"kino": {:git, "https://github.com/livebook-dev/kino.git", "baaa84a76b0440f7a2b8c9e77f806ce161a65f71", []},
"makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.5", "e0ff5a7c708dda34311f7522a8758e23bfcd7d8d8068dc312b5eb41c6fd76eba", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "94d2e986428585a21516d7d7149781480013c56e30c6a233534bedf38867a59a"},
Expand Down
40 changes: 31 additions & 9 deletions test/kino/explorer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ defmodule Kino.ExplorerTest do
data = connect(widget)

assert %{
features: [:export, :pagination, :sorting],
features: [:export, :pagination, :sorting, :relocate],
content: %{
columns: [
%{key: "0", label: "id", type: "number"},
Expand Down Expand Up @@ -121,6 +121,28 @@ defmodule Kino.ExplorerTest do
})
end

test "supports relocate" do
widget = Kino.Explorer.new(people_df())

connect(widget)

push_event(widget, "relocate", %{"from_index" => 1, "to_index" => 0})

assert_broadcast_event(widget, "update_content", %{
columns: [
%{key: "1", label: "name", type: "text"},
%{key: "0", label: "id", type: "number"},
%{key: "2", label: "start", type: "date"}
],
data: [
["Amy Santiago", "Jake Peralta", "Terry Jeffords"],
["3", "1", "2"],
["2023-12-12 12:12:12.121212", "2023-12-01 02:03:04.050607", "2023-11-11 11:11:11.111111"]
],
relocates: [%{from_index: 1, to_index: 0}]
})
end

test "supports data summary" do
df =
Explorer.DataFrame.new(%{
Expand Down Expand Up @@ -337,7 +359,7 @@ defmodule Kino.ExplorerTest do
data = connect(widget)

assert %{
features: [:export, :pagination, :sorting],
features: [:export, :pagination, :sorting, :relocate],
content: %{
columns: [
%{key: "0", label: "sepal_length", summary: nil, type: "number"},
Expand All @@ -359,7 +381,7 @@ defmodule Kino.ExplorerTest do
data = connect(widget)

assert %{
features: [:export, :pagination, :sorting],
features: [:export, :pagination, :sorting, :relocate],
content: %{
data: [["1", "2"], ["nx", "<<200, 210>>"]]
}
Expand All @@ -372,7 +394,7 @@ defmodule Kino.ExplorerTest do
data = connect(widget)

assert %{
features: [:export, :pagination, :sorting],
features: [:export, :pagination, :sorting, :relocate],
content: %{
total_rows: nil,
columns: [
Expand Down Expand Up @@ -420,7 +442,7 @@ defmodule Kino.ExplorerTest do

assert %{
export: %{formats: ["CSV", "NDJSON", "Parquet"]},
features: [:export, :pagination, :sorting],
features: [:export, :pagination, :sorting, :relocate],
content: %{
page: 1,
max_page: 3,
Expand All @@ -445,7 +467,7 @@ defmodule Kino.ExplorerTest do

assert %{
export: %{formats: ["CSV", "NDJSON", "Parquet"]},
features: [:export, :pagination, :sorting],
features: [:export, :pagination, :sorting, :relocate],
content: %{
page: 1,
max_page: nil,
Expand All @@ -464,7 +486,7 @@ defmodule Kino.ExplorerTest do

test "export to" do
df = Explorer.DataFrame.new(%{n: Enum.to_list(1..25)})
rows_spec = %{order: nil}
rows_spec = %{order: nil, relocates: []}

for format <- ["CSV", "NDJSON", "Parquet"] do
exported = Kino.Explorer.export_data(rows_spec, %{df: df}, format)
Expand All @@ -475,7 +497,7 @@ defmodule Kino.ExplorerTest do

test "export to for lazy data frames" do
df = Explorer.DataFrame.new(%{n: Enum.to_list(1..25)}, lazy: true)
rows_spec = %{order: nil}
rows_spec = %{order: nil, relocates: []}

for format <- ["CSV", "NDJSON", "Parquet"] do
exported = Kino.Explorer.export_data(rows_spec, %{df: df}, format)
Expand All @@ -486,7 +508,7 @@ defmodule Kino.ExplorerTest do

test "export to for data frames with list-type columns" do
df = Explorer.DataFrame.new(%{list: Explorer.Series.from_list([[1, 2], [1]])})
rows_spec = %{order: nil}
rows_spec = %{order: nil, relocates: []}

widget = Kino.Explorer.new(df)
data = connect(widget)
Expand Down

0 comments on commit fb16b08

Please sign in to comment.