Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
Package: sport
Type: Package
Title: Sequential Pairwise Online Rating Techniques
Version: 0.2.2
Depends: R (>= 3.0)
Version: 0.5.0
Depends:
R (>= 3.5)
Authors@R: person(given = "Dawid",
family = "Kałędkowski",
role = c("aut", "cre"),
Expand All @@ -23,20 +24,22 @@ Description: Calculates ratings for two-player or
Ruby C. Weng, Chih-Jen Lin (2011) <https://www.jmlr.org/papers/volume12/weng11a/weng11a.pdf>;
W. Penny, Stephen J. Roberts (1999) <doi:10.1109/IJCNN.1999.832603>.
BugReports: https://github.com/gogonzo/sport/issues
Imports:
Imports:
Rcpp,
data.table,
ggplot2
stats,
utils
LinkingTo: Rcpp
License: GPL-2
Encoding: UTF-8
Language: en-US
URL: https://github.com/gogonzo/sport
LazyData: true
RoxygenNote: 7.2.3
RoxygenNote: 7.3.3
Roxygen: list(markdown = TRUE)
Suggests:
Suggests:
dplyr,
ggplot2,
knitr,
lobstr,
rmarkdown,
Expand Down
21 changes: 15 additions & 6 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
# Generated by roxygen2: do not edit by hand

S3method(plot,rating)
S3method(predict,rating)
S3method(print,rating)
S3method(summary,rating)
S3method(as.list,ratings)
S3method(as.ratings,data.frame)
S3method(as.ratings,list)
S3method(as.ratings,numeric)
S3method(as.ratings,ratings)
S3method(coef,ratings)
S3method(plot,ratings)
S3method(predict,ratings)
S3method(print,ratings)
S3method(summary,ratings)
S3method(update,ratings)
export(as.ratings)
export(bbt_run)
export(dbl_run)
export(glicko2_run)
export(glicko_run)
export(positional)
import(data.table)
import(ggplot2)
importFrom(Rcpp,sourceCpp)
importFrom(data.table,rbindlist)
importFrom(stats,reorder)
importFrom(stats,coef)
importFrom(stats,predict)
importFrom(stats,setNames)
importFrom(stats,terms)
importFrom(stats,update)
Expand Down
33 changes: 33 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
# sport 0.5.0

----------------
## Changes:

* New `coef()`, `predict()`, `update()` and `as.list()` methods for objects
returned by `glicko_run()`, `glicko2_run()`, `bbt_run()` and `dbl_run()`.
`update()` continues training from existing ratings; `as.list()` produces a
JSON-friendly representation for persistence.
* New `as.ratings()` generic for constructing a ratings object from previously
fitted parameters, with methods for `numeric`, `data.frame` and `list`
inputs (the latter completes the round-trip with `as.list()`).
* New `positional()` function returning per-player, per-position finishing
probabilities for multi-competitor events via Plackett-Luce enumeration.
* Objects returned by the `*_run()` functions are now of class `"ratings"`
(previously `"rating"`).
* `plot.ratings()` is deprecated and will be removed in a future release.
Build your own plots from `coef(model)` and `model$trajectory` instead.
As a result `ggplot2` has moved from `Imports` to `Suggests` and is no
longer a hard dependency of the package.
* The `id` column in `model$trajectory` and `model$pairs` is now renamed to
the LHS id variable from the formula (e.g. `event_id` for
`place | event_id ~ player(rider)`), matching how the player/team columns
already adopt their formula names.
* `as.ratings.list()` now forwards the full `settings` list (`weight`,
`kappa`, `tau`, ...) into the reconstructed object, so a JSON round-trip
via `as.list()` -> `jsonlite::toJSON()` -> `jsonlite::fromJSON()` ->
`as.ratings()` -> `update()` resumes training with the original
hyperparameters and weight column.
* `glicko2_run()` and `bbt_run()` now use `numeric(0)` defaults for
`lambda`, `share`, and `weight` (matching `glicko_run()` and the internal
dispatcher) so the `settings` attribute is consistent across methods.

# sport v0.2.2

----------------
Expand Down
32 changes: 24 additions & 8 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

glicko <- function(unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau) {
.Call('_sport_glicko', PACKAGE = 'sport', unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau)
glicko <- function(unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau, record_trajectory = TRUE) {
.Call('_sport_glicko', PACKAGE = 'sport', unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau, record_trajectory)
}

glicko2 <- function(unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau) {
.Call('_sport_glicko2', PACKAGE = 'sport', unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau)
glicko2 <- function(unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau, record_trajectory = TRUE) {
.Call('_sport_glicko2', PACKAGE = 'sport', unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau, record_trajectory)
}

bbt <- function(unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau) {
.Call('_sport_bbt', PACKAGE = 'sport', unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau)
bbt <- function(unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau, record_trajectory = TRUE) {
.Call('_sport_bbt', PACKAGE = 'sport', unique_id, id, rank, team, player, r, rd, sigma, share, lambda, weight, init_r, init_rd, init_sigma, kappa, tau, record_trajectory)
}

dbl <- function(unique_id, id_vec, rank_vec, team_vec, MAP, X, cls, R, RD, lambda_vec, weight_vec, kappa) {
.Call('_sport_dbl', PACKAGE = 'sport', unique_id, id_vec, rank_vec, team_vec, MAP, X, cls, R, RD, lambda_vec, weight_vec, kappa)
dbl <- function(unique_id, id, rank, team, map, x, cls, r, rd, lambda, weight, kappa, record_trajectory = TRUE) {
.Call('_sport_dbl', PACKAGE = 'sport', unique_id, id, rank, team, map, x, cls, r, rd, lambda, weight, kappa, record_trajectory)
}

predict_glicko <- function(unique_id, id, rank, team, player, r, rd, share, lambda) {
.Call('_sport_predict_glicko', PACKAGE = 'sport', unique_id, id, rank, team, player, r, rd, share, lambda)
}

predict_glicko2 <- function(unique_id, id, rank, team, player, r, rd, sigma, share, lambda) {
.Call('_sport_predict_glicko2', PACKAGE = 'sport', unique_id, id, rank, team, player, r, rd, sigma, share, lambda)
}

predict_bbt <- function(unique_id, id, rank, team, player, r, rd, share, lambda) {
.Call('_sport_predict_bbt', PACKAGE = 'sport', unique_id, id, rank, team, player, r, rd, share, lambda)
}

predict_dbl <- function(unique_id, id, rank, team, map, x, r, rd, lambda) {
.Call('_sport_predict_dbl', PACKAGE = 'sport', unique_id, id, rank, team, map, x, r, rd, lambda)
}

51 changes: 51 additions & 0 deletions R/as.list.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#' Coerce a rating model to a plain list
#'
#' Returns a JSON-friendly representation of a `"ratings"` object: rating
#' vectors and metadata only. The cached `coefficients` matrix and any
#' `trajectory` / `pairs` data.tables are dropped -- they are either regenerable
#' (`coefficients`) or too large to store as model parameters. The `formula` is
#' deparsed to a character string so the result serializes cleanly with
#' `jsonlite::toJSON()` or similar.
#'
#' Use [as.ratings()] (the `list` method) to reconstruct a `"ratings"` object
#' from the result.
#'
#' @param x a `"ratings"` object.
#' @param ... ignored.
#'
#' @return A plain list with elements `method`, `formula` (character),
#' `settings`, `r`, `rd`, and (for glicko2) `sigma`.
#'
#' @examples
#' m <- glicko_run(rank | id ~ player(rider), data = gpheats[1:100, ])
#' params <- as.list(m)
#' str(params)
#'
#' # Round-trip
#' m2 <- as.ratings(params)
#' identical(m$r, m2$r)
#'
#' \dontrun{
#' # Persist to a database as JSON.
#' # Pass `digits = NA` so jsonlite preserves full floating-point precision --
#' # the default of 4 digits will quantise the ratings.
#' payload <- jsonlite::toJSON(as.list(m), auto_unbox = TRUE, digits = NA)
#' DBI::dbWriteTable(con, "models", data.frame(id = 1L, payload = payload))
#' }
#'
#' @seealso [as.ratings()], [coef.ratings()]
#' @export
as.list.ratings <- function(x, ...) {
formula <- attr(x, "formula")
# Convert named numerics to named lists so jsonlite::toJSON serializes
# them as JSON objects (preserving names) rather than bare arrays.
out <- list(
method = attr(x, "method"),
formula = paste(deparse(formula), collapse = " "),
settings = attr(x, "settings"),
r = as.list(x$r),
rd = as.list(x$rd)
)
if (!is.null(x$sigma)) out$sigma <- as.list(x$sigma)
out
}
Loading
Loading