Skip to content

Instantly share code, notes, and snippets.

@ribsy
Created April 19, 2022 01:44
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ribsy/76bfff5897322450819d8d0e0ad143ea to your computer and use it in GitHub Desktop.
Save ribsy/76bfff5897322450819d8d0e0ad143ea to your computer and use it in GitHub Desktop.
source("manifesto_functions.R")
##################
### Get Small Data
#Engineer One and Two Remediation Rate Beliefs
eng_one <- c(4,7) #Median and 90% Stretch
eng_two <- c(2,4)
# 4 fix, 7 stretch fix, out of 10
GetBeliefsHits(eng_one[1], eng_one[2],10)
MakeBetaGraph(1.96,2.78,"Vuln Fix Rate","Plausibility",
"Sec Eng Beliefs","4 Fix, 7 Max, out of 10")
# 2 Fixes, 4 Stretch Fixes, out of 10
GetBeliefsHits(eng_two[1], eng_two[2],10)
MakeBetaGraph(2.07,7.32,"Vuln Fix Rate","Plausibility",
"Sec Eng 2's Beliefs","2 Fix, 4 Max, out of 10")
### Data Functions for MakeBetaGraph() ###
# Generate prior distribution data using SME shape parameters
prior <- distribution_beta(1000,2.07,7.32)
# Look at first 20 results
head(prior, 20)
# Get 89% Credible Interval
ci(prior, method="HDI")
# Add density for graphing
prior <- prior %>% estimate_density()
# Print out some results
head(prior, 5)
#############################
### Scoring Beliefs With Data
opened_dates <- c("2020-07-25","2020-08-01","2020-08-03","2020-08-03",
"2020-08-03","2020-08-05","2020-08-05","2020-08-30",
"2020-09-12","2020-09-20","2020-09-23")
closed_dates <- c("2020-07-29","2020-08-05","2020-08-06","2020-08-06",
"2020-09-03","2020-09-13","2020-09-25")
#Get Shape Parameters For Each Engineer
eng_one <- GetBeliefsHits(4,7,10)
eng_two <- GetBeliefsHits(2,4,10)
#Get counts of opened and closed dates and their delta
opened <- length(opened_dates)
closed <- length(closed_dates)
delta <- opened - closed
# Compare each engineer's belief to the vulnerability data – no bias
raw_score <- ScoreBetaBeliefs(bias = c(.5,.5), first_belief = eng_one,
second_belief = eng_two, hits = closed, misses = delta )
# Compare again, but bias the data toward the second engineer: .3, .7
favor_eng2_score <- ScoreBetaBeliefs(bias = c(.3,.7),
first_belief = eng_one, second_belief = eng_two,
hits = closed, misses = delta )
# Print out the unbiased Score
raw_score
# Print out the biased score
favor_eng2_score
# Vuln Data Central Tendency – date ratios
closed/opened
###########################
### Graph The Updated Model
# Bayesian Updating - Data + Beliefs
updated_hits <- eng_one[1] + closed #update
updated_misses <- eng_one[2] + delta #update
MakeBetaGraph(hit = updated_hits, miss = updated_misses,
"Vuln Fix Rate","Plausibility","Bayesian Updating Example",
"Eng 1 Beliefs + Data")
#########################
### Predicting The Future
# What’s A Plausible Remediation Rate For 22 Extreme Vulns?
future_count <- 22
vpred <- GetVulnPredictions(updated_hits, updated_misses, future_count)
### Code Inside GetVulnPredictions
# Priors + Data
beta_vals <- c(updated_hits, updated_misses)
# Store as list from 0 to 22
future_list = 0:future_count
# LearnBayes predictive function: uses beta prior and binomial data output
prob_future = pbetap(beta_vals, future_count, future_list)
# This call produces the list seen below.
round(cbind(future_list, prob_future), digits=3)
### 90% Most Probable Results
discint(cbind(vpred[,1], vpred[,2]), .9)
beta_probs = rbeta(n=1000, updated_hits, updated_misses)
closed_counts = rbinom(n=1000, size=future_count, prob=beta_probs)
table(closed_counts)
closed_freq = table(closed_counts)
closed_props = closed_freq/sum(closed_freq)
plot(closed_props, type="h", xlab="Number Closed",
las=1, lwd=3, ylab="Probability Closed")
##############################
### Wrapping Up Basic Burndown
# Get prior beliefs in shape parameter form
eng_one <- GetBeliefsHits(4,7,10)
# Raw Data
opened_dates <- c("2020-07-25","2020-08-01","2020-08-03","2020-08-03",
"2020-08-03","2020-08-05","2020-08-05","2020-08-30",
"2020-09-12","2020-09-20","2020-09-23")
closed_dates <- c("2020-07-29","2020-08-05","2020-08-06","2020-08-06",
"2020-09-03","2020-09-13","2020-09-25")
# Count Closed
closed <- length(closed_dates)
# Count left opened
delta <- length(opened_dates) - closed
# Bayesian Update, beliefs + data
updated_hits <- eng_one[1] + closed
updated_misses <- eng_one[2] + delta
# Create a graph that is a mesh of the above
MakeBetaGraph(hit = updated_hits, miss = updated_misses,
"Vuln Fix Rate","Plausibility","Bayesian Updating Example",
"Eng 1 Beliefs + Data")
### Bayes Burndown Curves
# Bayes Burndown Curve (black): Eng1 Beliefs + Data
curve(dbeta(x, closed + eng_one[1], delta + eng_one[2]), from=0, to=1,
xlab="Burndown Rate", ylab="Plausibility",col=1, lwd=4, las=1)
# Actual Vuln Data (Dates) Curve (red)
curve(dbeta(x, closed + 1, delta + 1), add=TRUE, col=2,lwd=4)
# Engineer 1 Beliefs (green)
curve(dbeta(x, eng_one[1], eng_one[2]), add=TRUE, col=3, lwd=4)
# Engineer 2 Beliefs (blue)
curve(dbeta(x, eng_two[1], eng_two[2]), add=TRUE, col=4, lwd=4)
#Legend
legend("topright", c("Engineer 2","Engineer 1", "Real Data",
"Bayesian Update"), col=c(4,3, 2, 1), lwd=c(3,3, 3, 3))
######################################
### Building A Bayesian Burndown Chart
# Jan includes Prior + first months data.
vulnData <- tibble(
yaxis = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"),
hits = c( 2, 4, 13, 4, 5, 12, 17, 7, 4, 3, 2, 4),
misses = c(12, 11, 10, 9, 8, 7, 6, 5, 14, 13, 12, 16)
)
# Encode Prior Beliefs
eng_one_prior <- GetBeliefsHits(eng_one[1], eng_one[2],10)
# Build Tidy Data Frame for Visualization
eng_risk <- MakeVulnData(vulnData, eng_one_prior)
# Make Visualization
MakeRidgeChart(eng_risk,
"Extreme Vulnerability Burndown Rates - One Week SLA",
"One Team Baselining Month By Month",
"Baseline Rate",
"Months",
"Time Frame")
### MakeVulnData() and MakeBurnData() Availble in manifesto_functions.R
# Get beta shape parameters from eng_ris for january
jan <- eng_risk %>% filter(yaxis == "Jan") %>%
select(closed, misses) %>% distinct()
# Generate 1,000 random probabilities constrained by shape params
jan_dist <- rbeta(10000, jan$closed, jan$misses)
# Get the 89% Highest Density Interval
jan_hdi <- ci(jan_dist, method = "HDI")
jan_hdi
# Get the shape parameters for Dec
dec <- eng_risk %>% filter(yaxis == "Dec") %>%
select(closed, misses) %>% distinct()
# Generate 1000 probabilities constrained by shape parameters
dec_dist <- rbeta(1000, dec$closed, dec$misses)
# Get the HDI
dec_hdi <- ci(dec_dist, method = "HDI")
dec_hdi
# Get Diff Between Months
diff_dist <- dec_dist - jan_dist
# How much of Dec is credibly within Jan?
rope(diff_dist)
#####################
### Are We Improving?
# Best central tendency point estimates
map_estimate(jan_dist)
map_estimate(dec_dist)
# Simple/Quick Plots
plot(density(jan_dist))
plot(density(dec_dist))
GetRope(eng_risk, "Jun", "Dec")
##########################
### Final: Comparing Teams
# Build Team One Data Frame
teamOneData <- tibble(yaxis = "Team 1",
hits = c(10,24,46, 160),
misses = c(20,20,20,5),
legend = c("Q1", "Q2", "Q3", "Q4"))
# Codify Eng One Beliefs
prior <- GetBeliefsHits(eng_one[1], eng_one[2],10)
# Create Posterior Distribution
team1 <- MakeVulnData(teamOneData, prior)
# Build TEam Two Data Frame
teamTwoData <- tibble(yaxis = "Team 2",
hits = c(10,15,20, 40),
misses = c(20,30,40,80),
legend = c("Q1", "Q2", "Q3", "Q4"))
# Codify Eng Two Beliefs
prior <- GetBeliefsHits(eng_two[1], eng_two[2],10)
# Create Posterior Distribution
team2 <- MakeVulnData(teamTwoData, prior)
# Combine Posteriors Into One Data Frame row by row
eng_risk <- rbind(team1, team2)
# Make Combined Chart
MakeRidgeChart2(eng_risk,
"Extreme Vulnerability Burndown Rates - One Week SLA",
"Q1 To Q4 Difference",
"Baseline Rate", "Teams",
"Time Frame")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment