Skip to content
This repository was archived by the owner on Sep 18, 2025. It is now read-only.

Commit 4bbc357

Browse files
authored
Merge pull request #436 from JaseZiv/bug/432
2 parents ea98363 + 127a82c commit 4bbc357

265 files changed

Lines changed: 5581 additions & 2576 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: worldfootballR
33
Title: Extract and Clean World Football (Soccer) Data
4-
Version: 0.6.7.0004
4+
Version: 0.6.8
55
Authors@R: c(
66
person("Jason", "Zivkovic", , "jaseziv83@gmail.com", role = c("aut", "cre", "cph")),
77
person("Tony", "ElHabr", , "anthonyelhabr@gmail.com", role = "ctb"),

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export(load_match_results)
4444
export(load_understat_league_shots)
4545
export(player_dictionary_mapping)
4646
export(player_transfer_history)
47+
export(tm_each_team_player_market_val)
4748
export(tm_expiring_contracts)
4849
export(tm_get_player_absence)
4950
export(tm_get_risk_of_suspension)

NEWS.md

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

3+
### New Functions
4+
5+
* `tm_each_team_player_market_val()` created to allow users to get player market values per team [#432](https://github.com/JaseZiv/worldfootballR/issues/432)
6+
37
### Bugs
48

59
* `tm_team_transfers()` correctly returns both Arrivals and Departures. (0.6.7.0004) ([#433](https://github.com/JaseZiv/worldfootballR/issues/433))

R/player_market_values.R

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,174 @@
1+
#' Get each team Transfermarkt player market values
2+
#'
3+
#' Returns data frame of player valuations (in Euros) from transfermarkt.com
4+
#' for an individual team
5+
#'
6+
#' @param each_team_url the url of the required team
7+
#' @param time_pause the wait time (in seconds) between page loads
8+
#'
9+
#' @return returns a dataframe of player valuations for a team
10+
#'
11+
#' @importFrom magrittr %>%
12+
#' @importFrom rlang .data
13+
#'
14+
#' @export
15+
#'
16+
17+
tm_each_team_player_market_val <- function(each_team_url, time_pause = 15) {
18+
19+
main_url <- "https://www.transfermarkt.com"
20+
21+
# there now appears to be an errorneous URL so will remove that manually:
22+
if(any(grepl("com#", each_team_url))) {
23+
each_team_url <- each_team_url[-grep(".com#", each_team_url)]
24+
}
25+
26+
each_team_url <- gsub("startseite", "kader", each_team_url) %>%
27+
paste0(., "/plus/1")
28+
29+
Sys.sleep(time_pause)
30+
31+
team_page <- xml2::read_html(each_team_url)
32+
33+
comp_name <- team_page |> rvest::html_elements(".data-header__club a") |> rvest::html_text() |> trimws()
34+
country <- team_page |> rvest::html_elements(".data-header__content a img") |> rvest::html_attr("title")
35+
season_start_year <- gsub(".*saison_id/", "", each_team_url) |> gsub("/plus/1", "", x=_) |> as.numeric()
36+
37+
team_data <- team_page %>% rvest::html_nodes("#yw1") %>% rvest::html_nodes(".items") %>% rvest::html_node("tbody")
38+
39+
tab_head_names <- team_page %>% rvest::html_nodes("#yw1") %>% rvest::html_nodes(".items") %>% rvest::html_nodes("th") %>% rvest::html_text()
40+
41+
# team name
42+
squad <- team_page %>% rvest::html_node(".data-header__headline-wrapper--oswald") %>% rvest::html_text() %>% stringr::str_squish()
43+
# numbers
44+
player_num <- team_data %>% rvest::html_nodes(".rn_nummer") %>% rvest::html_text()
45+
if(length(player_num) == 0) {
46+
player_num <- NA_character_
47+
}
48+
# player names
49+
player_name <- team_data %>% rvest::html_nodes(".inline-table a") %>% rvest::html_text() %>% stringr::str_squish()
50+
if(length(player_name) == 0) {
51+
player_name <- NA_character_
52+
}
53+
# player_url
54+
player_url <- team_data %>% rvest::html_nodes(".inline-table a") %>% rvest::html_attr("href") %>%
55+
paste0(main_url, .)
56+
if(length(player_url) == 0) {
57+
player_url <- NA_character_
58+
}
59+
# player position
60+
player_position <- team_data %>% rvest::html_nodes(".inline-table tr+ tr td") %>% rvest::html_text() %>% stringr::str_squish()
61+
if(length(player_position) == 0) {
62+
player_position <- NA_character_
63+
}
64+
# birthdate
65+
player_birthday <- team_data %>% rvest::html_nodes("td:nth-child(3)") %>% rvest::html_text()
66+
if(length(player_birthday) == 0) {
67+
player_birthday <- NA_character_
68+
}
69+
# player_nationality
70+
player_nationality <- c()
71+
player_nat <- team_data %>% rvest::html_nodes(".flaggenrahmen:nth-child(1)")
72+
if(length(player_nat) == 0) {
73+
player_nationality <- NA_character_
74+
} else {
75+
for(i in 1:length(player_nat)) {
76+
player_nationality <- c(player_nationality, xml2::xml_attrs(player_nat[[i]])[["title"]])
77+
}
78+
}
79+
# current club - only for previous seasons, not current:
80+
current_club_idx <- grep("Current club", tab_head_names)
81+
if(length(current_club_idx) == 0) {
82+
current_club <- NA_character_
83+
} else {
84+
c_club <- team_data %>% rvest::html_nodes(paste0("td:nth-child(", current_club_idx,")"))
85+
current_club <- c()
86+
for(cc in c_club) {
87+
each_current <- cc %>% rvest::html_nodes("a") %>% rvest::html_nodes("img") %>% rvest::html_attr("alt")
88+
if(length(each_current) == 0) {
89+
each_current <- NA_character_
90+
}
91+
current_club <- c(current_club, each_current)
92+
}
93+
}
94+
# player height
95+
height_idx <- grep("Height", tab_head_names)
96+
if(length(height_idx) == 0) {
97+
player_height_mtrs <- NA_character_
98+
} else {
99+
suppressWarnings(player_height_mtrs <- team_data %>% rvest::html_nodes(paste0("td:nth-child(", height_idx, ")")) %>% rvest::html_text() %>%
100+
gsub(",", "\\.", .) %>% gsub("m", "", .) %>% stringr::str_squish() %>% as.numeric())
101+
}
102+
# player_foot
103+
foot_idx <- grep("Foot", tab_head_names)
104+
if(length(foot_idx) == 0) {
105+
player_foot <- NA_character_
106+
} else {
107+
player_foot <- team_data %>% rvest::html_nodes(paste0("td:nth-child(", foot_idx,")")) %>% rvest::html_text()
108+
}
109+
# date joined club
110+
joined_idx <- grep("Joined", tab_head_names)
111+
if(length(joined_idx) == 0) {
112+
date_joined <- NA_character_
113+
} else {
114+
date_joined <- team_data %>% rvest::html_nodes(paste0("td:nth-child(", joined_idx, ")")) %>% rvest::html_text()
115+
}
116+
# joined from
117+
from_idx <- grep("Signed from", tab_head_names)
118+
if(length(from_idx) == 0) {
119+
joined_from <- NA_character_
120+
} else {
121+
p_club <- tryCatch(team_data %>% rvest::html_nodes(paste0("td:nth-child(", from_idx, ")")), error = function(e) NA)
122+
joined_from <- c()
123+
for(pc in p_club) {
124+
each_past <- pc %>% rvest::html_nodes("a") %>% rvest::html_nodes("img") %>% rvest::html_attr("alt")
125+
if(length(each_past) == 0) {
126+
each_past <- NA_character_
127+
}
128+
joined_from <- c(joined_from, each_past)
129+
}
130+
}
131+
# contract expiry
132+
contract_idx <- grep("Contract", tab_head_names)
133+
if(length(contract_idx) == 0) {
134+
contract_expiry <- NA_character_
135+
} else {
136+
contract_expiry <- team_data %>% rvest::html_nodes(paste0("td:nth-child(", contract_idx, ")")) %>% rvest::html_text()
137+
}
138+
# value
139+
player_market_value <- team_data %>% rvest::html_nodes(".rechts.hauptlink") %>% rvest::html_text()
140+
if(length(player_market_value) == 0) {
141+
player_market_value <- NA_character_
142+
}
143+
144+
suppressWarnings(team_df <- cbind(squad, player_num, player_name, player_url, player_position, player_birthday, player_nationality, current_club,
145+
player_height_mtrs, player_foot, date_joined, joined_from, contract_expiry, player_market_value) %>% data.frame())
146+
147+
team_df <- team_df |>
148+
dplyr::mutate(comp_name = comp_name,
149+
season_start_year = season_start_year,
150+
country = country) |>
151+
dplyr::mutate(player_market_value_euro = mapply(.convert_value_to_numeric, player_market_value)) %>%
152+
dplyr::mutate(date_joined = .tm_fix_dates(.data[["date_joined"]]),
153+
contract_expiry = .tm_fix_dates(.data[["contract_expiry"]])) %>%
154+
tidyr::separate(., player_birthday, into = c("Month", "Day", "Year"), sep = " ", remove = F) %>% suppressWarnings() |>
155+
dplyr::mutate(player_age = gsub(".*\\(", "", .data[["player_birthday"]]) %>% gsub("\\)", "", .),
156+
Day = gsub(",", "", .data[["Day"]]) %>% as.numeric(),
157+
Year = as.numeric(gsub("\\(.*", "", .data[["Year"]])),
158+
Month = match(.data[["Month"]], month.abb),
159+
player_dob = suppressWarnings(lubridate::ymd(paste(.data[["Year"]], .data[["Month"]], .data[["Day"]], sep = "-")))) %>%
160+
dplyr::mutate(player_age = as.numeric(gsub("\\D", "", .data[["player_age"]]))) %>%
161+
dplyr::select(.data[["comp_name"]], .data[["country"]], .data[["season_start_year"]], .data[["squad"]], .data[["player_num"]], .data[["player_name"]], .data[["player_position"]], .data[["player_dob"]], .data[["player_age"]], .data[["player_nationality"]], .data[["current_club"]],
162+
.data[["player_height_mtrs"]], .data[["player_foot"]], .data[["date_joined"]], .data[["joined_from"]], .data[["contract_expiry"]], .data[["player_market_value_euro"]], .data[["player_url"]])
163+
164+
165+
return(team_df)
166+
167+
}
168+
169+
170+
171+
1172
#' Get Transfermarkt player market values
2173
#'
3174
#' Returns data frame of player valuations (in Euros) from transfermarkt.com

R/tm_league_suspensions.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ tm_get_suspensions <- function(country_name = NA, league_url = NA) {
123123
error = function(e) NA_real_)
124124
)
125125
}) %>%
126-
dplyr::mutate(dplyr::across(where(is.character), .replace_empty_na))
126+
dplyr::mutate(dplyr::across(dplyr::where(is.character), .replace_empty_na))
127127
}, error = function(e) {
128128
warning("Failed to extract suspension data")
129129
return(data.frame())
@@ -225,7 +225,7 @@ tm_get_risk_of_suspension <- function(country_name, league_url = NA) {
225225
rvest::html_text(trim = TRUE) %>% as.numeric(), error = function(e) NA)
226226
)
227227
}) %>%
228-
dplyr::mutate(dplyr::across(where(is.character), .replace_empty_na))
228+
dplyr::mutate(dplyr::across(dplyr::where(is.character), .replace_empty_na))
229229
}, error = function(e) {
230230
warning("Failed to extract risk data")
231231
return(data.frame())

docs/404.html

Lines changed: 11 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)