{"id":25452348,"url":"https://github.com/raphaelsenn/playervectors","last_synced_at":"2026-03-04T12:01:28.918Z","repository":{"id":269082266,"uuid":"906367106","full_name":"raphaelsenn/playervectors","owner":"raphaelsenn","description":"Implementation of the paper \"Player Vectors: Characterizing Soccer Players Playing Style from Match Event Streams\".","archived":false,"fork":false,"pushed_at":"2025-08-05T18:11:33.000Z","size":73598,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-26T20:15:40.103Z","etag":null,"topics":["data-science"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/raphaelsenn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-20T18:35:14.000Z","updated_at":"2025-09-23T13:28:09.000Z","dependencies_parsed_at":"2025-01-12T17:21:03.682Z","dependency_job_id":"34874e40-15f3-4647-b36b-ebf037447d77","html_url":"https://github.com/raphaelsenn/playervectors","commit_stats":null,"previous_names":["raphsenn/playervectors","raphaelsenn/playervectors"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/raphaelsenn/playervectors","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelsenn%2Fplayervectors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelsenn%2Fplayervectors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelsenn%2Fplayervectors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelsenn%2Fplayervectors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raphaelsenn","download_url":"https://codeload.github.com/raphaelsenn/playervectors/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raphaelsenn%2Fplayervectors/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30079565,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T11:57:42.557Z","status":"ssl_error","status_checked_at":"2026-03-04T11:56:10.793Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["data-science"],"created_at":"2025-02-17T23:05:34.222Z","updated_at":"2026-03-04T12:01:28.908Z","avatar_url":"https://github.com/raphaelsenn.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# playervectors\nImplementation of [Player Vectors: Characterizing Soccer Players Playing Style from Match Event Streams](https://ecmlpkdd2019.org/downloads/paper/701.pdf) in python.\n\n## Install\n\n```bash\npip install playervectors\n```\n\n## Usage\n\n## Expected Format for `df_events` (SPADL Format)\n\nThe `df_events` DataFrame used in `PlayerVectors.fit()` must follow the **SPADL format**, with the following required column names:\n\n| Column Name  | Description |\n|-------------|------------|\n| **player_id**  | Unique identifier for the player. |\n| **action_type** | Type of action or event (e.g., shot, pass, cross, dribble). |\n| **x_start** | X-coordinate where the action starts. |\n| **y_start** | Y-coordinate where the action starts. |\n| **x_end** | X-coordinate where the action ends. |\n| **y_end** | Y-coordinate where the action ends. |\n\nIf not, change the mapping in `PlayerVectors.fit(column_names=new_column_names)` such that:\n\n```python\nnew_column_names = {\n    'player_id': 'your_player_id',\n    'action_type': 'your_action_type',\n    'x_start': 'your_x_start',\n    'y_start': 'your_y_start',\n    'x_end': 'your_x_end',\n    'y_end': 'your_y_end'\n}\n```\n\n### Fitting PlayerVectors\nBuilding **18**-component **PlayerVectors** with selected actions **shot**, **cross**, **dribble** and **pass** with respective components **4**, **4**, **5** and **5**.\n\n```python\nfrom playervectors import PlayerVectors\n\n\npvs = PlayerVectors(\n    grid=(50, 50),\n    actions=['shot', 'cross', 'dribble', 'pass'],\n    components=[4, 4, 5, 5]\n)\n\npvs.fit(\n    df_events=df_events,\n    minutes_played=minutes_played,\n    player_names=player_names\n)\n```\n\n| Parameter  | Description |\n|-------------|------------|\n| **df_events**  | Event Stream Data in SPADL-Format. |\n| **minutes_played** | A dictionary that maps each player_id to the total minutes they played across all events in df_events|\n| **player_names** | Mapping player_id to player_name. |\n\n\n### Plotting Principle Components\n\n```python\nimport matplotlib.pyplot as plt\n\n\npvs.plot_principle_components()\nplt.show()\n```\n![image](res/principle_components.png)\n\n\u003cp style=\"font-size: 12px; text-align: center;\"\u003e\n    \u003cem\u003eOutput of: pvs.plot_principle_components()\u003c/em\u003e\n\u003c/p\u003e\n\n\n### Plotting Weight Distribution\n\n```python\nimport matplotlib.pyplot as plt\n\n\npvs.plot_distribution()\nplt.show()\n```\n![image](res/distribution_weights.png)\n\n\u003cp style=\"font-size: 12px; text-align: center;\"\u003e\n    \u003cem\u003eOutput of: pvs.plot_distribution()\u003c/em\u003e\n\u003c/p\u003e\n\n### Plotting Weights of a Player\n\n```python\nimport matplotlib.pyplot as plt\n\n\n# wy_id of Kevin De Bruyne (Central midfielder)\npvs.plot_weights(player_id=38021)\nplt.show()\n```\n\n![image](res/weights_kevin.png)\n\n\u003cp style=\"font-size: 12px; text-align: center;\"\u003e\n    \u003cem\u003eOutput of: pvs.plot_weights(player_id=38021)\u003c/em\u003e\n\u003c/p\u003e\n\n\n\n## Building Player Vectors\n\n### 1. Selecting Relevant Action Types\nLet $k_t$ be the number of principal components chosen to compress heatmaps of action type $t$.\n\nAccording to the paper, $k_t$ with $t \\in$ {shot, cross, dribble, pass} with corresponding components {4, 4, 5, 5} is the minimal number of components needed to explain 70% of the variance in the heatmaps of action type $t$.\n\n\nThis parameter setting\nwas empirically found to work well because of the high variability of players\npositions in their actions (see Challenge 1 in Section 2 in the paper).\n\nIgnoring 30% of the variance allows to summarize a player’s playstyle only by his dominant regions\non the field rather than model every position on the field he ever occupied.\n\n\n### 2. Constructing Heatmaps\n\n#### 2.1 Counting\n![image](res/counting.png)\n\n\u003cp style=\"font-size: 12px; text-align: center;\"\u003e\n    \u003cem\u003eSource: Tom Decroos and Jesse Davis, September 19th, 2019 ECMLPKDD\u003c/em\u003e\n\u003c/p\u003e\n\n#### 2.2 Normalizing\n![image](res/counting_norm.png)\n\n\u003cp style=\"font-size: 12px; text-align: center;\"\u003e\n    \u003cem\u003eSource: Tom Decroos and Jesse Davis, September 19th, 2019 ECMLPKDD\u003c/em\u003e\n\u003c/p\u003e\n\n#### 3.3 Smoothing\n![image](res/smoothing.png)\n\n\u003cp style=\"font-size: 12px; text-align: center;\"\u003e\n    \u003cem\u003eSource: Tom Decroos and Jesse Davis, September 19th, 2019 ECMLPKDD\u003c/em\u003e\n\u003c/p\u003e\n\n\n### 3. Compressing Heatmaps to Vectors\n\n#### 3.1 Reshaping\n![image](res/reshaping.png)\n\n\u003cp style=\"font-size: 12px; text-align: center;\"\u003e\n    \u003cem\u003eSource: Tom Decroos and Jesse Davis, September 19th, 2019 ECMLPKDD\u003c/em\u003e\n\u003c/p\u003e\n\n\n#### 3.2 Construct the matrix M\n\n![image](res/matrix_m.png)\n\n\u003cp style=\"font-size: 12px; text-align: center;\"\u003e\n    \u003cem\u003eSource: Tom Decroos and Jesse Davis, September 19th, 2019 ECMLPKDD\u003c/em\u003e\n\u003c/p\u003e\n\n\n#### 3.3 Compress matrix M by applying non-negative matrix factorization (NMF)\n\n![image](res/nmf.png)\n\n\u003cp style=\"font-size: 12px; text-align: center;\"\u003e\n    \u003cem\u003eSource: Tom Decroos and Jesse Davis, September 19th, 2019 ECMLPKDD\u003c/em\u003e\n\u003c/p\u003e\n\n\n\n### 4. Assembling Player Vectors\nThe player vector v of a player p is the concatenation of his compressed vectors\nfor the relevant action types.\n\n## Detailed Algorithm\n![image](res/algorithm.png)\n\n\n## Running `demo.ipynb`\n\n#### 1. Download this [Dataset](https://www.kaggle.com/datasets/aleespinosa/soccer-match-event-dataset) on Kaggle\n\n#### 2. Create a folder named `data` in this Repository\n\n```bash\nmkdir data\n```\n\n#### 3. Copy all .csv files from the Dataset in the folder `data`\n\n#### 4. Run notebook `demo.ipynb`\n\n## About the Datasets\n\nThis dataset contains European football team stats.\nOnly teams of Premier League, Ligue 1, Bundesliga, Serie A and La Liga are listed.\n\nAll the credit is to Luca Pappalardo and Emmanuele Massucco.\n\n[https://www.kaggle.com/datasets/aleespinosa/soccer-match-event-dataset](https://www.kaggle.com/datasets/aleespinosa/soccer-match-event-dataset)\n\n## Citations\n\n```bibtex\n@article{ecmlpkdd2019,\n  title     = {Player Vectors: Characterizing Soccer Players’\nPlaying Style from Match Event Streams},\n  author    = {Tom Decroos, Jesse Davis},\n  journal   = {ecmlpkdd2019},\n  year      = {2019},\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraphaelsenn%2Fplayervectors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraphaelsenn%2Fplayervectors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraphaelsenn%2Fplayervectors/lists"}