├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── component.json ├── index.js ├── package.json └── test └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store* 3 | *.log 4 | *.gz 5 | 6 | node_modules 7 | coverage 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | node_js: 2 | - "0.6" 3 | - "0.8" 4 | - "0.10" 5 | - "0.11" 6 | language: node_js 7 | script: "npm run-script test-travis" 8 | after_script: "npm install coveralls@2 && cat ./coverage/lcov.info | coveralls" 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jonathan Ong me@jongleberry.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wilson Score [![Build Status](https://travis-ci.org/math-utils/wilson-score.png)](https://travis-ci.org/math-utils/wilson-score) 2 | 3 | Calculates the lower bound of the [binomial proportion confidence interval](http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval) as calculated by the [Wilson score interval](http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval). 4 | If you're not retarded, you would use this score instead of averages when sorting and ranking (doesn't matter what the user sees). 5 | This is what [reddit uses](http://amix.dk/blog/post/19588) for "best". 6 | 7 | ## API 8 | 9 | ```js 10 | var wilson = require('wilson-score') 11 | ``` 12 | 13 | ### wilson(up, total [, z-score]) 14 | 15 | - `up` - the total number of "yes"s 16 | - `total` - the total number of votes 17 | - `z-score` - the z-score of the interval. 18 | By default, it's ~2.3 which corresponds to a 99% confidence interval. 19 | Use `1.644853` for 95%. 20 | 21 | Instead of calculating the average as `up / total`, 22 | calculate the wilson score via `wilson(up, total)`. 23 | The wilson score will always be lower than the average. 24 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wilson-score", 3 | "description": "Because averages suck", 4 | "version": "0.0.2", 5 | "license": "MIT", 6 | "scripts": [ 7 | "index.js" 8 | ], 9 | "main": "index.js", 10 | "repo": "math-utils/wilson-score" 11 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = function (up, total, z) { 2 | // http://amix.dk/blog/post/19588 3 | // 95% = 1.644853 4 | // 99% = 2.326348 5 | z = z || 2.326348 6 | if (total <= 0 || total < up) return 0 7 | 8 | var phat = up/total, z2 = z*z; 9 | return (phat + z2/(2*total) - z*Math.sqrt((phat*(1 - phat) + z2/(4*total))/total))/(1 + z2/total) 10 | } 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wilson-score", 3 | "description": "Because averages suck", 4 | "version": "1.0.0", 5 | "author": { 6 | "name": "Jonathan Ong", 7 | "email": "me@jongleberry.com", 8 | "url": "http://jongleberry.com", 9 | "twitter": "https://twitter.com/jongleberry" 10 | }, 11 | "license": "MIT", 12 | "repository": "math-utils/wilson-score", 13 | "devDependencies": { 14 | "mocha": "2", 15 | "istanbul": "0" 16 | }, 17 | "scripts": { 18 | "test": "mocha --reporter spec", 19 | "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot", 20 | "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter dot" 21 | }, 22 | "keywords": [ 23 | "wilson", 24 | "score", 25 | "average" 26 | ], 27 | "files": [ 28 | "index.js" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | 3 | var wilson = require('..') 4 | 5 | describe('Wilson Score', function () { 6 | it('should be lower than the average', function () { 7 | assert.ok(wilson(3, 5) < 3 / 5) 8 | }) 9 | 10 | it('should be 0 if there are no ups', function () { 11 | assert.equal(wilson(0, 100), 0) 12 | }) 13 | }) 14 | --------------------------------------------------------------------------------