Last active
June 25, 2021 10:22
-
-
Save mattm/d6fbf9dfd339d77a0a85 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
setClass( | |
Class = "Distribution", | |
representation = representation( | |
name = "character", | |
participants = "numeric", | |
conversions = "numeric", | |
sample_proportion = "numeric", | |
se = "numeric", | |
color = "character", | |
x = "vector", | |
y = "vector" | |
) | |
) | |
# We rewrite the initialize method for Distribution objects so that we can | |
# set the x and y values which are used throughout the plotting process | |
setMethod( | |
f = "initialize", | |
signature = "Distribution", | |
definition = function( .Object, name, participants, conversions, color ) { | |
.Object@name = name | |
.Object@sample_proportion = conversions / participants | |
.Object@se = sqrt( ( .Object@sample_proportion * ( 1 - .Object@sample_proportion ) ) / participants ) | |
.Object@color = color | |
.Object@x = seq( -4, 4, length = 100 ) * .Object@se + .Object@sample_proportion | |
.Object@y = dnorm( .Object@x, .Object@sample_proportion, .Object@se ) | |
return ( .Object ) | |
} | |
) | |
# Given a list of distributions, this returns a list of the x and y axis range | |
get_axis_ranges = function( distributions ) { | |
x_all = vector() | |
y_all = vector() | |
for ( distribution in distributions ) { | |
x_all = c( x_all, distribution@x ) | |
y_all = c( y_all, distribution@y ) | |
} | |
xlim = c( min( x_all ), max( x_all ) ) | |
ylim = c( min( y_all ), max( y_all ) ) | |
# Note that by forming a list of the vectors, the vectors get converted to lists | |
# which we then have to convert back to vectors in order to use them for plotting | |
return ( list( xlim, ylim ) ) | |
} | |
get_x_axis_values = function( x_range ) { | |
by = 0.01 | |
min_x = floor( min( x_range ) / by ) * by | |
max_x = ceiling( max( x_range ) / by ) * by | |
return ( seq( min_x, max_x, by = by ) ) | |
} | |
# Define the distributions that we want to plot | |
distributions = list( | |
new( Class = "Distribution", name = "original", participants = 250, conversions = 40, color = "#00cc00" ), | |
new( Class = "Distribution", name = "variation", participants = 270, conversions = 60, color = "blue" ) | |
) | |
# Determine the range to use for each axis | |
axis_range = get_axis_ranges( distributions ) | |
xlim = axis_range[[ 1 ]] | |
ylim = axis_range[[ 2 ]] | |
# Create the plot | |
plot( NULL, NULL, type = "n", xlim = xlim, ylim = ylim, xlab = "Conversion Rate", ylab = "", main = "", axes = FALSE ) | |
# Render each of the curves | |
line_width = 3 | |
for ( distribution in distributions ) { | |
polygon( distribution@x, distribution@y, col = adjustcolor( distribution@color, alpha.f = 0.3 ), border = NA ) | |
lines( distribution@x, distribution@y, col = adjustcolor( distribution@color, alpha.f = 1 ), lwd = line_width ) | |
# Draw a line down the center of the curve | |
ci_center_y = dnorm( distribution@sample_proportion, distribution@sample_proportion, distribution@se ) | |
coords = xy.coords( c( distribution@sample_proportion, distribution@sample_proportion ), c( 0, ci_center_y ) ) | |
lines( coords, col = adjustcolor( distribution@color, alpha.f = 0.4 ), lwd = 1 ) | |
} | |
# Render the x axis | |
axis( side = 1, at = get_x_axis_values( xlim ), pos = 0, col = "#777777", col.axis = "#777777", lwd = line_width ) | |
# Finally, render a legend | |
legend_text = vector() | |
legend_colors = vector() | |
for ( distribution in distributions ) { | |
legend_text = c( legend_text, distribution@name ) | |
legend_colors = c( legend_colors, distribution@color ) | |
} | |
legend('right', legend_text, lty = 1, lwd = line_width, col = legend_colors, bty = 'n' ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment