Replace percentile-tables with histograms
John Smith

John Smith commited on 2023-42 13:17:08
Showing 1 changed files, with 28 additions and 34 deletions.


The "s" option now displays detailed histograms in place of
the percentile-tables previously used.
... ...
@@ -140,19 +140,31 @@ local function badness(pr)
140 140
 end
141 141
 
142 142
 --[[
143
-    show list of selected percentile-samples into a list,
144
-    with each entry modulated by the given function
143
+    generate and return text-based vertical histogram,
144
+    with bins of given width across interval from max to min,
145
+    transforming values to numbers via func,
146
+    scaling bar-length by scale
145 147
 ]]
146
-local function showpctiles(list, pctiles, func, name)
147
-    local s = "%ile"
148
-    for _, v in ipairs(pctiles) do
149
-        s = string.format("%s\t%.1f", s, 100 * v)
148
+local function histogram(list, min, max, width, func, scale)
149
+    local bins = {}
150
+    local oorc = 0
151
+    local prc = 0
152
+    for _, v in ipairs(list) do
153
+        local n = func(v)
154
+        if n == n and n >= min and n < max + width then
155
+            local k = math.floor((n - min) / width) + 1
156
+            bins[k] = (bins[k] or 0) + 1
157
+        else
158
+            oorc = oorc + 1
159
+        end
160
+        prc = prc + 1
150 161
     end
151
-    s = s .. "\n" .. name
152
-    for _, v in ipairs(pctiles) do
153
-        s = s .. "\t" .. func(list[math.ceil(v * #list)])
162
+    local s = ""
163
+    for n = min, max, width do
164
+        local k = math.floor((n - min) / width) + 1
165
+        s = string.format("%s%.2f\t%s %d\n", s, n, ("\u{2588}"):rep(math.ceil(scale * (bins[k] or 0))), bins[k] or 0)
154 166
     end
155
-    return s .. "\n"
167
+    return s .. string.format("(%d out of range)\n", oorc)
156 168
 end
157 169
 
158 170
 local actions = {
... ...
@@ -396,30 +408,12 @@ local actions = {
396 408
                 "(average %.2f reviews per prompt), overall retention %.2f%%.\n",
397 409
                 (tsc + tfc) / #expdeck, 100 * tsc / (tsc + tfc)
398 410
             ))
399
-            table.sort(expdeck, function(a, b) return a.ease < b.ease end)
400
-            io.write("\n" .. showpctiles(expdeck, { 0.01, 0.05, 0.1, 0.25, 0.5, 0.8, 0.95 }, function(pr)
401
-                return string.format("%.2f", pr.ease)
402
-            end, "Ease"))
403
-            table.sort(expdeck, function(a, b) return a.delay > 0 and a.delay < b.delay end)
404
-            io.write("\n" .. showpctiles(expdeck, { 0.01, 0.05, 0.2, 0.5, 0.8, 0.95, 0.99 }, function(pr)
405
-                return disptime(pr.delay)
406
-            end, "Delay"))
407
-            table.sort(expdeck, function(a, b) return a:retention() < b:retention() end)
408
-            io.write("\n" .. showpctiles(expdeck, { 0.01, 0.05, 0.1, 0.15, 0.2, 0.25, 0.4 }, function(pr)
409
-                return math.floor(100 * pr:retention())
410
-            end, "Ret. %"))
411
-            table.sort(expdeck, function(a, b) return a.succ + a.fail < b.succ + b.fail end)
412
-            io.write("\n" .. showpctiles(expdeck, { 0.25, 0.5, 0.7, 0.85, 0.95, 0.99, 0.998 }, function(pr)
413
-                return pr.succ + pr.fail
414
-            end, "Reviews"))
415
-            table.sort(expdeck, function(a, b) return (a.created or 99^98) > (b.created or 99^99) end)
416
-            io.write("\n" .. showpctiles(expdeck, { 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99 }, function(pr)
417
-                return disptime(os.time() - pr.created)
418
-            end, "Age"))
419
-            table.sort(deck, function(a, b) return #a < #b end)
420
-            io.write("\n" .. showpctiles(deck, { 0.2, 0.5, 0.8, 0.95, 0.99, 0.998 }, function(card)
421
-                return #card
422
-            end, "Prompts"))
411
+            io.write("\nEase\n" .. histogram(expdeck, 1.0, 3.3, 0.1, function(pr) return pr.ease end, 0.03))
412
+            io.write("\nLog2-delay (seconds)\n" .. histogram(expdeck, 15, 28, 0.5, function(pr) return math.log(pr.delay, 2) end, 0.1))
413
+            io.write("\nRetention (%)\n" .. histogram(expdeck, 30, 100, 10, function(pr) return 100 * pr:retention() end, 0.02))
414
+            io.write("\nReview counts\n" .. histogram(expdeck, 0, 20, 2, function(pr) return pr.succ + pr.fail end, 0.03))
415
+            io.write("\nLog2-age (seconds)\n" .. histogram(expdeck, 18, 28, 0.5, function(pr) return math.log(os.time() - (pr.created or 2 * os.time()), 2) end, 0.05))
416
+            io.write("\nPrompt-count\n" .. histogram(deck, 1, 10, 1, function(card) return #card end, 0.03))
423 417
             table.sort(expdeck, function(a, b) return a.time + a.delay < b.time + b.delay end)
424 418
             io.write("\nUpcoming due prompts wrt days from now:\n")
425 419
             local ppi = 1
426 420