How do individual members of the federal German parliament (Bundestag) vote in "Namentliche Abstimmungen" (roll call votes)? How does the individual align with the different political parties? And how may the members vote on upcoming bills? The
bundestagcli provides tools to assist to answer those questions by providing tools download and transform the required data.
The German parliament makes roll call votes available as XLSX / XLS files (and PDFs ¯\_(ツ)_/¯ ) here: https://www.bundestag.de/parlament/plenum/abstimmung/liste.
The NGO abgeordnetenwatch provides an open API for a variety of related data. They also provide a great way of inspecting the voting behavior of members of parliament and their (non-)responses to question asked by the public.
Do all the members of a party always follow the party line? Clearly not. But that "discipline" is similar across parties. The significant deviation are the factionless, as measured here using Shannon entropy. The curious mind could even estimate the energy it takes to enforce the disciplines.
As a side effect of trying to predict the vote of individual members of parliament, we can obtain embeddings for each member. Doing so for the 2017-2021 legislative period, we find that they cluster into governing coalition (CDU/CSU & SPD) and the opposition:

If you want to see more check out this site or this notebook.
pip install bundestagor
uv add bundestagto get access to the cli to download and transform bundestag roll call votes data from bundestag.de or abgeordnetenwatch.de.
By to keep things light the machine learning dependencies are made optional. If you want to get those and related functionality as well run
pip install bundestag[ml]or
uv add bundestag[ml]For development
git clone https://github.com/eschmidt42/bundestag
cd bundestag
make install-dev-envA tool to assist with the data processing.
For an overview over commands run
bundestag --helpTo get preprocessed data simply run
bundestag download huggingfaceTo download data from abgeordnetenwatch, for a specific legislature id
bundestag download abgeordnetenwatch 132To transform the downloaded data run
bundestag transform abgeordnetenwatch 132To find out the legislature id for the current Bundestag, visit abgeordnetenwatch.de and click on the "Open Data" button at the bottom of the page.
To download data from bundestag.de
bundestag download bundestag-sheets --do-create-xlsx-uris-jsonNote that this is using selenium and is therefore starting a browser. Currently this is not using a headless browser so it is easy to see when the scraping should be broken.
To transform the downloaded data run
bundestag transform bundestag-sheet --sheet-source=json_fileNote: If you run the extraction for the legislature with id 132, i.e.
bundestag transform abgeordnetenwatch 132the data is damaged for some reason. To fix it run
uv run python scripts/fix_empty_fraction.pydownload commands will store artefacts in ./data/raw and transform commands will transform that data and store artefacts in ./data/preprocessed.
Pre-processing cli for bundestag cli.
uv run get_xlsx_uris run --helpModule for collecting and storing XLSX URIs from Bundestag data sources. Also done with
bundestag download bundestag_sheet --do-create-xlsx-uris-json- fraktionszwang
- embedded members of parliament

