Popup YouTube Video
Sheerpower Logo

Cluster and Traditional Array Statistics


The Sheerpower Statistics Package

Sheerpower has 48 statistical functions built in, all named stats$something. Each one takes a set of numbers and gives back one answer: stats$mean(scores) is the average of the scores, stats$max(scores) the biggest one, stats$stddev(scores) how spread out they are. You never write the loop.

The set of numbers can be a plain array (dim scores(*)) or a column of a cluster (sales->amount) — every function accepts either, and an array expression works too. The arithmetic is Sheerpower's exact 256-bit decimal, so a total is a total, not a floating-point approximation. When there is no answer — an empty array, say — the function raises a catchable exception rather than handing you a misleading 0.

Start Here: Statistics on a Plain Array

Eight test scores. Put them in an array and ask questions:

dim scores(*) fill scores with 72, 85, 90, 64, 58, 95, 78, 81 print 'mean '; stats$mean(scores) print 'median '; stats$median(scores) print 'highest '; stats$max(scores); ' lowest '; stats$min(scores) print 'spread '; stats$stddev(scores)
mean 77.875 median 79.5 highest 95 lowest 58 spread 12.6653351430475098

Counting is a sum. A comparison on a whole array gives 1 where it is true and 0 where it is not, so adding those up counts them:

print 'passed '; stats$sum(scores >= 60); ' of '; size(scores) print '90th pct '; stats$percentile(scores, 90) print 'above mean '; filter(scores, scores > stats$mean(scores))
passed 7 of 8 90th pct 91.5 above mean 85, 90, 95, 78, 81

Two arrays, one question. Do hours of study go with higher scores? Pair a second array with the first — same number of elements, matched position by position:

dim hours(*) fill hours with 4, 6, 8, 3, 2, 9, 5, 6 print 'correlation '; stats$pcorr(hours, scores) print 'slope '; stats$linreg(hours, scores); ' intercept '; _real
correlation .98475809258555 slope 5.225705329153605 intercept 49.7868338557993731

A correlation of .98 is about as strong as they come; the regression says each extra hour is worth about 5.2 points, starting from about 50. (Functions that have two answers return the first and leave the second in _real.)

Strings have numbers in them too. A string array is not a set of numbers — but len() of a string array is one number per name, and a pipeline reads left to right: the names, their lengths, the largest length. sortindex() then says which name that was:

dim names$(*) fill names$ with 'apples', 'pears', 'blueberrys', 'oranges' print 'Longest name len: '; names$ |> len() |> stats$max() dim by_len$(*) by_len$ = names$[sortindex(len(names$), descending: true)] print 'Longest name: '; by_len$(1) print 'mean length: '; names$ |> len() |> stats$mean() print 'shortest: '; filter(names$, len(names$) = stats$min(len(names$)))
Longest name len: 10 Longest name: blueberrys mean length: 7 shortest: pears

A thousand dice. fill evaluates its value for every element, so 1000 of rnd(6) is a thousand separate rolls:

dim dice(*) set seed 42 fill dice with 1000 of rnd(6) print 'mean of 1000 rolls '; stats$mean(dice) print 'sixes '; stats$sum(dice = 6) print 'mode '; stats$mode(dice)
mean of 1000 rolls 3.55 sixes 178 mode 4

The mean of a fair die is 3.5 and a sixth of 1000 is 167, so 3.55 and 178 are what chance looks like. (Drop the set seed line for different rolls each run.)

Any shape is one population. A two-dimensional array is walked cell by cell, so a grid needs no flattening:

dim grid(3, 4) fill grid with seq(1, 12) print 'sum of all cells '; stats$sum(grid) print 'mean of all cells '; stats$mean(grid)
sum of all cells 78 mean of all cells 6.5

No data, no answer. An empty array has no mean, and the function says so — catch it if the array might be empty:

dim none(*) when exception in m = stats$mean(none) use print 'empty array: '; extext$ end when
empty array: No statistic exists for this data

Everything above works the same way on a cluster column: write sales->amount where the examples write scores. The reference section below does exactly that.

About the reference examples: from “Statistical Functions Overview” on, the examples use a cluster named sample with two fields, value1 (100 rows, 1 to 100) and value2 (100 to 1). The functions run at in-memory speed; with enough RAM a cluster of a billion rows is fine.

Statistics on a subset: every function accepts the named option collected: true, which computes over the current collection — exactly the rows a for each would visit — so a collect with include filters is all it takes to analyze a subset (next section). For a subset that must outlive the collection, copy the rows to their own cluster: see Copy Cluster.

Error handling: a function that cannot produce an answer raises a catchable exception instead of returning 0 — 0 is an ordinary statistic (a mean of 0, a covariance of 0) and could never reliably mean “no data”. Two exception types:

  • exceptiontype("msg_nostatistic") (-4107) — the data admits no answer: an empty set, too few rows, a zero variance where one is divided by, a zero mean under stats$cv, non-positive values under stats$gmean / stats$hmean.
  • exceptiontype("msg_num_outofrange") (-4106) — an argument the function cannot use, such as a percentile outside 0–100.

Three cases still return 0 because there 0 is the answer: stats$cdf(0, df), stats$fcdf(0, df1, df2), and stats$gmean of a set that contains a 0.

Precision: 37 of the 48 functions compute exactly on the 256-bit REAL arithmetic. The eleven that need a transcendental reach their answer through C doubles: cagr (pow), gmean (exp/log), cdf and fcdf (lgamma), ncdf (erf), tcdf (incomplete beta), ks_test (erf); chi2, ftest, ttest and ttest_paired compute their statistic exactly and use a double only for the p-value.


Statistics over a Collection

Every statistical function accepts the named option collected: true: the function then computes over the current collection — exactly the rows a for each would visit — instead of every row in the cluster. Like every optional setting of a built-in function, it is written by name after the positional arguments, with a colon (a plain name = value argument stays a comparison). Filter with collect, then ask for the statistics of what you kept:

collect cluster sales include sales->region$ = 'east' end collect print 'east rows: '; _extracted print 'east total: '; stats$sum(sales->amount, collected: true) print 'east mean: '; stats$mean(sales->amount, collected: true) print 'east median: '; stats$median(sales->amount, collected: true) print 'all total: '; stats$sum(sales->amount)

The output (from a five-row cluster where three rows are 'east'):

east rows: 3 east total: 4500 east mean: 1500 east median: 1500 all total: 5250

Without the option (or with collected: false) the function processes every row of the cluster, exactly as before. The option composes with everything a collection can express: an include-filtered subset, the duplicate groups kept by groupmin, or the survivors of a fuzzy scoring model — if a for each would see it, the statistics see it.

Rules worth knowing:

  • Being named, collected: true goes last and needs no placeholders for the optional arguments before it: stats$stddev(c->v, collected: true) is the sample form over the collection; stats$stddev(c->v, 1, collected: true) the population form. (The older positional spelling — stats$stddev(c->v, population, true) — still works.)
  • Using the flag before any collect/extract has been done raises the same catchable NEVER_EXTRACTED exception a for each would.
  • Two-field functions (pcorr, cov, ttest, ttest_paired, chi2, linreg, linreg_r2, spearman, ftest, weighted_mean) require both fields from the same cluster when the flag is used — two different collections have no coherent row pairing. Mixing clusters raises a catchable STATSTWOCLUSTERS exception (−4115).
  • For stats$zscore(field, row, collected: true) and stats$rank(field, row, collected: true) the row argument is still an ordinary cluster row — the flag chooses the population the score or rank is measured against.
  • stats$max and stats$min with two arguments are the scalar forms (stats$max(a, b)); stats$max(c->v, collected: true) is the collection form (positionally that was stats$max(c->v, 0, true), the middle argument ignored).
  • stats$cdf, stats$fcdf, stats$ncdf, and stats$tcdf operate on plain values, not cluster rows, so they take no flag.

Statistical Functions Overview

Below is a detailed table of the statistical functions available in the Sheerpower Statistics Package, including when to use them, example scenarios, returned values, and actionable decisions based on the results.

(Show/Hide Functions Table)
(Show/Hide Scenarios)

Summary: The Sheerpower Statistics Package

With sample->value1 and sample->value2 as example data sources, the Sheerpower Statistics Package analyzes trends, variability, and relationships in contexts like finance, manufacturing, and science. Decisions turn on whether values meet targets (e.g., stats$mean, stats$cagr), indicate risk (stats$vrisk, stats$sharpe), or suggest relationships (stats$cov, stats$pcorr)—guiding actions from resource allocation to strategic shifts.

Key Features:

  • Comprehensive Analysis: From basic stats (stats$mean, stats$median) to advanced metrics (stats$kurtosis, stats$spearman).
  • Decision Support: Practical examples and decision points for real-world applications.
  • Performance: Optimized for large datasets, using Sheerpower's cluster efficiency.

The Sheerpower Statistics Package empowers users to turn raw data into actionable insights with ease and precision.

(Show/Hide Sheerpower Cluster Statistics Takeaways)
Hide Description

    

       


      

Enter or modify the code below, and then click on RUN

Looking for the full power of Sheerpower?
Check out the Sheerpower website. Free to download. Free to use.