{"id":277,"date":"2026-03-31T12:36:53","date_gmt":"2026-03-31T04:36:53","guid":{"rendered":"https:\/\/yoyodyne.com.au\/?p=277"},"modified":"2026-03-31T14:26:42","modified_gmt":"2026-03-31T06:26:42","slug":"ucl-v-utl","status":"publish","type":"post","link":"https:\/\/yoyodyne.com.au\/index.php\/2026\/03\/31\/ucl-v-utl\/","title":{"rendered":"UCL v UTL"},"content":{"rendered":"\n<p>This dataset $[0.1, 0.2, 0.05]$ is the sample set used in Hewett, 2006 so we&#8217;re going to use it here too. It perfectly illustrates why the <strong>Upper Tolerance Limit (UTL)<\/strong> (the defensive choice for occupational hygiene), and the <strong>Upper Confidence Limit (UCL)<\/strong> (serves a different purpose than &#8216;most exposed worker in a group&#8217;) both fail when sample sizes are small.<\/p>\n\n\n\n<p>To paraphrase multiple regulators I&#8217;ve spoken to:<\/p>\n\n\n\n<p>&#8220;We are not as interested in the average exposure to a work group as the potentially highest exposure end of the workgroup exposure distribution&#8221;.<\/p>\n\n\n\n<p>This is where the langauge gets loose and terms are used interchangably; specfically <strong>UCL<\/strong> and <strong>UTL<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Core Difference<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>UCL (of the Mean):<\/strong> Estimates where the <strong>average<\/strong> exposure lies, or the limit below which you are confident it sit under.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-text-align-center has-medium-font-size\">NORM.DIST formula: $mean+ 1.645 \\times sd$<br>NORM.DIST formula: $\\bar{x} + 1.645 \\times \\sigma$<\/p>\n\n\n\n<p class=\"has-text-align-center has-medium-font-size\"><\/p>\n\n\n\n<p class=\"has-text-align-center has-medium-font-size\">LOGNORM.DIST: $GM \\times GSD^{1.645}$<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>UTL (95\/95):<\/strong> Estimates the limit where the worst-case (95th percentile) of the worse-case of exposures of the population &#8211; not the sample set- lie with <strong>high confidence.<\/strong><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The $k$-factor for small datasets<\/h2>\n\n\n\n<p class=\"has-large-font-size\">The <strong>$k$-factor<\/strong> is a statistical multiplier used to calculate one-sided tolerance limits (like the 95\/95 UTL) when the true population mean and standard deviation are unknown. Unlike a standard Z-score\u2014which assumes you have perfect knowledge of the entire population\u2014the $k$-factor explicitly accounts for the <strong>sampling error<\/strong> inherent in small datasets. It acts as a &#8220;safety margin&#8221; or uncertainty penalty: because we are estimating the distribution from only a few data points, $k$ must be significantly larger than a Z-score to ensure we maintain our desired confidence level (e.g., 95%) that a specific proportion of the population is actually covered. <\/p>\n\n\n\n<p class=\"has-large-font-size\">As the sample size ($n$) increases and our estimate of the population becomes more reliable, the $k$-factor decreases, eventually converging toward the standard normal quantile ($1.645$ for the 95th percentile) as $n$ approaches infinity.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Comparison of $k$ vs. $z$ (95% Confidence \/ 95% Coverage)<\/h3>\n\n\n\n<figure class=\"wp-block-table has-small-font-size\"><table class=\"has-fixed-layout\"><thead><tr><td><strong>Sample Size (n)<\/strong><\/td><td><strong>k-factor<\/strong><\/td><td><strong>Z-score (z0.95\u200b)<\/strong><\/td><td><strong>The &#8220;Uncertainty Penalty&#8221;<\/strong><\/td><\/tr><\/thead><tbody><tr><td><strong>3<\/strong><\/td><td><strong>7.656<\/strong><\/td><td>1.645<\/td><td>+365%<\/td><\/tr><tr><td><strong>10<\/strong><\/td><td><strong>2.911<\/strong><\/td><td>1.645<\/td><td>+77%<\/td><\/tr><tr><td><strong>30<\/strong><\/td><td><strong>2.220<\/strong><\/td><td>1.645<\/td><td>+35%<\/td><\/tr><tr><td><strong>$\\infty$<\/strong><\/td><td><strong>1.645<\/strong><\/td><td>1.645<\/td><td>0%<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The Worked Example<\/h2>\n\n\n\n<p>With only three data points, the uncertainty is massive. Even though your &#8220;best guess&#8221; (point estimate) for the 95th percentile is low, the statistical safety margin required for 95% confidence is huge.<\/p>\n\n\n\n<figure class=\"wp-block-table has-small-font-size\"><table class=\"has-fixed-layout\"><thead><tr><td><strong>Metric<\/strong><\/td><td><strong>Calculation Logic<\/strong><\/td><td><strong>Result<\/strong><\/td><td><strong>Context<\/strong><\/td><\/tr><\/thead><tbody><tr><td><strong>Point Estimate (95th %ile)<\/strong><\/td><td>$\\exp^{(\\bar{y} + 1.645 \\cdot s_y)}$<\/td><td><strong>0.31<\/strong><\/td><td>&#8220;The most likely 95th percentile.&#8221;<\/td><\/tr><tr><td><strong>UCL95 (of the Mean)<\/strong><\/td><td>Land&#8217;s H-statistic calculation<\/td><td><strong>~2.8<\/strong><\/td><td>&#8220;We are 95% sure the <em>average<\/em> is below 2.8.&#8221;<\/td><\/tr><tr><td><strong>UTL 95\/95<\/strong><\/td><td>$\\exp^{(\\bar{y} + 7.656 \\cdot s_y)}$<\/td><td><strong>20.2<\/strong><\/td><td>&#8220;We are 95% sure 95% of shifts are below 20.2.&#8221;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">How to Calculate It<\/h2>\n\n\n\n<p>The &#8220;jump&#8221; from 0.31 to 20.2 happens because of the <strong>$k$-factor<\/strong>, which penalizes the small sample size ($n=3$).<\/p>\n\n\n\n<p><strong>Log-Transform the data<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\">$\\ln(0.05) = -3.0$, <\/p>\n\n\n\n<p class=\"has-medium-font-size\">$\\ln(0.1) = -2.3$, <\/p>\n\n\n\n<p class=\"has-medium-font-size\">$\\ln(0.2) = -1.6$<\/p>\n\n\n\n<p><strong>Descriptive statistics<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\">$\\bar{y} = -2.3$, $GM = 1.0$<\/p>\n\n\n\n<p class=\"has-medium-font-size\">$s_y = 0.693$, $GSD =  2.00$<\/p>\n\n\n\n<p><strong>Select the K-Factor<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\">Account for n=3. For a 95\/95 limit with 3 samples, use <strong>$k = 7.656$<\/strong>. (For $n=20$, this would drop to ~2.4).<\/p>\n\n\n\n<p><strong>Calculate the Limit<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\">$UTL = \\exp^{(-2.3 + (7.656 \\cdot 0.693))} = \\exp^{(3.0)} \\approx \\mathbf{20.2}$.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">The &#8220;Sample Size Penalty&#8221; Simulator<\/h3>\n\n\n\n<p>You can use this tool to see how increasing your sample size ($n$) collapses the massive gap between your point estimate (0.31) and your defensible 95\/95 limit (20.2).<\/p>\n\n\n\n<div id=\"hygiene-simulator-root\" style=\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; color: #333; max-width: 850px; margin: 20px auto; padding: 25px; border: 1px solid #e1e4e8; border-radius: 12px; background-color: #ffffff; box-shadow: 0 4px 12px rgba(0,0,0,0.08);\">\n\n    <h2 style=\"color: #1a73e8; border-bottom: 2px solid #1a73e8; padding-bottom: 10px; margin-top: 0;\">The 95\/95 Tolerance Simulator<\/h2>\n    \n    <p style=\"margin-bottom: 25px;\">This tool demonstrates the difference between a <strong>Point Estimate<\/strong> (a best guess) and the <strong>95\/95 UTL<\/strong> (the defensible compliance limit). As sample size increases, the gap between these two numbers narrows.<\/p>\n\n    <div style=\"display: flex; gap: 30px; flex-wrap: wrap; background: #f8f9fa; padding: 20px; border-radius: 8px; border: 1px solid #eee;\">\n        \n        <div style=\"flex: 1; min-width: 280px;\">\n            <div style=\"margin-bottom: 20px;\">\n                <label style=\"display: block; font-weight: bold; margin-bottom: 5px;\">Sample Size (n): <span id=\"n-val\" style=\"color: #1a73e8;\">3<\/span><\/label>\n                <input type=\"range\" id=\"n-slider\" min=\"3\" max=\"50\" value=\"3\" style=\"width: 100%; cursor: pointer;\">\n                <small style=\"color: #666;\">Small sets carry a high &#8220;uncertainty penalty.&#8221;<\/small>\n            <\/div>\n\n            <div style=\"margin-bottom: 20px;\">\n                <label style=\"display: block; font-weight: bold; margin-bottom: 5px;\">Geometric Mean (GM): <span id=\"gm-val\" style=\"color: #1a73e8;\">0.1<\/span><\/label>\n                <input type=\"range\" id=\"gm-slider\" min=\"0.01\" max=\"1.0\" step=\"0.01\" value=\"0.1\" style=\"width: 100%; cursor: pointer;\">\n            <\/div>\n\n            <div style=\"margin-bottom: 10px;\">\n                <label style=\"display: block; font-weight: bold; margin-bottom: 5px;\">Geo. Std. Dev (GSD): <span id=\"gsd-val\" style=\"color: #1a73e8;\">2.0<\/span><\/label>\n                <input type=\"range\" id=\"gsd-slider\" min=\"1.1\" max=\"4.0\" step=\"0.1\" value=\"2.0\" style=\"width: 100%; cursor: pointer;\">\n            <\/div>\n        <\/div>\n\n        <div style=\"flex: 1.5; min-width: 300px; display: flex; flex-direction: column; justify-content: center; border-left: 1px solid #ddd; padding-left: 20px;\">\n            <h4 style=\"margin: 0 0 15px 0; font-size: 14px; text-transform: uppercase; color: #666;\">Calculated Exposure Limits<\/h4>\n            \n            <div style=\"margin-bottom: 20px;\">\n                <div style=\"display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 5px;\">\n                    <span>Point Estimate (95th %ile)<\/span>\n                    <strong id=\"point-est-text\">0.31<\/strong>\n                <\/div>\n                <div style=\"background: #e1e4e8; height: 12px; border-radius: 6px;\">\n                    <div id=\"point-bar\" style=\"background: #34a853; width: 1.5%; height: 100%; border-radius: 6px; transition: width 0.3s ease;\"><\/div>\n                <\/div>\n            <\/div>\n\n            <div style=\"margin-bottom: 5px;\">\n                <div style=\"display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 5px;\">\n                    <span style=\"color: #c5221f; font-weight: bold;\">95\/95 Upper Tolerance Limit<\/span>\n                    <strong id=\"utl-text\" style=\"color: #c5221f;\">20.2<\/strong>\n                <\/div>\n                <div style=\"background: #e1e4e8; height: 24px; border-radius: 6px; position: relative;\">\n                    <div id=\"utl-bar\" style=\"background: #ea4335; width: 100%; height: 100%; border-radius: 6px; transition: width 0.3s ease;\"><\/div>\n                    <div style=\"position: absolute; left: 5%; top: 0; height: 100%; width: 2px; background: rgba(0,0,0,0.2);\" title=\"OEL Threshold\"><\/div>\n                <\/div>\n                <small style=\"font-size: 10px; color: #999;\">The red bar shows the &#8220;Defensible Limit.&#8221;<\/small>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div style=\"margin-top: 25px; font-size: 14px; color: #555;\">\n        <p><strong>UCL (Upper Confidence Limit):<\/strong> Used for long-term averages. For the set above, the UCL of the mean is <strong>~2.8<\/strong>. It is lower than the UTL because it measures the group average, not individual extreme shifts.<\/p>\n        <p><strong>UTL (Upper Tolerance Limit):<\/strong> This is the 95\/95 limit. With only 3 samples, the UTL of <strong>20.2<\/strong> is roughly 65 times higher than the point estimate. By increasing your sample size to 20, you&#8217;ll see the UTL &#8220;penalty&#8221; drop dramatically.<\/p>\n    <\/div>\n\n<script>\n    (function() {\n        const nSlider = document.getElementById('n-slider');\n        const gmSlider = document.getElementById('gm-slider');\n        const gsdSlider = document.getElementById('gsd-slider');\n        \n        const nVal = document.getElementById('n-val');\n        const gmVal = document.getElementById('gm-val');\n        const gsdVal = document.getElementById('gsd-val');\n        \n        const pointText = document.getElementById('point-est-text');\n        const utlText = document.getElementById('utl-text');\n        const pointBar = document.getElementById('point-bar');\n        const utlBar = document.getElementById('utl-bar');\n\n        \/\/ EXACT K-FACTORS for 95\/95 (n=3 to 9) from ISO 16269-6\n        const exactK = {\n            3: 7.656, 4: 5.144, 5: 4.203, 6: 3.708, \n            7: 3.399, 8: 3.187, 9: 3.031\n        };\n\n        function update() {\n            const n = parseInt(nSlider.value);\n            const gm = parseFloat(gmSlider.value);\n            const gsd = parseFloat(gsdSlider.value);\n            \n            nVal.innerText = n;\n            gmVal.innerText = gm;\n            gsdVal.innerText = gsd;\n\n            const meanLog = Math.log(gm);\n            const sdLog = Math.log(gsd);\n\n            \/\/ 1. Point Estimate (Z=1.645)\n            const pointEst = Math.exp(meanLog + (1.64485 * sdLog));\n            \n            \/\/ 2. K-factor Calculation\n            let k;\n            if (exactK[n]) {\n                \/\/ Use exact table for small samples (Hewett Accuracy)\n                k = exactK[n];\n            } else {\n                \/\/ Use Natrella Approximation for n >= 10\n                const zp = 1.64485;\n                const zg = 1.64485;\n                const a = 1 - (Math.pow(zg, 2) \/ (2 * (n - 1)));\n                const b = Math.pow(zp, 2) - (Math.pow(zg, 2) \/ n);\n                k = (zp + Math.sqrt(Math.pow(zp, 2) - a * b)) \/ a;\n            }\n\n            const utl = Math.exp(meanLog + (k * sdLog));\n\n            \/\/ Update text\n            pointText.innerText = pointEst.toFixed(2);\n            utlText.innerText = utl.toFixed(2);\n\n            \/\/ Update Visualization Bars \n            \/\/ We scale relative to a \"max\" of 25 to keep the OEL (1.0) visible\n            const maxScale = 25; \n            const pWidth = Math.min((pointEst \/ maxScale) * 100, 100);\n            const uWidth = Math.min((utl \/ maxScale) * 100, 100);\n            \n            pointBar.style.width = pWidth + '%';\n            utlBar.style.width = uWidth + '%';\n        }\n\n        [nSlider, gmSlider, gsdSlider].forEach(s => s.addEventListener('input', update));\n        update();\n    })();\n<\/script>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This dataset $[0.1, 0.2, 0.05]$ is the sample set used in Hewett, 2006 so we&#8217;re going to use it here too. It perfectly illustrates why the Upper Tolerance Limit (UTL) (the defensive choice for occupational hygiene), and the Upper Confidence Limit (UCL) (serves a different purpose than &#8216;most exposed worker in a group&#8217;) both fail [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-277","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/posts\/277","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/comments?post=277"}],"version-history":[{"count":31,"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/posts\/277\/revisions"}],"predecessor-version":[{"id":311,"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/posts\/277\/revisions\/311"}],"wp:attachment":[{"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/media?parent=277"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/categories?post=277"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yoyodyne.com.au\/index.php\/wp-json\/wp\/v2\/tags?post=277"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}