{"id":17224206,"url":"https://github.com/ekstroem/soccer","last_synced_at":"2025-06-13T20:04:14.583Z","repository":{"id":56936825,"uuid":"168207378","full_name":"ekstroem/socceR","owner":"ekstroem","description":"Evaluating sport tournament predictions","archived":false,"fork":false,"pushed_at":"2019-07-03T13:24:43.000Z","size":41,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-16T07:52:30.888Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ekstroem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-29T18:37:38.000Z","updated_at":"2024-04-10T02:08:27.000Z","dependencies_parsed_at":"2022-08-21T07:20:40.311Z","dependency_job_id":null,"html_url":"https://github.com/ekstroem/socceR","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ekstroem/socceR","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekstroem%2FsocceR","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekstroem%2FsocceR/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekstroem%2FsocceR/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekstroem%2FsocceR/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ekstroem","download_url":"https://codeload.github.com/ekstroem/socceR/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekstroem%2FsocceR/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259712374,"owners_count":22900034,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T04:10:30.751Z","updated_at":"2025-06-13T20:04:14.547Z","avatar_url":"https://github.com/ekstroem.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"# socceR package\n\n\nDevelopment version of the R package `socceR` for evaluating and comparing sport tournament predictions.\n\nTo install the development version of `socceR` run the following command from \nwithin R (this requires that the `devtools` package is already installed on the system.)\n\n\n    devtools::install_github('ekstroem/socceR')\n\n\n## Evaluating predictions\n\n```\nm1 \u003c- matrix(c(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, .5, .5, 0, 0, .5, .5), 4)\nm1 # Prediction where certain on the top ranks\nm2 \u003c- matrix(c(.5, .5, 0, 0, .5, .5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1), 4)\nm2  # Prediction where the groups are okay \nm3 \u003c- matrix(c(.5, .5, 0, 0, .5, .5, 0, 0, 0, 0, .5, .5, 0, 0, .5, .5), 4)\nm3  # Prediction where no clue about anything\nm4 \u003c- matrix(rep(1/4, 16), 4)\nm4\n\nrps(m1, c(1, 2, 3, 4)) # Better prediction\nrps(m2, c(1, 2, 3, 4)) # Slightly worse prediction\nrps(m3, c(1, 2, 3, 4)) # Slightly worse prediction\nrps(m4, c(1, 2, 3, 4)) # Slightly worse prediction\n\noptimize_weights(list(m1, m2, m3, m4), 1:4)\n\n```\n\n# Weighing predictions over multiple tournaments\n\nThis section is not quite finished yet and is more or less just proof-of-concept\n\nLet's create another set of predictions fro another tournament but with the same methods as above.\n\n```\nM1 \u003c- matrix(c(.8, .2, 0, 0, .1, .7, .2, 0, .05, .05, .4, .5, .05, .05, .4, .5), 4)\nM1 # Prediction where certain on the top ranks\nM2 \u003c- matrix(rev(c(.8, .2, 0, 0, .1, .7, .2, 0, .05, .05, .4, .5, .05, .05, .4, .5)), 4)\nM2  # Prediction where the groups are okay \nM3 \u003c- matrix(c(.5, .5, 0, 0, .5, .5, 0, 0, 0, 0, .5, .5, 0, 0, .5, .5), 4)\nM3  # Prediction where no clue about anything\nM4 \u003c- matrix(rep(1/4, 16), 4)\nM4\n```\n\nLet us find the optimal weights (and assume that outcome was the same in the two tournaments)\n\n\n```\noptimize_weights2 \u003c- function(predictionlist, outcome, FUN=rps) {\n  # Sanity checks needed:\n  # Check equal dimensions of matrices\n  # Check match with outcome\n  \n  # Start by finding their individual RPS scores\n  startrps \u003c- rowSums(sapply(predictionlist, function(plist) { sapply(plist, function(mat) { FUN(mat, outcome)} )})\n  )  \n  # Should be possible to get much faster\n  weightedrps \u003c- function(weights) { \n    weights \u003c- exp(weights)/sum(exp(weights))\n    Reduce('+', lapply(predictionlist, function(x) {\n    FUN(Reduce('+', lapply(1:length(weights), function(i){weights[i]*x[[i]]})), outcome)\n    }))\n  }\n  \n  res \u003c- optim(exp(-startrps), weightedrps)\n  \n  exp(res$par)/sum(exp(res$par))\n}\n```\n\nThe function above should probably be wrapped in a proper function. If we run\n\n\n```\noptimize_weights2(list(list(m1, m2, m3, m4), list(M1, M2, M3, M4)), 1:4)\n```\n\nthen we get the optimal weights across multiple tournaments.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekstroem%2Fsoccer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fekstroem%2Fsoccer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekstroem%2Fsoccer/lists"}