Skip to content

Instantly share code, notes, and snippets.

@maennchen
Created December 3, 2024 13:50
Show Gist options
  • Save maennchen/8fefa25a517b63b61f50065f1862d8bc to your computer and use it in GitHub Desktop.
Save maennchen/8fefa25a517b63b61f50065f1862d8bc to your computer and use it in GitHub Desktop.
Hex Version Stats

Hex Version Stats

Mix.install([
  :hex_core,
  :explorer,
  :kino_explorer,
  :kino_vega_lite
])

for app <- [:hex_core, :inets, :ssl] do
  {:ok, _apps} = Application.ensure_all_started(app)
end

Collect Data / Setup

require Explorer.DataFrame
Explorer.DataFrame
config = :hex_core.default_config()
{:ok, {200, _headers, result}} = :hex_repo.get_versions(config)
[hex_http_httpc] using default ssl options which are insecure.
Configure your adapter with: {hex_http_httpc, #{http_options => [{ssl, SslOpts}]}}
{:ok,
 {200,
  %{
    "accept-ranges" => "bytes",
    "age" => "0",
    "cache-control" => "public, max-age=3600",
    "connection" => "keep-alive",
    "content-length" => "263739",
    "content-type" => "application/octet-stream",
    "date" => "Tue, 03 Dec 2024 13:42:00 GMT",
    "etag" => "\"18929c9d8d5a03dd64fcb862b4003b9c\"",
    "last-modified" => "Tue, 03 Dec 2024 13:29:26 GMT",
    "server" => "AmazonS3",
    "via" => "1.1 varnish",
    "x-amz-id-2" => "wELzuVelxrcTMksGuEjR5Opf50PkjpD0tNbHQLTQ43JIheD6NHxRYvKhMpWGhqIi5YpJhXehpHA=",
    "x-amz-meta-surrogate-control" => "public, max-age=604800",
    "x-amz-meta-surrogate-key" => "registry registry-index",
    "x-amz-request-id" => "QX2AWD7S5R82XEHP",
    "x-amz-server-side-encryption" => "AES256",
    "x-amz-version-id" => "nfz3J9ulMFSB0gE8z7PcaPyKbZ8FF8RI",
    "x-cache" => "MISS",
    "x-cache-hits" => "0",
    "x-served-by" => "cache-vie6345-VIE",
    "x-timer" => "S1733233320.677303,VS0,VE526"
  },
  %{
    packages: [
      %{name: "a11y_audit", versions: ["0.1.0", "0.2.0", "0.2.1", "0.2.2"], retired: []},
      %{name: "a_message", versions: ["1.0.0"], retired: []},
      %{name: "aa", versions: ["0.1.0"], retired: []},
      %{name: "aadya", versions: ["0.1.0"], retired: []},
      %{name: "aasm", versions: ["0.1.0", "0.2.0"], retired: []},
      %{name: "aatree", versions: ["0.1.0"], retired: []},
      %{name: "aba", versions: ["0.1.0", "0.2.0", "0.3.0", "0.4.0"], retired: []},
      %{name: "aba_api", versions: ["1.0.0"], retired: []},
      %{name: "aba_cli", versions: ["1.0.0"], retired: []},
      %{name: "aba_model", versions: ["1.0.0"], retired: []},
      %{
        name: "aba_validator",
        versions: ["0.0.0", "0.1.2", "0.1.4", "1.0.0", "2.0.0", "2.1.0"],
        retired: [0, 1]
      },
      %{
        name: "abac",
        versions: ["0.4.0", "0.10.0", "0.11.0", "0.11.1", "0.11.2", "0.11.3", "0.11.5", "1.7.0",
         "1.7.1", "1.7.2", "1.8.0"],
        retired: []
      },
      %{
        name: "abacus",
        versions: ["0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.3.2", "0.3.3", "0.4.0", "0.4.1", "0.4.2",
         "2.0.0", "2.1.0"],
        retired: []
      },
      %{name: "abacus_sm", versions: ["1.0.0"], retired: []},
      %{name: "abacus_sql", versions: ["2.0.0", "2.1.0", "2.1.1"], retired: []},
      %{name: "abatap", versions: ["0.1.0", "0.2.0"], retired: []},
      %{name: "abbrev", versions: ["0.1.0"], retired: []},
      %{name: "abc", versions: ["0.1.0"], retired: []},
      %{name: "abex", versions: ["0.1.0", "0.1.1", "0.1.2"], retired: []},
      %{
        name: "abi",
        versions: ["0.1.0", "0.1.1", "0.1.2", "0.1.3", "0.1.4", "0.1.5", "0.1.6", "0.1.7", "0.1.8",
         "0.1.9", "0.1.10", "0.1.11", "0.1.12", "0.1.13", "0.1.15", "0.1.16", "0.1.17", "0.1.18",
         "0.1.19", "0.1.20", "0.1.21-alpha1", "0.1.21-alpha2", ...],
        retired: []
      },
      %{
        name: "abit",
        versions: ["0.1.0", "0.1.1", "0.1.2", "0.1.3", "0.1.4", "0.1.5", "0.2.0", "0.2.1", "0.2.2",
         "0.2.3", "0.2.4", "0.3.0", "0.3.1", "0.3.2", "0.3.3"],
        retired: []
      },
      %{name: "abnf", versions: ["0.0.1"], retired: []},
      %{name: "abnf2", versions: ["0.1.2", "0.1.4"], retired: []},
      %{
        name: "abnf_parsec",
        versions: ["0.1.0", "0.1.1", "0.1.2", "0.1.3", "1.0.0", "1.0.1", "1.1.0", "1.2.0", "1.2.1"],
        retired: [4]
      },
      %{name: "abnfc", versions: ["0.5.2", "0.5.4"], retired: []},
      %{
        name: "about",
        versions: ["0.0.1", "0.0.2", "0.0.3", "0.0.4", "0.0.5", "0.0.6", "0.0.7", "0.0.8", "0.0.9",
         "0.0.10", "0.0.11"],
        retired: []
      },
      %{
        name: "absinthe",
        versions: ["0.1.0", "0.2.1", "0.2.2", "0.2.3", "0.4.0", "0.4.1", "0.4.2", "0.4.3", "0.4.4",
         "0.4.5", "0.4.6", "0.5.0", "0.5.1", "0.5.2", "1.0.0", ...],
        retired: ~c"?e"
      },
      %{name: "absinthe_auth", versions: ["0.1.0", "0.1.1", "0.2.0", "0.2.1"], retired: []},
      %{name: "absinthe_cache", versions: ["0.1.0"], retired: []},
      %{name: "absinthe_cache_fairy", versions: ["0.2.0", "0.2.1", "0.2.2", "0.2.3"], retired: []},
      %{name: "absinthe_client", versions: ["0.1.0", "0.1.1"], retired: []},
      %{name: "absinthe_compose", versions: ["0.1.0"], retired: []},
      %{name: "absinthe_conn_test", versions: ["0.0.0", "0.1.0", "0.1.1"], retired: []},
      %{name: "absinthe_constraints", versions: ["0.0.1", "0.1.0", "0.1.1", "0.2.0"], retired: [0]},
      %{name: "absinthe_ecto", versions: ["0.1.0", "0.1.1", "0.1.2", "0.1.3"], retired: []},
      %{
        name: "absinthe_error_payload",
        versions: ["1.0.0", "1.0.1", "1.1.1", "1.1.2", "1.1.3", "1.1.4", ...],
        retired: []
      },
      %{
        name: "absinthe_extra",
        versions: ["0.1.0", "0.1.1", "0.1.2", "0.1.3", "0.1.4", ...],
        retired: []
      },
      %{
        name: "absinthe_federation",
        versions: ["0.1.0", "0.1.1", "0.1.2", "0.1.3", ...],
        retired: []
      },
      %{name: "absinthe_field_telemetry", versions: ["0.1.0", "0.2.0", "0.2.1", ...], retired: []},
      %{name: "absinthe_gen", versions: ["0.1.0", "0.1.1", ...], retired: []},
      %{name: "absinthe_generator", versions: ["0.1.0", ...], retired: []},
      %{name: "absinthe_graphql_ws", versions: [...], ...},
      %{name: "absinthe_helpers", ...},
      %{...},
      ...
    ],
    repository: "hexpm"
  }}}
df = result.packages
|> Explorer.DataFrame.new()
|> Explorer.DataFrame.explode(:versions)
#Explorer.DataFrame<
  Polars[121205 x 3]
  name string ["a11y_audit", "a11y_audit", "a11y_audit", "a11y_audit", "a_message", ...]
  retired list[s64] [[], [], [], [], [], ...]
  versions string ["0.1.0", "0.2.0", "0.2.1", "0.2.2", "1.0.0", ...]
>

Version Count Distribution

summary_df = df
  |> Explorer.DataFrame.group_by(:name)
  |> Explorer.DataFrame.summarise(version_count: Explorer.Series.count(versions))
  |> Explorer.DataFrame.group_by(:version_count)
  |> Explorer.DataFrame.summarise(package_count: Explorer.Series.count(name))
  |> Explorer.DataFrame.sort_by(asc: version_count)
#Explorer.DataFrame<
  Polars[140 x 2]
  version_count u32 [1, 2, 3, 4, 5, ...]
  package_count u32 [4791, 2672, 1803, 1287, 968, ...]
>
VegaLite.new(width: 700, height: 400, title: "Version Count")
|> VegaLite.data_from_values(summary_df, only: ["version_count", "package_count"])
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "version_count", type: :quantitative, scale: [type: :log])
|> VegaLite.encode_field(:y, "package_count", type: :quantitative, scale: [type: :log])
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","data":{"values":[{"package_count":4791,"version_count":1},{"package_count":2672,"version_count":2},{"package_count":1803,"version_count":3},{"package_count":1287,"version_count":4},{"package_count":968,"version_count":5},{"package_count":768,"version_count":6},{"package_count":587,"version_count":7},{"package_count":503,"version_count":8},{"package_count":405,"version_count":9},{"package_count":322,"version_count":10},{"package_count":290,"version_count":11},{"package_count":257,"version_count":12},{"package_count":221,"version_count":13},{"package_count":184,"version_count":14},{"package_count":171,"version_count":15},{"package_count":163,"version_count":16},{"package_count":115,"version_count":17},{"package_count":181,"version_count":18},{"package_count":99,"version_count":19},{"package_count":95,"version_count":20},{"package_count":77,"version_count":21},{"package_count":90,"version_count":22},{"package_count":76,"version_count":23},{"package_count":73,"version_count":24},{"package_count":56,"version_count":25},{"package_count":53,"version_count":26},{"package_count":33,"version_count":27},{"package_count":50,"version_count":28},{"package_count":36,"version_count":29},{"package_count":38,"version_count":30},{"package_count":32,"version_count":31},{"package_count":34,"version_count":32},{"package_count":16,"version_count":33},{"package_count":24,"version_count":34},{"package_count":10,"version_count":35},{"package_count":22,"version_count":36},{"package_count":27,"version_count":37},{"package_count":17,"version_count":38},{"package_count":19,"version_count":39},{"package_count":19,"version_count":40},{"package_count":20,"version_count":41},{"package_count":11,"version_count":42},{"package_count":14,"version_count":43},{"package_count":17,"version_count":44},{"package_count":13,"version_count":45},{"package_count":9,"version_count":46},{"package_count":14,"version_count":47},{"package_count":9,"version_count":48},{"package_count":15,"version_count":49},{"package_count":11,"version_count":50},{"package_count":13,"version_count":51},{"package_count":10,"version_count":52},{"package_count":4,"version_count":53},{"package_count":5,"version_count":54},{"package_count":9,"version_count":55},{"package_count":6,"version_count":56},{"package_count":10,"version_count":57},{"package_count":5,"version_count":58},{"package_count":7,"version_count":59},{"package_count":5,"version_count":60},{"package_count":9,"version_count":61},{"package_count":5,"version_count":62},{"package_count":11,"version_count":63},{"package_count":6,"version_count":64},{"package_count":8,"version_count":65},{"package_count":6,"version_count":66},{"package_count":4,"version_count":67},{"package_count":7,"version_count":68},{"package_count":5,"version_count":69},{"package_count":2,"version_count":70},{"package_count":4,"version_count":71},{"package_count":4,"version_count":72},{"package_count":5,"version_count":73},{"package_count":1,"version_count":74},{"package_count":5,"version_count":75},{"package_count":4,"version_count":76},{"package_count":1,"version_count":77},{"package_count":2,"version_count":78},{"package_count":3,"version_count":79},{"package_count":3,"version_count":80},{"package_count":2,"version_count":81},{"package_count":3,"version_count":82},{"package_count":2,"version_count":83},{"package_count":3,"version_count":84},{"package_count":6,"version_count":86},{"package_count":1,"version_count":87},{"package_count":3,"version_count":88},{"package_count":1,"version_count":89},{"package_count":3,"version_count":90},{"package_count":2,"version_count":92},{"package_count":2,"version_count":93},{"package_count":2,"version_count":96},{"package_count":2,"version_count":97},{"package_count":2,"version_count":98},{"package_count":1,"version_count":99},{"package_count":1,"version_count":100},{"package_count":3,"version_count":101},{"package_count":1,"version_count":102},{"package_count":1,"version_count":103},{"package_count":1,"version_count":105},{"package_count":1,"version_count":106},{"package_count":1,"version_count":107},{"package_count":2,"version_count":109},{"package_count":3,"version_count":110},{"package_count":2,"version_count":111},{"package_count":1,"version_count":112},{"package_count":2,"version_count":113},{"package_count":1,"version_count":115},{"package_count":1,"version_count":116},{"package_count":1,"version_count":119},{"package_count":1,"version_count":120},{"package_count":1,"version_count":123},{"package_count":1,"version_count":125},{"package_count":1,"version_count":127},{"package_count":2,"version_count":129},{"package_count":1,"version_count":130},{"package_count":1,"version_count":134},{"package_count":1,"version_count":136},{"package_count":1,"version_count":137},{"package_count":1,"version_count":138},{"package_count":1,"version_count":147},{"package_count":1,"version_count":148},{"package_count":1,"version_count":150},{"package_count":1,"version_count":151},{"package_count":1,"version_count":154},{"package_count":1,"version_count":162},{"package_count":1,"version_count":163},{"package_count":1,"version_count":165},{"package_count":2,"version_count":168},{"package_count":1,"version_count":178},{"package_count":1,"version_count":183},{"package_count":1,"version_count":192},{"package_count":1,"version_count":196},{"package_count":1,"version_count":201},{"package_count":1,"version_count":215},{"package_count":1,"version_count":258},{"package_count":1,"version_count":272},{"package_count":1,"version_count":288},{"package_count":1,"version_count":341},{"package_count":1,"version_count":744}]},"encoding":{"x":{"field":"version_count","scale":{"type":"log"},"type":"quantitative"},"y":{"field":"package_count","scale":{"type":"log"},"type":"quantitative"}},"height":400,"mark":"line","title":"Version Count","width":700}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment