Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0cd00e8

Browse files
authored
Merge pull request#265 from DanielTomaro13/team-stats-scraper
Add fetch_team_stats function and documentation
2 parentsa968556 +05e1adb commit0cd00e8

File tree

7 files changed

+218
-0
lines changed

7 files changed

+218
-0
lines changed

‎NAMESPACE‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export(fetch_results_footywire)
3030
export(fetch_results_squiggle)
3131
export(fetch_score_worm_data)
3232
export(fetch_squiggle_data)
33+
export(fetch_team_stats)
3334
export(get_afl_cookie)
3435
export(get_aflw_detailed_data)
3536
export(get_aflw_detailed_match_data)

‎NEWS.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
#fitzRoy (development version)
22

3+
##Improvements
4+
5+
* Added a new wrapper function`fetch_team_stats()` for retrieving team-level statistics from multiple sources.
6+
* Improved code clarity and consistency with better error handling (`cli`), safer scoping (`.data$`), and modern`dplyr` syntax.
7+
* Enhanced compatibility with other functions by ensuring consistent team naming and structure in outputs.
8+
9+
310
##Bug Fixes
411

512
* Fix duplicates for most recent game in`fetch_player_stats_afltables()` ([#250](https://github.com/jimmyday12/fitzRoy/issues/250))

‎R/fetch_team_stats.R‎

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#' Fetch Team Statistics
2+
#'
3+
#' General wrapper for fetching team statistics from a specified source.
4+
#'
5+
#' @param season Integer. The season to fetch stats for (e.g. 2024).
6+
#' @param summary_type Character. Either `"totals"` (default) or `"averages"`.
7+
#' @param source Character. Currently only `"afltables"` is supported.
8+
#' @param ... Additional arguments passed to the underlying data source function.
9+
#'
10+
#' @return A data frame of team stats for the season.
11+
#' @export
12+
#'
13+
#' @examples
14+
#' fetch_team_stats(2023)
15+
#' fetch_team_stats(2024, summary_type = "averages")
16+
fetch_team_stats<-function(season,
17+
summary_type="totals",
18+
source="afltables",
19+
...) {
20+
dat<-switch(source,
21+
"afltables"= fetch_team_stats_afltables(season,summary_type),
22+
NULL
23+
)
24+
25+
if (is.null(dat)) {
26+
cli::cli_warn('The source "{source}" is not supported.')
27+
}
28+
29+
return(dat)
30+
}
31+
32+
33+
#' Fetch Team Statistics from AFLTables
34+
#'
35+
#' Scrapes team-level statistics from AFLTables.com for a given season.
36+
#'
37+
#' @param season Integer. A season (e.g. 2024).
38+
#' @param summary_type Character. Either `"totals"` (default) or `"averages"`.
39+
#'
40+
#' @return A data frame with team statistics from AFLTables.
41+
#' @keywords internal
42+
fetch_team_stats_afltables<-function(season,summary_type="totals") {
43+
if (!is.numeric(season)||season<1965) {
44+
cli::cli_abort('Season must be numeric and greater than or equal to 1965. You provided "{season}".')
45+
}
46+
47+
cli::cli_progress_step("Downloading team stats from AFLTables for {season}")
48+
49+
url<-glue::glue("https://afltables.com/afl/stats/{season}s.html")
50+
page<- tryCatch(rvest::read_html(url),error=function(e)NULL)
51+
52+
if (is.null(page)) {
53+
cli::cli_abort("Could not access AFLTables page for season {season}.")
54+
}
55+
56+
tables<-page|>rvest::html_elements("table")
57+
58+
if (length(tables)<3) {
59+
cli::cli_abort("Insufficient tables found on the page for season: {season}")
60+
}
61+
62+
team_totals_for<-tables[[2]]|>rvest::html_table(fill=TRUE)
63+
team_totals_against<-tables[[3]]|>rvest::html_table(fill=TRUE)
64+
65+
colnames(team_totals_for)[1]<-"Team"
66+
colnames(team_totals_against)[1]<-"Team"
67+
team_totals_for$type<-"for"
68+
team_totals_against$type<-"against"
69+
70+
team_stats<-dplyr::bind_rows(team_totals_for,team_totals_against)|>
71+
dplyr::filter(.data$Team!="Totals")|>
72+
dplyr::mutate(
73+
dplyr::across(
74+
dplyr::where(is.character)&!dplyr::any_of(c("Team","type")),
75+
readr::parse_number
76+
)
77+
)
78+
79+
team_stats_wide<-team_stats|>
80+
tidyr::pivot_wider(
81+
names_from=.data$type,
82+
values_from=-c(.data$Team,.data$type),
83+
names_sep="_"
84+
)
85+
86+
for_cols<- grep("_for$", names(team_stats_wide),value=TRUE)
87+
against_cols<- gsub("_for$","_against",for_cols)
88+
diff_cols<- gsub("_for$","_diff",for_cols)
89+
90+
diff_list<-rlang::set_names(
91+
purrr::map2(for_cols,against_cols,~team_stats_wide[[.x]]-team_stats_wide[[.y]]),
92+
diff_cols
93+
)
94+
95+
team_stats_final<-dplyr::bind_cols(team_stats_wide,tibble::as_tibble(diff_list))|>
96+
dplyr::mutate(season=season)|>
97+
dplyr::relocate(.data$season,.before=.data$Team)
98+
99+
if (summary_type=="averages") {
100+
results<-fitzRoy::fetch_results_afltables(season)
101+
102+
game_counts<-results|>
103+
dplyr::filter(!is.na(.data$Home.Team),!is.na(.data$Away.Team))|>
104+
tidyr::pivot_longer(cols= c(.data$Home.Team,.data$Away.Team),
105+
names_to="HomeAway",values_to="Team")|>
106+
dplyr::count(.data$Team,name="Games")
107+
108+
# fetch_results_afltables has these two teams named differently
109+
name_map<- c(
110+
"GWS"="Greater Western Sydney",
111+
"Footscray"="Western Bulldogs"
112+
)
113+
game_counts<-game_counts|>
114+
dplyr::mutate(
115+
Team=dplyr::recode(.data$Team,!!!name_map)
116+
)
117+
118+
team_stats_final<-dplyr::left_join(team_stats_final,game_counts,by="Team")
119+
120+
numeric_cols<-team_stats_final|>
121+
dplyr::select(-.data$season,-.data$Team,-.data$Games)|>
122+
dplyr::select(where(is.numeric))|>
123+
names()
124+
125+
team_stats_final<-team_stats_final|>
126+
dplyr::mutate(dplyr::across(dplyr::all_of(numeric_cols),~./.data$Games))
127+
}
128+
129+
return(team_stats_final)
130+
}

‎_pkgdown.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ reference:
2828
-'`fetch_results`'
2929
-'`fetch_fixture`'
3030
-'`fetch_player_stats`'
31+
-fetch_team_stats
3132
-fetch_lineup
3233
-fetch_player_details
3334
-fetch_coaches_votes

‎man/fetch_team_stats.Rd‎

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎man/fetch_team_stats_afltables.Rd‎

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
test_that("fetch_team_stats_afltables returns totals", {
2+
skip_on_cran()
3+
skip_if_offline()
4+
5+
result<- fetch_team_stats(2023,summary_type="totals")
6+
7+
expect_s3_class(result,"data.frame")
8+
expect_true("season"%in% names(result))
9+
expect_true("Team"%in% names(result))
10+
expect_true(any(grepl("_for$", names(result))))
11+
expect_true(any(grepl("_against$", names(result))))
12+
expect_true(any(grepl("_diff$", names(result))))
13+
})
14+
15+
test_that("fetch_team_stats_afltables returns averages", {
16+
skip_on_cran()
17+
skip_if_offline()
18+
19+
result<- fetch_team_stats(2023,summary_type="averages")
20+
21+
expect_s3_class(result,"data.frame")
22+
expect_true("Games"%in% names(result))
23+
expect_true(all(result$Games>=0))
24+
})
25+
26+
test_that("fetch_team_stats fails gracefully on invalid season", {
27+
expect_error(fetch_team_stats(1900),"Season must be numeric and greater than or equal to 1965")
28+
})
29+
30+
test_that("fetch_team_stats warns on unknown source", {
31+
expect_warning(fetch_team_stats(2023,source="unknown"),"The source")
32+
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp