Skip to main content

lib/statwise/visualization/rank_plot.ex

defmodule Statwise.Visualization.RankPlot do
  @moduledoc false

  alias Statwise.Nonparametric.Rank
  alias Statwise.Visualization.{Data, Plot}

  def new(x, y, opts \\ []) do
    x_values =
      x
      |> Data.values([])
      |> Data.ensure_non_empty!("x")

    y_values =
      y
      |> Data.values([])
      |> Data.ensure_non_empty!("y")

    x_label = Keyword.get(opts, :x_label, "x")
    y_label = Keyword.get(opts, :y_label, "y")
    ranks = Rank.ranks(x_values ++ y_values)

    rows =
      rows(x_label, x_values, Enum.take(ranks, length(x_values))) ++
        rows(y_label, y_values, Enum.drop(ranks, length(x_values)))

    %Plot{
      type: :rank_plot,
      data: rows,
      title: Keyword.get(opts, :title),
      x: %{
        field: :value,
        type: :quantitative,
        title: Keyword.get(opts, :x_title, "Value")
      },
      y: %{
        field: :rank,
        type: :quantitative,
        title: Keyword.get(opts, :y_title, "Rank")
      },
      series: %{
        field: :group,
        type: :nominal,
        title: Keyword.get(opts, :series_title, "Group")
      },
      options: opts
    }
  end

  defp rows(label, values, ranks) do
    values
    |> Enum.zip(ranks)
    |> Enum.map(fn {value, rank} -> %{group: Data.to_label(label), value: value, rank: rank} end)
  end
end