You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
60 lines
2.1 KiB
60 lines
2.1 KiB
#' Product an ATT&CK Cumulative Distribution Function by Tactic
|
|
#'
|
|
#' @param xdf a data frame with `tactic`, `technique` and `value` columns.
|
|
#' If no `value` column exists, then the function will assume you
|
|
#' have passed in individual events and will perform a "count"
|
|
#' summarization before generating the heatmap.
|
|
#' @param input,output,matrix if both are not `NULL` then they should be
|
|
#' what [fct_tactic()] takes as parameters. Otherwise, the function
|
|
#' will assume that the `tactic` column is already an ordered factor.
|
|
#' @param ... passed on to [ggplot2::geom_label()]
|
|
#' @export
|
|
attck_cdf_tactic <- function(xdf, input = NULL, output = NULL, matrix = NULL, ...) {
|
|
|
|
cn <- colnames(xdf)
|
|
if (!all(c("tactic", "technique") %in% cn)) {
|
|
stop("'xdf' needs both 'tactic' and 'technique' columns.", call.=FALSE)
|
|
}
|
|
|
|
if (!("value" %in% cn)) {
|
|
xdf <- dplyr::count(xdf, tactic, technique, name = "value")
|
|
}
|
|
|
|
if (is.null(input) && is.null(output)) {
|
|
if (!is.factor(xdf$tactic)) {
|
|
stop(
|
|
"No 'input'/'output' transformation specified but 'tactic' is not a factor.",
|
|
call.=FALSE
|
|
)
|
|
}
|
|
} else {
|
|
if (sum(c(!is.null(input), !is.null(output), !is.null(matrix))) != 3) {
|
|
stop("Must specify 'input', 'output', and 'matrix' if any one of them is not NULL", call.=FALSE)
|
|
}
|
|
xdf$tactic <- fct_tactic(xdf$tactic, input = input, output = output, matrix = matrix)
|
|
}
|
|
|
|
xdf <- dplyr::count(xdf, tactic, wt=value)
|
|
xdf <- dplyr::arrange(xdf, tactic)
|
|
xdf <- dplyr::mutate(xdf, pct = n/sum(n))
|
|
xdf <- dplyr::mutate(xdf, cpct = cumsum(pct))
|
|
|
|
gg <- ggplot(xdf, aes(tactic, cpct, group=1))
|
|
gg <- gg + geom_path()
|
|
gg <- gg + geom_label(
|
|
aes(
|
|
label = sprintf("%s\n%s\n%s", scales::comma(n), scales::percent(pct), scales::percent(cpct)),
|
|
), lineheight = 0.875, ...
|
|
)
|
|
gg <- gg + scale_x_discrete(
|
|
expand = c(0, 0.5), position = "top",
|
|
breaks = levels(xdf$tactic), limits = levels(xdf$tactic)
|
|
)
|
|
gg <- gg + scale_y_continuous(
|
|
expand = c(0, 0.05), limits = c(-0.05, 1.05), label = scales::percent
|
|
)
|
|
gg <- gg + labs(x = NULL, y = NULL)
|
|
|
|
gg
|
|
|
|
}
|
|
|