Created
December 1, 2019 18:35
-
-
Save jonmagic/f36540424f7618118041411e435a6e72 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Reputation | |
class Error < StandardError; end | |
def initialize(sample_size:, not_spammy_sample_size:) | |
@sample_size = sample_size | |
@not_spammy_sample_size = not_spammy_sample_size | |
end | |
attr_reader :sample_size | |
attr_reader :not_spammy_sample_size | |
def spammy_sample_size | |
sample_size - not_spammy_sample_size | |
end | |
def reputation | |
calculations[0] | |
end | |
def reputation_lower_bound | |
calculations[2].round(4) | |
end | |
def plus_minus | |
calculations[1] | |
end | |
def minimum_reputation | |
minimum_reputation = reputation - plus_minus | |
minimum_reputation < 0 ? 0.0 : minimum_reputation | |
end | |
def maximum_reputation | |
maximum_reputation = reputation + plus_minus | |
maximum_reputation > 1 ? 1.0 : maximum_reputation | |
end | |
# Models reputation as the estimated proportion of good items to all items, | |
# with a 95% confidence interval, using the normal approximation interval. | |
# It returns two values: the estimated reputation and the interval | |
# at 95% confidence. See http://bit.ly/2yD5TvJ for more details. | |
private def calculations | |
@calculations ||= begin | |
raise Error.new("sample_size must be ≥ 0") unless sample_size > 0 | |
raise Error.new("not_spammy_sample_size must be ≥ 0") unless not_spammy_sample_size >= 0 | |
raise Error.new("sample_size must be ≥ not_spammy_sample_size") unless sample_size >= not_spammy_sample_size | |
p_hat = not_spammy_sample_size.to_f / sample_size # p̂ -- estimated proportion | |
z_score = 1.95996 # z-score for 95% confidence | |
z_squared = z_score * z_score | |
plus_minus = z_score * Math.sqrt((p_hat * (1.0 - p_hat)) / sample_size) | |
lower_bound = ((2 * sample_size * p_hat) + z_squared - (z_score * Math.sqrt(z_squared + (4 * sample_size * p_hat * (1.0 - p_hat))))) / (2 * (sample_size + z_squared)) | |
[p_hat, plus_minus, lower_bound] | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment