Merge branch 'main' into feature/abstract-data-extraction

This commit is contained in:
TrisNol
2023-08-10 17:12:01 +02:00
140 changed files with 60269 additions and 604 deletions

20
documentations/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

Binary file not shown.

View File

@ -1,27 +1,27 @@
# Pflichtenheft: Kapitalgesellschaften referenzregister
Version 0.1 Erstellt am 07.04.2023
Version 0.1 Erstellt am 07.04.2023
|Autoren | Matrikelnummer |
|----------|---------|
| Kim Mesewinkel | 000 |
| Tristan Nolde | 000 |
| Sebastian Zelenie | 000 |
| Philip Horstenkamp | 000 |
| Sascha Zhu | 000 |
| Tim Ronneburg | 000 |
| Autoren | Matrikelnummer |
|--------------------|----------------|
| Kim Mesewinkel | 000 |
| Tristan Nolde | 000 |
| Sebastian Zelenie | 000 |
| Philip Horstenkamp | 000 |
| Sascha Zhu | 000 |
| Tim Ronneburg | 000 |
## Historie der Dokumentenversion <a name="historie"></a>
|Version | Datum | Autor | Änderungsgrund / Bemerkung |
|----------|---------| ---------| ---------|
| 0.1 | 07.04.2023 | Tim Ronneburg | Intialaufsetzen des Pflichtenhefts |
| 0.2 | 000 |
| ... | 000 |
| 1.0 | 000 |
| Version | Datum | Autor | Änderungsgrund / Bemerkung |
|-----------|------------|---------------|----------------------------------------|
| 0.1 | 07.04.2023 | Tim Ronneburg | Initiales aufsetzen des Pflichtenhefts |
| 0.2 | 000 | | |
| ... | 000 | | |
| 1.0 | 000 | | |
## Inhaltsverzeichnis <a name="inhaltsverzeichnis"></a>
[Historie der Dokumentenversion](#historie)
@ -78,7 +78,7 @@ Test
## Funktionale Anforderungenn <a name="f_anforderung"></a>
## Funktionale Anforderungen <a name="f_anforderung"></a>
### **Muss Ziele**
@ -115,9 +115,9 @@ Die Software soll bewerten ob die Berichtserstattung der letzten 7 Tage eher Pos
### **Muss Ziele**
### N100 <a name="n100"></a>
Das System muss die 1000 größten deutschen und europäischen Unternehmen beinhalten. Diese werden anhand der Kennzahlen
Das System muss die 1000 größten deutschen und europäischen Unternehmen beinhalten. Diese werden anhand der Kennzahlen
- Umsatz
-
-
-
bewertet und bemessen.
@ -144,4 +144,4 @@ Das System kann möglichst skalierbar sein, sodass auch eine Nutzerzahl von 1000
## Lieferumfang <a name="lieferumfang"></a>
## Anhang / Ressourcen <a name="anhang/ressourcen"></a>
## Anhang / Ressourcen <a name="anhang/ressourcen"></a>

88
documentations/conf.py Normal file
View File

@ -0,0 +1,88 @@
"""Python sphinx documentation build configuration."""
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
import os
import sys
from importlib.metadata import metadata
from typing import Final
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
_DISTRIBUTION_METADATA = metadata("aki-prj23-transparenzregister")
__author__: Final[str] = _DISTRIBUTION_METADATA["Author"]
__email__: Final[str] = _DISTRIBUTION_METADATA["Author-email"]
__version__: Final[str] = _DISTRIBUTION_METADATA["Version"]
project: Final[str] = "transparenzregister"
copyright: Final[str] = "2023, AKI PRJ23" # noqa: A001
author: Final[str] = __author__
version: Final[str] = __version__
release: Final[str] = __version__
sys.path.insert(0, os.path.abspath("../src")) # Add the path to your Python package
sys.path.insert(0, os.path.abspath("../src/aki_prj23_transparenzregister"))
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions: Final[list[str]] = [
"sphinx.ext.autodoc",
"nbsphinx",
"myst_parser",
"sphinx.ext.napoleon",
"sphinx_copybutton",
"sphinx_autodoc_typehints",
"sphinx.ext.intersphinx",
"sphinx.ext.autosectionlabel",
"sphinx.ext.viewcode",
"IPython.sphinxext.ipython_console_highlighting",
"sphinxcontrib.mermaid",
]
# templates_path : Final[list[str]] = ["_templates"]
exclude_patterns: Final[list[str]] = ["_build", "Thumbs.db", ".DS_Store", "templates"]
root_doc: Final[str] = "index"
# master_doc = "index"
autodoc_default_flags: Final[list[str]] = [
"members",
"inherited-members",
"show-inheritance",
]
autodoc_class_signature: Final[str] = "separated"
autodoc_default_options: Final[dict[str, bool]] = {
_: True for _ in autodoc_default_flags
}
autodoc_typehints: Final[str] = "signature"
simplify_optional_unions: Final[bool] = True
typehint_defaults: Final[str] = "comma"
source_suffix: Final[list[str]] = [".rst", ".md"]
mermaid_output_format: Final[str] = "raw"
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme: Final[str] = "sphinx_rtd_theme"
html_static_path: Final[list[str]] = ["_static"]
napoleon_google_docstring: Final[bool] = True
napoleon_numpy_docstring: Final[bool] = False
nbsphinx_execute = "never"
intersphinx_mapping: Final[dict[str, tuple[str, None]]] = {
"python": ("https://docs.python.org/3", None),
"pandas": ("https://pandas.pydata.org/docs/", None),
"numpy": ("https://numpy.org/doc/stable/", None),
"matplotlib": ("https://matplotlib.org/stable/", None),
"scikit-learn": ("https://scikit-learn.org/stable/", None),
"sphinx": ("https://docs.sympy.org/latest/", None),
}

54
documentations/index.rst Normal file
View File

@ -0,0 +1,54 @@
.. Your Package Name documentation master file, created by Sphinx
Transparenzregister Dokumentation
=================================
This is the documentation for the AKI project group on the german transparenzregister and an Analysis there of.
.. toctree::
:maxdepth: 3
:caption: Project planung
Pflichtenheft
timeline.md
.. toctree::
:glob:
:maxdepth: 1
:caption: Meeting Notes:
meeting-notes/*
.. toctree::
:glob:
:maxdepth: 3
:caption: Research
research/*
research/*.ipynb
.. toctree::
:glob:
:maxdepth: 0
:caption: Seminararbeiten
seminararbeiten/DevOps/Seminarpräsentation.ipynb
seminararbeiten/Datenspeicherung/00_Datenspeicherung.md
.. toctree::
:glob:
:maxdepth: 0
:caption: Modules
modules
.. automodule:: aki_prj23_transparenzregister
:members:
:undoc-members:
:show-inheritance:
:inherited-members:
:autodoc_member_order:
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`

35
documentations/make.bat Normal file
View File

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

View File

@ -0,0 +1,54 @@
# Weekly *3*: 04.05.2023
## Teilnehmer
- Prof. Arinir
- Tristan Nolde
- Tim Ronneburg
- Phillip Horstenkamp
- Kim Mesewinkel-Risse
- Sascha Zhu
- Sebastian Zeleny
## Themen
### Organisatorische Absprachen:
Gelten die Seminarthemen als Zwischenprüfung? In welcher Form?
- Herr Giefers hat Seminarthemen im Vorfeld definiert, in unserer Gruppe gab es eine offene Einarbeitung in die Forschungs- und Entwicklungsarbeit
- Geplanter Umfang: Seminararbeit 15-20 Seiten (Rücksprache mit Herrn Giefers und Herrn Gawron durch Herrn Arinir, Feedback beim nächsten Termin) und Vortrag mit Folien oder anderen Quellen (z.B. Quellcode) ca. 15-20 Minuten im Rahmen eines JF Termins (keine Vorstellung im Plenum)
- Die Seminararbeiten werden benotet (20% der Endnote), die Ausarbeitung und der Vortrag zählen dabei zu jeweils 50%
Wie lautet der zeitliche Rahmen?
- Keine feste Deadline vorgegeben, Absprache innerhalb der Projektgruppe ausreichend
- Vortrag: Einigung auf zwei Termine Ende Juni/Anfang Juli -> Thema 1-3 am 22.06.2023 und Thema 4-6 am 06.07.2023
- Seminararbeit: Abgabe voraussichtlich Ende des Sommersemesters, potentiell auch zu einem späteren Zeitpunkt möglich
Welche Themenbereiche sollen behandelt werden?
- Die erste kurze Beschreibung der 6 Themenbereiche/Domänen wurde durch Herrn Arinir als positiv befunden
- Zur Eingrenzung der Themen und für ein konkreteres Feedback soll für jeden Themenbereich beim nächsten JF am 11.05.2023 ein Abstract vorgestellt werden
- Grundsätzlich sollen die Themen nicht zu oberflächlich behandelt werden, sondern explizit auf Techniken zur Umsetzung eingegangen werden
Einigung auf Änderungen im Bereich Projektorganisation:
- Aufnahme des zeitlichen Ablaufs der Tickets in die Meeting Notes -> Screenshot des Projects in Protokoll mit aufnehmen
- Start-, Enddaten und Labels der Tickets besser pflegen
Sonstiges:
- Urlaubszeiten Herr Prof. Arinir: 17.07.-01.08.2023
## Abgeleitete Action Items
| Action Item | Verantwortlicher | Deadline |
|-------------|------------------|-----------------|
| Abstract pro Thema | Alle | nächstes Weekly |
| Folienvorlage für den Seminarvortrag | Alle | nächstes Weekly |
| Rückmeldung zum Umfang der Seminararbeit | Prof. Arinir | nächstes Weekly |
## Aktueller Projektstand
![alt text](https://github.com/fhswf/aki_prj23_transparenzregister/blob/meeting_notes_2023-05-04/documentations/meeting-notes/images/Project_2023-05-04.PNG)

View File

@ -0,0 +1,117 @@
# Weekly *4*: 11.05.2023
## Teilnehmer
- Prof. Arinir
- Tristan Nolde
- Tim Ronneburg
- Phillip Horstenkamp
- Kim Mesewinkel-Risse
- Sascha Zhu
- Sebastian Zeleny
## Themen
### Organisatorische Absprachen zum Umfang und Inhalt der Seminararbeit:
- Herr Arinir wird sich nochmal wegen des Umfangs der Seminararbeit bei unserer Gruppe melden
- In der Seminarbeit sollen Anforderungen und Lösungsskizzen für das Projekt "Transparenzregister" dargestellt werden.
- Die Seminarabeit soll aus einem theoretischen Teil und einem praktischen Teil, in dem der praktische Nutzen für das Projekt "Transparenzregister" erörtert wird, bestehen; ob das Verhältnis zwischen dem theoretischen und praktischen Teil bei 50:50 oder 40:60 liegt, darüber können die Verfaser der Seminararbeit selbst entscheiden
- Der Fokus der Seminarbeit soll stets danach ausgerichtet werden, wie die entsprechenden Aspekte bzw. die entsprechenden Technologien für das Projekt "Transparenzregister" genutzt werden können.
### Vorstellung des Abstracts der Seminararbeit zu "Dev Ops" (Philipp Horstenkamp):
Abstract siehe Datei in github.
Folgende Punkte wurden bei bzw. nach der Vorstellung des Abstracts diskutiert:
- Eine sehr straffe Pipeline, die für Seriensoftware in Ordnung wäre, könnte uns für unser Projekt zu sehr „fesseln“ bzw. einschränken.
- Es wäre zu überlegen, ob die Software-Entwicklung, wie diese früher ablief, mit der Software-Entwicklung von heute (u.a. mit den Automatisierungsmöglichkeiten von heute) gegenübergestellt werden soll, um daraus zunächst eine Strategie für unser Projekt zu entwickeln, bevor man sich vertieft mit DevOps beschäftigt
- Die Verwendung von CI/CD (Continuous Integration/Continuous Delivery)-Pipelines für KI-Projekte wäre ein interessantes Thema.
### Vorstellung des Abstracts der Seminararbeit zu "Automatisierte Datenextraktion aus Internetquellen als Grundlage für die Analyse von Kapitalgesellschaften" (Tristan Nolde):
Abstract siehe Datei in github.
Folgende Punkte wurden bei bzw. nach der Vorstellung des Abstracts diskutiert:
- Pros und Cons von WebScraping gegenüber RSS-Feeds und gegenüber der API-Lösung sollen dargestellt werden
- Die Quelle E-Mail-Newsletter (z.B. vom Handelsblatt) könnte ebenfalls interessant sein, jedoch muss hierfür möglicherweise ein separater E-Mail-Account erstellt werden, was eher aufwändig ist
- Es wäre eventuell zu prüfen, ob auch Daten aus LinkedIn API, XING oder Facebook extrahiert werden könnten.
### Vorstellung des Abstracts der Seminararbeit zu "Datenspeicherung" (Sebastian Zeleny):
Abstract siehe Datei in github.
Folgende Punkte wurden bei bzw. nach der Vorstellung des Abstracts diskutiert:
- Bei der Wahl der Datenbank müssen verschiedene Anforderungen berücksichtigt werden, mit hohem Abstimmungsbedarf zwischen den Topics "Datenextraktion" und "Datenvisualisierung"
- Herr Prof. Arinir fragte noch, ob wir das Thema "relationale Datenbanken" als Modul behandelt haben. Dies wurde bejaht, insbesondere SQL Datenbanken und SQL queries waren Gegenstand des Moduls "Datenbankprogrammierung"
### Vorstellung des Abstracts der Seminararbeit zu "Verpflechtungsanalyse" (Tim Ronneburg):
Abstract siehe Datei in github.
Folgende Punkte wurden bei bzw. nach der Vorstellung des Abstracts diskutiert:
- Beim Social Graph wäre zu überlegen, nicht nur Beziehungen zwischen Unternehmen via Personen (z.B. Wirtschaftsprüfer), sondern auch Beziehungen zwischen Unternehmen via Kooperationspartner (Stiftungen, Unis, Forschungsinstitute) bzw. Eigentums-, Kunden- und Lieferbeziehungen darzustellen
- Beim Social Graph wäre zu überlegen, ob man nach Art der Beziehung filtern könnte
### Vorstellung des Abstracts der Seminararbeit zu "Text Mining" (Sascha Zhu):
Abstract siehe Datei in github.
Folgende Punkte wurden bei bzw. nach der Vorstellung des Abstracts diskutiert:
- Bei den Sentiment-Analyse-Tools wie FinBERT oder VADER wäre stets eine maschinelle Übersetzung der deutschen Nachrichtentexte ins Englische erforderlich, da FinBERT oder VADER keine deutschen Texte erkennen können
- Die Generierung von Ontologien ist zu komplex und soll nicht Gegenstand der Projektarbeit sein
- Bei der semantischen Textanalyse wäre empfehlenswert, dass dies über "Einzel-Personen" ausgeführt wird (das wäre dann ein Punkt im Graphen)
- Das Thema "Named Entity Recognition" wird für die Projektarbeit eine hohe Bedeutung haben
### Vorstellung des Abstracts der Seminararbeit zu "Datenvisualisierung" (Kim Mesewinkel-Risse):
Abstract siehe Datei in github.
Folgende Punkte wurden bei bzw. nach der Vorstellung des Abstracts diskutiert:
- Bei der Datenvisualisierung wäre zu überlegen, dass man sich nur auf Python-Bibliotheken beschränkt
- Die Datenabfrage könnte über SQL oder Spark laufen, eine Schnittstelle zwischen dem Speicher und dem Front-End wird benötigt
- Zwischen Daten und der Datenvisualisierung werden eventuell Zwischen-Caches benötigt
- Bezüglich der Frage nach der „Middleware“: Wenn Plotly oder Plotly Dash verwendet wird, wird keine Middleware benötigt, da dies schon eingebaut ist.
### Feedback von Herrn Prof. Arinir:
- Es scheint noch kein Gesamtkonzept für das Gewerk vorzuliegen.
- Wir sollten uns die Frage stellen: Was soll am Ende für "ein brauchbares Stück Software" herauskommen, damit der Anwender mit der Vielzahl von Informationen und Funktionen zurechtkommt.
- Eine Lösungsskizze muss definiert werden, wobei ein Pflichtenheft jetzt noch nicht erforderlich ist
- Es sollen zunächst einige GUI-Designs (mit einem Muster-Datensatz) entwickelt werden.
- Pros und Cons zwischen einem Wasserfallmodell (Pflichtenheft mit bis zu 1000 Seiten) und der agilen Modellierung sollen berücksichtigt werden.
- Wie sollen die Verflechtungen eingebaut werden?
- Wie sollen die Daten persistiert werden?
- Es wäre empfehlenswert, mit irgendetwas (d.h. einer kleinen Lösung) anzufangen, dann das Ergebnis anzuschauen, und diese kontinuierlich zu verbessern.
## Abgeleitete Action Items
| Action Item | Verantwortlicher | Deadline |
|--------------------------------------------|------------------|-------------------|
| GUI Designs | Alle | nächstes Weekly |
| Rückmeldung zum Umfang der Seminararbeit | Prof. Arinir | nächstes Weekly |
## Aktueller Projektstand

View File

@ -0,0 +1,90 @@
# Weekly *5*: 09.06.2023
## Teilnehmer
- Prof. Arinir
- Tristan Nolde
- Tim Ronneburg
- Phillip Horstenkamp
- Kim Mesewinkel-Risse
- Sascha Zhu
- Sebastian Zeleny
## Themen
- Stepstone Projekt:
- Gewünscht wird ein initialer Austausch mit Stepstone
- Befürchtung ist, dass es zu einem Hinderniss wird
- Entscheidung liegt daher beim Projekt-Team
- Weitere Informationen sind nicht aktuell nicht vorhanden
- Vorschlag Prof. Arinir: Sollte das Thema nochmal zum Team getragen werden, wird der aktuelle Stand vorgestellt und der Link zum Repo wird geteilt. Darüber hinaus werden keine Ressourcen zugesprochen.
- Vorstellung [vorheriger Absprache](https://github.com/orgs/fhswf/projects/17?pane=issue&itemId=29707639) und Feedback:
- Ändert sich der Scope - Nein
- NDA - Nein
- Veröffentlichung - maximal Impressionen
- Was muss geleistet werden - nicht direkt an Stepstone sondern über FH als Mediator
- Sollen Präsentationen vorab zur Verfügung gestellt werden?
- Einige Tage vorher in das Git Repo. hochladen und Prof. Arinir benachrichtigen
- Rücksprache Seminarpräsentationen
- Verflechtungsanalyse:
- Graphen Theorie
- Social Network Analyse
- Erweiterung über Graphen Theorie hinaus
- Fokus auf Anwendung und Mehrwert, weniger genauer mathematischer Lösung
- Feedback:
- Präsentation scheint sehr umfangreich; Wunsch nach Reduzierung der Folienanzahl
- Formeln hinter den Analysen spannend, ggf. doch drauf eingehen, um Kennzahl in Kontext zu setzen
- Visualiserung:
- Prinzipien
- Vorteile
- Bibliotheken für Umsetzung (Network X, PyViz, ...)
- Effekt von Farbwahl
- Erste Umsetzung im Jupyter Notebook
- Feedback:
- Es werden extem viele Datenpunkte angezeigt werden müssen, wie wird dies in den Bibliotheken umgesetzt? Kann dort gefiltert werden?
- Wenn nicht direkt am Graphen (der Darstellung) gefiltert werden kann, dann frühzeitig filtern, bevor der Graph gebaut wird
- Datenspeicherung
- Erste Integration von Visualisierung mit Datenspeicherung
- Vorstellung der "Datencluster"
- Stammdaten
- Stimmungsdaten
- Social Graph
- Zeitseriendaten
- Relationales DB Modell
- Fokus ebenfalls auf Abfrage der Daten für Folge-Projekte wie Visualiserung und Mehrwert fürs Team, weniger Theorie
- Feedback:
- Es müssen Erfahrungen mit der Library und Darstellung gesammelt werden, um den Mehrwert der Lösung hervorzuheben
- Modellierung der Finzanz-Kennzahlen
- Spaltennamen sollen sprechend sein, z.B. "value" statt "sum"
- Präferenz zum Modell mit einzelnem Eintrag mit mehren Kennzahl Spalten stallt generischer Lösung über Enum
- Text Mining
- Fokus auf Sentiment Analyse
- Vergleich verschiedener Lösungen und ML Modelle
- Abschließendes Fazit, welches Tool am besten geeignet ist
- Daten Extraktion
- Fokus auf Web Mining/Scraping im Rahmen des Transparenzregisters
- Datenquellen
- API
- Websites (HTML)
- PDF
- Datenextraktion aus diesen Quellen
- Orchestrierung mit Airflow
- DevOps
- Dependency Management in Python
- Standard requirements.txt
- pip-tools
- poetry
- Vorteile von Lintern
- GitHub
- Actions
- Security
- etc.
- Feedback:
- Git wird als State-of-the-Art angesehen und muss nicht näher erläutert werden
## Abgeleitete Action Items
| Action Item | Verantwortlicher | Deadline |
|-------------|------------------|-----------------|
| Folien hochladen | Projekt Team | vor Präsentationstermin |
| Absprache Abgrenzung von Verflechtungsanalyse und Visualisierung | Tim und Kim | nächster Abgleich |
| Deployment Plan aufstellen | Projekt Team | nach Seminararbeiten |

View File

@ -0,0 +1,33 @@
# Weekly *5*: 25.05.2023
## Teilnehmer
- Prof. Arinir
- Tristan Nolde
- Tim Ronneburg
- Philipp Horstenkamp
- Kim Mesewinkel-Risse
- Sascha Zhu
- Sebastian Zeleny
## Themen
- Nächster Termin am 08.06.2023 ist Fronleichnam => Verschoben auf 09.06.2023 09:00
- Sebastian präsentiert das Miro Bord mit den Wireframediagrammen. [Siehe Anlage]()
- Philipp präsentiert den Sozial graph
- Sebastian präsentiert die Unternehmensdetails in sicht auf die Kennzahlen
- Sebastian dankt Kim für das Überarbeiten der Graphen im Farbschema
- Sebastian zeigt die anderen Übersichten
- Sascha weist darauf hin das zusätzlich noch das Quellmaterial für die Stimmungen mit angezeigt werden sollen.
- Die Form ist bisher noch unklar.
- Arinir: Auch indirekte verpflächtungen für N sprünge sollen bei den Details angezeigt werden und einen wert für den Einfluss von personen und Firmen sein.
- Zähle die Personenverbindungen juristisch/Natürlich getrennt nach den schichten der Indirektion. Interessant wäre eine auftrennung der natürlichen und Jiristischen personen in der Zählung
- Ranking der Personen nach Anzahl der Verbindungen
- Die Frage wie wir zeitliche veränderungen im sozial graph bewerten sollen kam auf. Wurde aber noch nicht abschließend beantwortet.
## Abgeleitete Action Items
| Action Item | Verantwortlicher | Deadline |
|------------------------------------------|------------------|-----------------|
| Erster entwurf der Seminarpräsentationen | Alle | nächstes Weekly |

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -0,0 +1,45 @@
**Abstract/Planung der Seminararbeit zu "Text Mining"**
**Sascha Zhu**
**10.05.2023**
Gliederung
1. Einleitung und Begriffsbestimmung
2. Text Mining Prozess
3. Verwendung von NLP-Methoden für das Text Mining
3.1 Morphologische Textanalyse
3.2 Syntaktische Textanalyse
3.3 Semantische Textanalyse
4. Ontologien und Text Mining
4.1 Verwendung von Ontologien als Grundlage der Textanalyse
4.2 Generierung von Ontologien mittels Text Mining ("ontology generation"/"ontology learning" )
5. Sentiment-Analyse als Teilgebiet des Text Minings
6. Zusammenfassung und Ausblick
Die Seminararbeit zu "Text Mining" soll in die oben genannten sechs Abschnitte gegliedert werden.
Nach einer Einleitung, in der der Begriff "Text Mining" näher definiert wird und gegenüber "Data Mining" und "Computational Linguistics" abgegrenzt wird, folgt der zweite Abschnitt zum Text Mining Prozess, der nach Hippner u. Rentzmann (2006) in die folgenden sechs Schritte eingeteilt wird: (a) Aufgabendefinition; (b) Dokumentenselektion; (c) Dokumentenaufbereitung; (d) Untersuchung mit Text-Mining-Methoden; (e) Interpretation und Evaluation; (f) Anwendung der Ergebnisse.
Im darauffolgenden dritten Abschnitt zur Verwendung von NLP-Methoden für das Text Mining werden die drei Phasen des Natural Language Processings (NLP), d.h. die morphologische, syntaktische und semantische Textanalyse, näher dargestellt, wobei der Schwerpunkt auf die semantische Analysetechniken wie z.B. "Word Sense Disambiguation" (WSD) und "Named Entity Recognition" (NED) liegen soll.
Der vierte Abschnitt soll sich dem Thema "Ontologien und Text Mining" widmen. Einerseits können Ontologien, die domänenspezifisches Wissen abbilden, als Grundlage für NLP-Methoden dienen, um etwa die semantische Textanalyse zu verbessern. Andererseits können mittels Text Mining automatisch bzw. semi-automatisch Ontologien als Repräsentation der Text-Mining-Ergebnisse erstellt werden ("ontology generation"/"ontology learning").
Im vorletzten, fünften Analyse soll die Sentiment-Analyse als Teilgebiet des Text Mining durchleuchtet werden. Dieser Abschnitt soll den Schwerpunkt der gesamten Seminararbeit darstellen. Die Methodik, Funktionsweise, Varianten und Use Cases der Sentiment Analyse sollen anhand ausgewählter Beispiele erläutert werden. Zudem sollen auch bekannte Sentiment-Analyse-Tools wie z.B. FinBERT, VADER, SentiWS etc. näher beschrieben werden.
Am Ende der Seminararbeit soll der sechste Abschnitt eine Zusammenfassung liefern und einen Ausblick darüber geben, in welche Richtung die zukünftige Entwicklung auf dem Gebiet des Text Minings gehen wird.

View File

@ -0,0 +1,47 @@
# Seminarthema: Datenvisualisierung
## Geplanter Inhalt:
- Einführung
- Best Practice für Datenvisualisierung
- Vorstellung verschiedener Diagrammarten
- Welche Diagrammarten eignen sich für unsere drei Anwendungsbereiche Time Series Daten, Netzwerke und Stimmungen?
- Betrachtung verschiedener Bibliotheken (z.B. D3Blocks, pyvis, plotly)
- Zweck der Bibliothek, unterstützte Visualisierungen, Vor- und Nachteile
- Minimalbeispiele
- Anwendung auf unser Projekt:
- Vergleich der Bibliotheken mit Blick auf unsere drei Anwendungsbereiche
- Welche Daten werden für die einzelnen Diagramme gebraucht?
- Welche Ideen/Anforderungen ergeben sich an die anderen Themenbereiche?
- Fazit und Handlungsempfehlung
- Welche Diagramme und welche Bibliotheken eignen sich für uns?
## Abstract:
In dieser Seminararbeit geht es um die Visualisierung von Daten in Python. Im Fokus steht die Anwendung auf die drei Themenbereiche, die im Projekt "Transparenzregister" behandelt werden: Time Series Daten, Soziale Netzwerke und Stimmungen. Nach einer Einführung in das Thema werden Best Practices für die Datenvisualisierung vorgestellt und verschiedene Diagrammarten präsentiert. Anschließend wird diskutiert, welche Diagramme für die genannten Anwendungsbereiche am besten geeignet sind.
Im zweiten Abschnitt werden verschiedene Python Bibliotheken vorgestellt und anhand von Minimalbeispielen betrachtet. Dabei wird analysiert, welche Bibliotheken die gewünschten Diagramme für unsere Anwendungsbereiche am besten darstellen und welche Daten für die Erstellung der verschiedenen Diagramme benötigt werden. Es werden zudem Ideen und Anforderungen an die anderen Themenbereiche aufgezeigt.
Im letzten Abschnitt der Arbeit wird ein Fazit gezogen und eine Handlungsempfehlung gegeben. Insgesamt soll die Arbeit einen Einblick in die Welt der Datenvisualisierung in Python geben und unserem Projekt helfen, die richtigen Entscheidungen bei der Wahl der Diagrammarten und Bibliotheken zu treffen.
## Erste Sammlung von Referenzen:
Bibliotheken/Tools:
- D3Blocks: [Documentation](https://d3blocks.github.io/d3blocks/pages/html/index.html), [Medium Blog](https://towardsdatascience.com/d3blocks-the-python-library-to-create-interactive-and-standalone-d3js-charts-3dda98ce97d4)
- pyvis: [Documentation](https://pyvis.readthedocs.io/en/latest/tutorial.html)
- networkx: [Documentation](https://networkx.org/documentation/stable/auto_examples/index.html), [Example](https://www.kirenz.com/post/2019-08-13-network_analysis/)
- plotly: [Documentation](https://plotly.com/python/#animations)
Netzwerke:
- Zentralitätsmaße: [Medium Blog](https://towardsdatascience.com/social-network-analysis-from-theory-to-applications-with-python-d12e9a34c2c7)
- Visualisierungsideen: [Medium Blog](https://towardsdatascience.com/visualizing-networks-in-python-d70f4cbeb259)
Kennzahlen:
- Visualisierungsideem: [Towards AI](https://towardsai.net/p/l/time-series-data-visualization-in-python)
Best Practice:
- [Science Direct](https://www.sciencedirect.com/science/article/pii/S2666389920301896)
- [Toptal](https://www.toptal.com/designers/data-visualization/data-visualization-best-practices)

View File

@ -0,0 +1,35 @@
---
title: "Automatisierte Daten Extraktion aus Internetquellen als Grundlage für die Analyse von Kapitalgesellschaften"
author: "Nolde, Tristan Norbert"
date: "2023-05-06"
---
# Abstract: Automatisierte Daten Extraktion aus Internetquellen als Grundlage für die Analyse von Kapitalgesellschaften
## Gliederung
1. Einleitung (Zielsetzung/Problemstellung, Vorgehen)
2. Web Scraping/Crawling
1. Definition und Theorie
2. Technologien
3. Umsetzung
3. RSS Feeds
1. Definition und Theorie
2. Technologien
3. Umsetzung
4. APIs
1. Definition und Theorie
2. Technologien
3. Umsetzung
5. Rechtliche Rahmenbedingungen
6. Vergleich der Lösungsansätze
7. Zusammenfassung
## Inhalt
In Zeiten von Big Data und AI stellen Daten und ihre Verfügbarkeit zunehmend eines der wichtigsten Wirtschaftsgüter dar. Als solches können sie auch eingesetzt werden, um Kapitalgesellschaften (eine Subklasse von Unternehmen) anhand verschiedener Kennzahlen wie der Mitarbeiterzahl oder dem Jahresgewinn zu analysieren. Obwohl solche Daten zu Genüge in Zeitungsartikeln, Newslettern oder dedizierten Aktienanalysen zu finden sind, so gestaltet sich eine automatisierte Extraktion dieser Daten aufgrund verschiedener Formate sowie weiterer Restriktionen schwierig.
Daher sollen im Rahmen dieser Seminararbeit verschiedene Wege betrachtet werden, die eben diese Daten erheben und zur Verfügung stellen können. Zu den nennenswerten Quellen gehören: Der Bundesanzeiger, RSS Feeds, Nachrichten APIs. Ziel ist es, aus diesen Quellen wertvolle Informationen bezogen auf den wirtschaftlichen Erfolg einer Kapitalgesellschaft sowie aktueller Nachrichten zu extrahieren und in ein einheitliches Format zu überführen.
Neben des technischen Einsatzes von Web Scraping/Crawling, um Informationen aus Webseiten zu gewinnen, sowie des Abfragens verfügbarer APIs soll auch der rechltiche Aspekt dieser Vorgehens Berücksichtigung finden, um die Rechtmäßigkeit zu bewerten.
Abschließend wird der Einsatz der verschiedenen Technologien an den Faktoren: Flexibilität, Simplizität, Verfügbarkeit und Rechtmäßigkeit, ein Fazit gezogen sowie ein Ausblick des weiteren Einsatzes gegeben.

View File

@ -0,0 +1,748 @@
![Front](images/Front.PNG)
<div style="page-break-after: always;"></div>
# Datenspeicherung
## Inhaltsverzeichnis
- [Datenspeicherung](#datenspeicherung)
- [Inhaltsverzeichnis](#inhaltsverzeichnis)
- [Motivation: Warum speichern wird Daten?](#motivation-warum-speichern-wird-daten)
- [1. Allgemeine Anforderungen an Datenbank](#1-allgemeine-anforderungen-an-datenbank)
- [2. Datenarten](#2-datenarten)
- [2.1 Welche Daten erwarten wir im Projekt?](#21-welche-daten-erwarten-wir-im-projekt)
- [2.2 strukturierte Daten](#22-strukturierte-daten)
- [2.3 unstrukturierte Daten](#23-unstrukturierte-daten)
- [3. Arten von Datenbanken](#3-arten-von-datenbanken)
- [3.1 Relationale Datenbank](#31-relationale-datenbank)
- [3.1.1 Anlegen von Tabellen](#311-anlegen-von-tabellen)
- [3.1.2 SQL - Abfrage von relationalen Datenbanken](#312-sql---abfrage-von-relationalen-datenbanken)
- [3.2 Graphdatenbank](#32-graphdatenbank)
- [3.2.1 Erstellung eines Datensatzes](#321-erstellung-eines-datensatzes)
- [3.2.2 Cypher - Abfrage von Graphdatenbanken](#322-cypher---abfrage-von-graphdatenbanken)
- [3.3 Zeitseriendatenbank](#33-zeitseriendatenbank)
- [3.3.1 Erstellung eines Datensatzes](#331-erstellung-eines-datensatzes)
- [3.3.2 FluxQuery](#332-fluxquery)
- [3.4 Dokumenten Datenbank ](#34-dokumenten-datenbank-)
- [3.4.1 Erstellen einer Collection / Ablegen von Dokumenten](#341-erstellen-einer-collection--ablegen-von-dokumenten)
- [3.5 Aufbau einer Datenbank](#35-aufbau-einer-datenbank)
- [4. Datenbanken Transparenzregister](#4-datenbanken-transparenzregister)
- [4.1 Production DB - relationales Datenbankmodell](#41-production-db---relationales-datenbankmodell)
- [4.2 Staging DB](#42-staging-db)
- [4.3 SQL Alchemy](#43-sql-alchemy)
- [5. Proof of Concept](#5-proof-of-concept)
- [5.1 Docker](#51-docker)
- [5.2 PG Admin](#52-pg-admin)
- [5.3 Erstellen von Mock Daten](#53-erstellen-von-mock-daten)
- [5.4 Anlegen der relationalen Tabellen](#54-anlegen-der-relationalen-tabellen)
- [5.5 Abfragen der Datenbank](#55-abfragen-der-datenbank)
- [6. Zusammenfassung](#6-zusammenfassung)
- [Quellen](#quellen)
<div style="page-break-after: always;"></div>
## Motivation: Warum speichern wird Daten?
Für die Speicherung von Daten gibt es verschiedene Motivationen:
- **Sammlung:** Zur Aufbewahrung von Wissen und Informationen über Objekte, Ereignisse oder Prozesse werden Daten gespeichert.
- **Historisierung:** Durch die Speicherung von Daten in einem zeitlichen Zusammenhang, wird eine Historie erstellt, mit welcher Muster, Trends oder Zusammenhänge erkannt werden können. Historische Daten helfen ausserdem bei der Entscheidungsfindung.
- **Bewertung:** Mit gespeicherten Daten können Systeme, Produkte und Prozesse nachvollzogen, bewertet und verbessert werden.
Im Projekt Transparenzregister ist die Datenspeicherung eine Kernkomponente, da die gesammelten Informationen die Grundlage für Analysen darstellen. \
Mit geeigneten Pipelines werden aus diesen Daten Erkenntnisse extrahiert, um z.B. Verflechtungen zwischen Personen und Unternehmen oder den wirtschaftlichen Trend eines Unternehmens visualisieren und bewerten zu können.
## 1. Allgemeine Anforderungen an Datenbank
- **1.1 Speicherung/Integrität**: Das verwendete System muss Daten, wie Unternehmenskennzahlen, Stammdaten und Verflechtungen speichern. Die Daten müssen korrekt und konsistent gespeichert werden. Konsistent bedeutet in einem gültigen und widerspruchsfreien Zustand und die Transaktionen sollen den ACID-Eigenschaften entsprechen.
- **Atomarity:** Eine Transaktion wird atomar betrachte, d.h. es ist die kleinste unteilbare Einheit, wodurch eine Transaktion entweder vollständig durchgeführt und übernommen wird (Commit) oder bei einem Fehler rückgängig gemacht wird (Rollback).
- **Consistency:** Konsistenz bedeutet, dass eine Transaktion den Datenbankzustand von einem gültigen in einen anderen gültihgen Zustand überführt. Sollte eine Transaktion eine Konsitenzverletzung verursachen, wird diese abgebrochen und die Änderungen zurückgesetzt.
- **Isolation:** Isolation sorgt dafür, dass alle Transaktion unabhängig voneinander ausgeführt werden, damit sich diese bei der Ausführung nicht gegenseitig beeinflussen.
- **Durability:** Dauerhaftigkeit bedeutet, dass die Ergebnisse einer Transaktion dauerhaft in der Datenbank gespeichert werden und auch nach einem Systemneustart oder Systemfehler erhalten bleiben.
- **1.2 Skalierbarkeit:** Das System soll skalierbar sein, um zukünftige Daten weiterhin zu speichern und weitere Unternehmen hinzuzufügen. Durch Hinzufügen von Ressourcen kann das System an steigende Datenmengen und Benutzeranforderungen angepasst werden. Man spricht von horizontaler Skalierung, da die Last auf mehrere Datenbankserver verteilt wird.
- **1.3 Sicherheit:** Die Datenbank muss Mechanismen bereitstellen, um die Daten vor unbefugtem Zugriff zu schützen.
- **Authentifizierung:** Überprüfung der Identität eines Benutzers, durch Benutzername und Passwort. Meist wird eine Zwei-Faktor-Authentifizierung verwendet, um das Sicherheitslevel zu erhöhen.
- **Autorisierung:** Der authentifizierte Benutzer erhält bei der Autorisierung Zugriffsrechte und Ressourcen, welche auf seiner Benutzerrolle basieren. Ein Benutzer mit Administratorrechten, erhält Zugriff auf alle Systemressourcen, wohingegen ein normaler Benutzer nur beschränkten Zugriff erhält.
- **Verschlüsselung:** Durch Verschlüsselung werden Daten in ein nicht interpretierbaren Code umgewandelt, um den Inhalt vor unbefugtem Zugriff zu schützen. Dafür wird ein Algorithmus verwendet, welcher einen Schlüssel generiert und die Daten mit diesem verschlüsselt. Um die Daten wieder lesen zu können, müssen diese mit dem Schlüssel dechiffriert werden.
- **1.4 Datensicherung- und Wiederherstellung:** Die Datenbank muss Funktionen zur Sicherung und Wiederherstellung unterstützen. Im Falle eines Ausfalls oder Fehlers muss sichergestellt sein, dass Mechanismen die Daten schützen und wiederherstellen.
Die meisten Daten in einer Datenbank ändern sich nur langsam, manche allerdings schnell. Je nach Anwendungsfall muss eine geeignete Sicherungsstrategie ausgewählt werden, um nur die Daten zu sichern, die sich tatsächlich ändern.
Jedes Datenbankmanagementsystem bietet unterschiedliche Mechanismen zur Datensicherung und Wiederherstellung, dessen Möglichkeiten nach Auswahl eines Systems
- **vollständiges Backup:** Das vollständige Backup ist eine komplette Kopie der Datenbank inkl. aller Daten, Indizes, Tabellen und Metadaten. Es benötigt viel Speicherplatz und Zeit zur Erzeugung der Sicherung und auch zur Wiederherstellung.
- **inkrementelles Backup:** Ein inkrementelles Backup sichert nur die Änderungen seit dem letzten vollständigem bzw. inkrementellen Backup. Durch den verringerten Datenbestand ist es deutlich schneller und datensparsamer, als das vollständige Backup. Zur Wiederherstellung wird das letzte vollständige und alle inkrementellen Backups benötigt. Allerdings entsteht eine Abhängigkeitskette, da jedes Backup seine Vorgänger zur Wiederherstellung benötigt.
- **differentielles Backup:** Beim differentiellen Backup werden alle Änderungen seit dem letzten vollständigem Backup gesichert. D.h. je weiter die letzte vollständige Sicherung zurückliegt, desto größer und langsamer wird das Backup. Zur Wiederherstellung werden das letzte vollständige und differentielle Backup benötigt.
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({ tex2jax: {inlineMath: [['$', '$']]}, messageStyle: "none" });
</script>
**Backuphäufigkeit:**
Die Backuphäufigkeit ist eine Abwägung aus Risiken, Kosten und Arbeitsaufwand. Dieses muss individuell abgeschätzt werden aufgrund des Datenbankumfangs und der Änderungshäufigkeit der Daten, um eine geeignete Backup-Strategie zu entwerfen. \
*Beispiel:*
- Vorgabe: Datenbank mit 500GB Größe
- Anforderungen
- min. vierfache Backupkapazität --> 2 TB
- Backupdauer vollständig: \
USB 2.0:$\frac {500GB}{\frac{60MB/s}{1024}} = 8533 sec. \approx 142Min. \approx 2,37 Std.$ \
USB 3.0:$\frac {500GB}{\frac{625MB/s}{1024}} = 820 sec. \approx 13,6Min. \approx 0,23 Std.$ \
VDSL 100:$\frac {500GB}{\frac{5MB/s}{1024}} = 102400 sec. \approx 1706Min. \approx 28,4 Std.$ \
Glasfaser:$\frac {500GB}{\frac{62,5MB/s}{1024}} = 8192 sec. \approx 136,5Min. \approx 2,3 Std.$
- **1.5 Leistung:** Die Performanceanforderungen an die Datenbank ergibt sich aus verschiedenen Merkmalen. Diese können kombiniert gestellt werden und sind abhängig von den Anforderungen an das System. Eine Analyse der Anwendungsfälle ist notwendig, um die Anforderungen zu spezifizieren.
- **Latenz:** Die Datenbank soll Anfragen effizient und in einer akzeptablen Antwortzeit verarbeiten. Typische Datenbankapplikationen, wie z.B. ein Webshop benötigen viele einzelne Zugriffe, wofür jedes Mal ein Kommunikationsprotokoll angewendet wird. Durch viele kleine Datenbankzugriffe wird die Applikation verlangsamt, da auf die Netzwerkkommunikation gewartet wird. Für das Benutzererlebnis eines Webshops ist die Latenz ein wichtiges Merkmal.
- **Durchsatz:** Ist eine Metrik für die Anzahl an Transaktionen pro Zeiteinheit. Der Durchsatz ist wichtig bei großen Benutzeraufkommen in einem Webshop.
- **Verfügbarkeit:** Eine hohe Verfügbarkeit, also Erreichbarkeit der Datenbank, wird durch Redundanz (mehrfaches Vorhandensein) und Wiederherstellungsmechanismen gewährleistet, damit Daten koninuierlich verfügbar sind.
- **Wartbarkeit:** Eine einfach zu wartende Datenbank muss Funktionen zur Überwachung, Diagnose, Wartung, Datensicherung und Wiederherstellung bereitstellen. Durch diese automatisierten Pipelines können andere Eigenschaften, wie z.B. die Verfügbarkeit negativ beeinflusst werden, weil Prozesse die Datenbank blockieren.
- **1.6 Integration:** Die Datenbank muss Schnittstellen bereitstellen, um die gespeicherten Daten für eine Anwendung bzw. Systeme zur Verfügung zu stellen.
- **API:** Das *Application Programming Interface* ist eine definierte Schnittstelle, welche Methoden und Funktionen bereit stellt, um auf die Datenbank zuzugreifen bzw. um diese zu verwalten.
- **REST:** REpresential State Transfer beschreibt eine Schnittstelle, die das http-Protokoll verwendet, wo mit den Methoden GET, POST, PUT, DELETE die Kommunikation realisiert wird.
- **SOAP:** Simple Object Access Protocol ist eine Schnittstelle, welche auf XML basiert.
- **ODBC:** Open Database Connectivity ist eine standardisierte Schnittstelle zum Austausch zwischen Anwendungen und Datenbanken.
- **JDBC:** Java Database Connectivity
## 2. Datenarten
Zur Beschreibung von Unternehmen, werden verschiedene Datenarten verwendet.
Die folgenden Datenarten sind eine allgemeine Zusammenfassung und sollen das Brainstorming für die projektspezifischen Daten unterstützen.
- **Stammdaten:** Stammdaten beinhalten die grundsätzlichen Eigenschaften und
Informationen von realen Objekten, welche für die periodische Verarbeitung notwendig sind. Ein Stammsatz für Personal besteht z.B. aus einer Personalnummer, dem Mitarbeiternamen, Anschrift und Bankverbindung. \
Je nach Anwendungsfall bzw. Geschäftsprozess muss der Inhalt definiert werden, wie z.B. bei Unternehmens-, Kunden-, Material- oder Patientenstammdaten.
- **Metadaten:** Mit Metadaten werden weitere Daten beschrieben und vereinfachen das Auffinden und Arbeiten mit diesen. Metadaten beinhalten beispielsweise den Verfasser, das Erstellungs- oder Änderungsdatum, die Dateigröße oder den Ablageort. \
Mit Metadaten können Datenbestände einfacher und effizienter verwaltet und abgefragt werden.
- **Transaktionsdaten:** Transaktionsdaten beschreiben eine Veränderung des Zustands, wie z.B. eine Kapitalbewegung oder eine Ein-/Auslieferung aus einem Lager.
- **Referenzdaten:** Referenzdaten sind eine Teilmenge von Stammdaten und beschreiben die zulässigen Daten. Diese werden nur selten geändert oder angepasst und gelten als konstant. Beispiele für Referenzdaten sind: Postleitzahlen, Kostenstellen, Währungen oder Finanzhierarchien.
- **Bestandsdaten:** Bestandsdaten sind dauerhafter Veränderung ausgesetzt, da diese z.B. die Artikelmenge in einem Lager oder das Guthaben auf einem Konto beschreiben. Diese korrelieren mit den Transaktionsdaten.
Diese Datenarten müssen im Kontext des Projektes betrachtet werden und sollen das Brainstorming unterstützen. \
*Stammdaten:* Unternehmensname, Anschrift, Branche \
*Metadaten:* Verfasser einer Nachricht - Veröffentlichungsdatum; Prüfungsunternehmen - Prüfdatum \
*Transaktionsdaten:* Wer hat wann wo gearbeitet? \
*Referenzdaten:* Einheit von Metriken (Umsatz, EBIT usw.) \
*Bestandsdaten:* Vorstand, Geschäftsführer, Aufsichtsrat
### 2.1 Welche Daten erwarten wir im Projekt?
Aus den vorangehenden, allgemeinen Datenarten haben wir Cluster identifiziert, welche im Projekt benötigt werden.
Die Kombination aus den folgend aufgeführten Datenclustern ermöglicht eine ganzheitliche Betrachtung und Bewertung der Unternehmen.
- **Unternehmensstammdaten:** Die Stammdaten beinhalten grundlegende Informationen zu einem Unternehmen, wie z.B. Name, Anschrift, Gesellschaftsform und Branche.
- **Sentimentdaten:** Die Sentiment- oder Stimmungsdaten beschreiben die Aussenwahrnehmung des Unternehmens hinsichtlich der Mitarbeiterzufriedenheit, Nachhaltigkeit und Umweltfreundlichkeit.
> Mit Sentimentdaten können folgende Fragen beantwortet werden:
>- Welchen Ruf hat das Unternehmen?
>- Wie ist die Aussenwahrnehmung?
>- Wie ist die Kundenbindung?
- **Finanzdaten:** Die Finanzdaten sind Metriken bzw, Indikatoren, um den wirtschaftlichen Erfolg des Unternehmens zu bewerten. Hierzu zählen z.B. Umsatz, EBIT, EBIT Marge, Bilanzsumme, Eigenkapitalanteil, Fremdkapitalanteil, Verschuldungsgrad, Eigenkapitalrentabilität, Umschlaghäufigkeit des Eigenkapitals.
> Mit Finanzdaten können folgende Fragen beantwortet werden:
>- Wie rentabel wirtschaftet das Unternehmen?
>- Wie ist der wirtschaftliche Trend?
>- Bewerten anhand verschiedender Metriken.
- **Verflechtungsdaten/Social Graph:** Die Verbindungen bzw. Beziehungen zu Personen oder Unternehmen wird in den Verflechtungsdaten abgelegt. Beziehungen entstehen, wenn eine Person Geschäftsführer, Vorstand, Aufsichtsratmitglied, Prokurist oder Auditor ist und Unternehmen z.B. gemeinsam arbeiten, beliefert wird oder Anteile an einem anderen Unternehmen besitzt.
> Mit Verflechtungsdaten können folgende Fragen beantwortet werden:
>- Gibt es strategische Partnerschaften?
>- Wie sind die Lieferketten aufgebaut?
>- Wie ist die Qualität der Geschäftsbeziehungen?
>- Ist das Unternehmen widerstandsfähig aufgestellt?
>- Gibt es Zusammenhänge zu Personen?
Die abgebildete Mind Map ist nicht vollständig und bildet nicht den finalen Datenumfang des Projekts ab. Es ist eine Momentaufnahme, bevor das relationale Schema entwickelt und die Implementierung begonnen wurde.
![Data_Clusters](/documentations/seminararbeiten/Datenspeicherung/images/Data_Cluster.PNG)
### 2.2 strukturierte Daten
Strukturierte Daten liegen in einem definierten Format. Vorab wird ein Schema definiert, um Felder, Datentypen und Reihenfolgen festzulegen und die Daten entsprechend abzulegen.
Diese Art von Daten wird z.B. in relationalen Datenbanken verwendet, wobei jede Zeile einer Tabelle einen Datensatz repräsentiert. Die Beziehungen untereinander sind über die Entitäten definiert.
Das Beispiel unten zeigt ein einfaches Beispiel, wie die Daten für die Klasse *Company* definiert sind. Mit diesem Schema kann die Datenaufbereitung umgesetzt werden.
```mermaid
---
title: Structured Data
---
classDiagram
class Company:::styleClass {
int ID
string Name
string Street
int ZipCode
}
```
|Vorteile|Nachteile|
|:-----:|:------:|
|einfach nutzbar, da organisiert |Einschränkung der Verwendungsmöglichkeit durch Schema |
| bei bekannten Schema sind Werkzeuge vorhanden|begrenze Speichermöglichkeit, da starre Schemata vorgegeben sind |
|gut automatisierbar | |
### 2.3 unstrukturierte Daten
Unstrukturierte Daten unterliegen keinem Schema, wie z.B. E-Mails, Textdokumente, Blogs, Chats, Bilder, Videos oder Audiodateien.
- **Textanalyse:** Aus unstrukturierten Texten werden z.B. durch Analyse und Mining Informationen gewonnen, um diese zu extrahieren. Es wird das Vorkommen von bestimmten Wörtern mittels Named Entity Recognition ermittelt oder die Stimmung bzw. das Thema in einem Artikel.
- **Audio-/Videoanalyse:** Bei der Verarbeitung unstrukturierter Audio- oder Videodateien werden Objekte, Gesichter, Stimmen oder Muster erkannt, um diese für Sprachassistenten oder autonome Fahrzeuge nutzbar zu machen.
Eine wichtige Informationsquelle sind unstrukturierte Daten für Explorations- und Analyseaufgaben. Dabei werden Datenquellen wie z.B. E-Mails, RSS-Feeds, Blogs durchsucht, um bestimmte Informationen zu finden oder Zusammenhänge zwischen verschiedenen Quellen hherzustellen. Dies ermöglicht tiefe Einsicht in die Daten zu erhalten und unterstützt die Entscheidungsfindung bei unklaren Sachverhalten und die Entdeckung neuer Erkenntnisse.
|Vorteile|Nachteile|
|:-----:|:------:|
|großes Potenzial Erkenntnisse zu erlangen |aufwändige Bearbeitung notwendig, um Daten nutzbar zu machen|
|unbegrenzte Anwendungsmöglichkeiten, da kein Schema vorhanden ist|spezielle Tools zur Aufbereitung notwendig|
| |Expertenwissen über die Daten und Datenaufbereitung notwendig |
## 3. Arten von Datenbanken
### 3.1 Relationale Datenbank
Eine relationale Datenbank speichert und verwaltet strukturierte Daten. Dabei werden die Daten in Tabellen organisiert, welche aus Zeilen und Spalten bestehen. \
In den Zeilen der Tabellen sind die Datensätze gespeichert, d.h. jede Zeile repräsentiert einen Datensatz. Durch logisches Verbinden der Tabellen können die Beziehungen zwischen den Daten abgebildet werden. \
Die wichtigsten Elemente einer relationalen Datenbank werden folgend erklärt:
**Tabelle:** Eine Tabelle repräsentiert eine Entität bzw. Objekt , wie z.B. Unternehmen, Kunde oder Bestellung. Die Tabelle besteht aus Spalten, welche die Attribute der Entität speichern. \
Jede Zeile ist eine Instanz des Objekts und enthält konkrete Werte.
**Table_Person**
|**ID**|**Name**|**Age**|**Salary**|**Height**|
|---|---|---|---|---|
|1|Tim|31|300.00|191.20|
|2|Tom|21|400.00|181.87|
|3|Tam|51|500.00|176.54|
https://www.sqlservercentral.com/articles/creating-markdown-formatted-text-for-results-from-sql-server-tables
**Primärschlüssel:** Der Primärschlüssel ist ein eindeutiger Bezeichner für jede einzelne Zeile einer Tabelle und wird zur Identifikation einer einzelnen Zeile benötigt. Im oberen Beispiel ist die Spalte *ID* der Primärschlüssel.
**Fremdschlüssel:** Ein Fremdschlüssel verweist auf einen Primärschlüssel einer anderen Tabelle, um eine Beziehung zwischen den Tabellen herzustellen. \
Im Beispiel ist bezieht sich die Spalte *customer_id* auf den Primärschlüssel der Tabelle *Table_Person*.
**Table_Orders**
|**ID**|**Product**|**total**|**customer_id**|
|---|---|---|---|
|1|Paper|12|2|
|2|Book|3|2|
|3|Marker|5|3|
**Beziehungen:** Wie bereits beschrieben, können mit der Verwendung von Fremdschlüsseln Beziehungen zwischen den Tabellen hergestellt werden. \
Es gibt verschiedene Beziehungstypen:
|**Typ**|**Beschreibung**|
|---|---|
|1:1|Jeder Primärschlüsselwert bezieht sich auf nur einen Datensatz. **Beispiel:** Jede Person hat genau eine Bestellung. |
|1:n|Der Primärschlüssel ist eindeutig, tritt in der bezogenen Tabelle 0..n mal auf. **Beispiel:** Jede Person kann keine, eine oder mehrere Bestellungen haben. |
|n:n|Jeder Datensatz von beiden Tabellen kann zu beliebig vielen Datensätzen (oder auch zu keinem Datensatz) stehen. Meist wird für diesen Typ eine dritte Tabelle verwendet, welche als Zuordnungs- bzw. Verknüpfungstabelle angelegt wird, da andernfalls keine direkte Verbindung hergestellt werden kann. |
https://www.ibm.com/docs/de/control-desk/7.6.1.2?topic=structure-database-relationships
#### 3.1.1 Anlegen von Tabellen
Der Umgang von relationalen Datenbanken erfolgt mittels SQL. Folgend ein Beispiel zum Anlegen einer Tabelle mit Attributen.
```
CREATE TABLE Bildungsstaette (
ID INT PRIMARY KEY NOT NULL,
Name VARCHAR(255) NOT NULL,
Anschrift VARCHAR(255),
Art VARCHAR(100)
);
```
#### 3.1.2 SQL - Abfrage von relationalen Datenbanken
Für die Verwaltung und Abfrage wird SQL (Structured Query Language) verwendet.
Mit dieser Syntax können Tabellen erstellt, Daten eingefügt, aktualisiert und gelöscht und Daten abgefragt werden.
**Anzeige aller Attribute einer Tabelle:**
```
SELECT * FROM table_name;
```
**Anzeige definierter Attribute einer Tabelle:**
```
SELECT column1, column2 FROM table_name;
```
**Gefilterte Anzeige einer Tabelle:**
```
SELECT * FROM table_name WHERE condition;
```
**Daten aus mehreren Tabellen abrufen (Join):**
```
SELECT t1.column1, t2.column2
FROM table1 t1
JOIN table2 t2 ON t1.id = t2.id;
```
### 3.2 Graphdatenbank
Eine Graphdatenbank basiert auf dem Graphenkonzept. \
Ein Graph besteht aus Knoten und Kanten (Beziehungen), welche die Verbindungen zwischen den Knoten darstellen. \
Die Stärke der Graphdatenbank liegt in der Darstellung von komplexen Beziehungen.
**Knoten:** Jeder Knoten repräsentiert eine Entität bzw. Objekt. Jeder Knoten hat eine eindeutige ID oder Bezeichner, um auf diesen zugreifen zu können. Es können auch Attribute hinterlegt werden, um zusätzliche Informationen zu speichern, wie z.B. Geburtsjahr, Wohnort einer Person.
**Kanten:** Die Kanten verbinden die Knoten und repräsentieren damit die Beziehungen unter den Objekten. Die Kanten können gerichtet und ungerichtet sein. Bei einer gerichteten Beziehung muss die Richtung vom Quell- zum Zielknoten beachtet werden, wohingegen eine ungerichtete Kante eine symmetrische Beziehung darstellt. \
*gerichtete Beziehung:* Ein Unternehmen ist abhängig vom Bericht des Wirtschaftsprüfers. \
*ungerichtete Beziehung:** Unternehmen A arbeitet gemeinsam mit Unternehmen B an einem Projekt.
**Label:** Label werden verwendet, um die Knoten zu kategorisieren/gruppieren. Ein Knoten kann auch mehrere Label besitzen, um die Zugehörigkeit an verschiedenen Kategorien darzustellen (z.B. Unternehmensbranche).
#### 3.2.1 Erstellung eines Datensatzes
1. Knotenerstellung: Es wird zuerst ein Knoten erstellt, der die Entität repräsentiert.
2. ID: Der Knoten benötigt eine eindeutige Identifikationsnummer, welche automatisch erzeugt oder manuell festgelegt werden kann.
3. Knoten einfügen: Wenn die beiden notwendigen Elemente (Knoten und ID) festgelegt sind, kann der Knoten eingefügt werden.
4. Beziehungen/Kanten festlegen: Wenn der Knoten Beziehungen zu anderen Knoten hat, können diese hinzugefügt werden.
**Beispiel:**
Folgender Code legt in neo4j zwei Knoten und die entsprechenden Beziehungen an.
```
CREATE (:University {id: 4711, name: 'FH SWF - Iserlohn'}),
(:University {id: 1234, name: 'FH SWF - Meschede'})
WITH *
MATCH (u1:University {id: 4711}), (u2:University {id: 1234})
CREATE (u1)-[:cooparates_with]->(u2),
(u2)-[:cooparates_with]->(u1)
```
![Graph_example](images/Graph.png)
#### 3.2.2 Cypher - Abfrage von Graphdatenbanken
Um Daten abzufragen wird die Abfragesprache Cypher verwendet.\
Es werden folgend nur einige grundlegende Befehle gezeigt.\
**Abfrage aller Knoten**
```
MATCH (n)
RETURN n
```
**Abfrage aller Kanten/Beziehungen**
```
MATCH ()-[r]-()
RETURN r
```
**Abfrage von Knoten mit definierten Eigenschaften**
```
MATCH (n:Label)
WHERE n.property = value
RETURN n
```
**Beziehung zwischen zwei Knoten abfragen**
```
MATCH (n1)-[r]->(n2)
WHERE n1.property = value1 AND n2.property = value2
RETURN r
```
### 3.3 Zeitseriendatenbank
Zeitserien fallen überall dort an, wo eine Metrik zeitlich betrachtet wird, wie z.B. Umsatz oder EBIT.
D.h. zu jedem Messwert gibt es einen zeitlich zugeordneten Zeitstempel, wobei die einzelnen Zeitpunkte zu einer Serie zusammengefasst werden, um den Zusammenhang zu betrachten. \
Diese Datenbanken sind spezialisiert auf die Speicherung, Verwaltung und Abfrage von Zeitserien. \
Die folgenden Erklärungen beziehen sich auf die InfluxDB.
**Bucket:** Der Bucket separiert Daten in verschiedene Speicher und ist mit der Datenbank bei relationalen Datenbanken vergleichbar.
**Datapoint:** Unter dem Bucket werden die Datenpunkte gespeichert. Ein Datapoint setzt sich aus mehreren Elementen zusammen, welche erorderlihc oder optional sind:
|**Element**|**Eigenschaft**|
|---|---|
|Measurement |Datentyp: String<br>Leerzeichen sind verboten<br>Max. 64kB|
|Tags| Sind optional<br> Bestehen aus einem Key/Value-Paar <br> Datentyp: String <br>Leerzeichen sind verboten <br> Max. 64 kB|
|Fields| Min. 1 Field=value Paar wird benötigt <br> Nicht alle Felder müssen in jedem Punkt vorhanden sein <br> Datentypen: Float, String, Integer, Boolean|
|Timestamp| Sind optional <br>Influx schreibt standardmäßig die Systemzeit als Zeitstempel <br>Genauigkeit kann eingestellt werden (Default: Nanosekunden)|
#### 3.3.1 Erstellung eines Datensatzes
Die Einrichtung von Zeitseriendatenbanken erfolgt mit der CLI von Influx.
**Anlegen eines Buckets:**
```
CREATE DATABASE finance
```
#### 3.3.2 FluxQuery
Zur Abfrage von Datenpunkten gibt es FluxQuery, welche sich stark an SQL orientiert. \
**Abrufen aller Daten aus Bucket:**
```
from(bucket: "my-bucket")
```
**Festlegen des Zeitbereich:**
```
range(start: -1h, stop: now())
```
**Filtern nach Bedingungen:**
```
filter(fn: (r) => r._measurement == "temperature")
```
**Transformieren von Datenpunkten:**
```
map(fn: (r) => ({r with temperatureF: r.temperature * 2.34 + 123}))
```
### 3.4 Dokumenten Datenbank <a name="3.4"></a>
Eine Dokumentendatenbank ist ein System, welches für das Speichern von Dokumenten entwicklet wurde. Es gibt verschiedene Arten von Dokumenten, wie z.B. Textdateien (JSON, HTML, XML) oder PDF.
Es muss kein Schema für die Dokumente festgelegt werden, dadurch ist es möglich Dokumente mit verschiedenen Datenfeldern zu speichern.
Gleiche oder ähnliche Dokumente werden gemeinsam in *Collections* gespeichert.
Die wichtigsten Elemente einer Dokumenten-Datenbank sind:
**Database:** Unter Database versteht man einen Container, unter welchem Dokumente gespeichert werden. Dies dient der Isolierung bzw. logischen Trennung von Daten.
**Collection:** Collections werden verwendet, um Dokumente mit ähnlichen Eigenschaften zusammenzufassen. Da Dokumenten-Datenbanken schemenlos sind, dienen die Collections der Organisation.
**Document:** Das Dokument ist ein einzelnes Datenobjekt und die kleinste Einheit in einer Dokumenten-DB. Ein Dokument kann z.B. ein JSON mit einer eigenen internen Struktur.
![Document_DB](images/Document_DB.PNG)
#### 3.4.1 Erstellen einer Collection / Ablegen von Dokumenten
Folgend ein Code-Snippet zum Verbinden mit der Datenbank, Anlegen einer Collection und ablegen von Dokumenten.
``` python
from pymongo import MongoClient
# Verbindung zur MongoDB-Datenbank herstellen
client = MongoClient('mongodb://localhost:27017')
# erstelle ein Cleint-Objekt zur Datenbank
db = client['transparenz']
# Collection erstellen
collection = db['Tagesschau_API']
# Beispiel-Dokumente einfügen
doc1 = {
'title': 'BASF wird verkauft!',
'content': 'BASF wird an Bayer AG verkauft',
'date': '2023-06-22'
}
doc2 = {
'title': 'Bayer Aktie erreicht Rekordniveau',
'content': 'Aufgrund des Zukaufs von BASF.....',
'date': '2023-06-23'
}
# Dokumente in die Collection einfügen
collection.insert_one(doc1)
collection.insert_one(doc2)
# Verbindung zur Datenbank schließen
client.close()
```
### 3.5 Aufbau einer Datenbank
Vor dem Aufbau einer relationalen Datenbank sollten planerische Schritte durchgeführt werden, um ein System zu entwerfen, dass den Anforderungen gerecht wird. \
Die wichtigsten Schritte sind:
**Anforderungsanalyse:** Identifikation und Definition von Anforderungen an die Datenbank durch Betrachtung des Anwendungsfalls.
**Datenmodell:** Analysieren der Strukturen und Beziehungen, die sich aus der Anforderungsanalyse ergeben. Auswahl eines Datenbankmodells, welches am besten geeignet ist.
**Tabellenentwurf:** Basierend auf den identifizierten Anforderungen wird die Tabellenstruktur der Datenbank entworfen. Für jede Tabelle werden Spaltennamen, Datentyp und mögliche Einschränkungen wie Primärschlüssel und Fremdschlüssel definiert.
**Erstellung der Tabellen:** Wenn der Tabellenentwurf schlüssig ist und bereits diskutiert wurde, können die Tabellen erstellt werden. Es werden die zuvor festgelegten Bezeichner, Datenytpen und Constraints hinzugefügt.
**Beziehungen festlegen:** Um die Beziehungen zwischen Tabellen festzulegen, werden Fremdschlüssel verwendet. Mit Fremdschlüsseln verknüpft man Tabellen mit den Primärschlüsseln anderer, abhängiger Tabellen.
## 4. Datenbanken Transparenzregister
Nachdem die Datencluster identifiziert wurden, welche für das Transparenzregister notwendig sind, wurde Rechereche zu den benötigten Datenquellen betrieben. \
Es gibt verschiedene Quellen, mit unterschiedlichen Schnittstellen bzw. Zugriff auf die Daten, z.B. mit API´s oder über Web Scrapping.
Es wurde eine Architektur definiert, welche den Aufbau der späteren Software skizziert:
![High_level_design](images/HLD.png)
Mittels geeigneter Techniken werden Daten aus diversen Quellen extrahiert (Data Extraction) und in der Staging DB gespeichert.
Mit unterschiedlichen Daten-Extraktionspipelines (Dazta Loader, Sentiment Analysis, Graph Analysis) werden die Daten aus der Staging DB verarbeitet und die strukturierten und aufbereiteten Daten in der Production DB abgelegt. \
Das Frontend kann auf diese strukturierten Daten zugreifen, um diese zu visualisieren.
### 4.1 Production DB - relationales Datenbankmodell
Für die Production DB ist eine relationale Datenbank vorgesehen, da diese die Daten organisiert und durch Verwendung von definierten Schemata strukturiert. \
Diese Strukturen erleichtern die Wartung und Integration zwischen Back- und Frontend.
![Relationales Modell](images/DB_Schema.png)
Zentrales Element ist die Stammdatentabelle **company**, welche einen zusammengesetzten Primärschlüssel aus der Nummer des Handelsregister und dem zuständigen Amtsgericht bildet. \
Die Handelsregisternummer ist nicht eindeutig und wird deutschlandweit mehrfach vergeben, allerdings nur einfach unter einem Amtsgericht.
Es schließt sich die Tabelle **finance** an, in welcher die Finanzdaten persisitiert werden. Diese steht in einer 1:n Beziehung zur Unternehmenstabelle, da ein Unternehmen viele Finanzdaten haben kann und jeder Datensatz genau einem Unternehmen zugewiesen ist. \
Die einzelnen Metriken wurden als Attribute definiert, wodurch es viele NULL-Werte in jeder Zeile gibt. Vorteilhaft bei dieser Notation ist allerdings, dass die Metriken durch den Spalztenbezeichner eindeutig sind.
Die Tabelle **Sentiment** speichert die Stimmungsdaten zu einem Unternehmen. Auch hier besteht eine 1:n Beziehung zu der Unternehmenstabelle. Es gibt einen eigenen Enumeration-Typ, der die Art der Stimmungsdaten festlegt.
Die Tabelle **district_court** speichert die Amtsgericht, unter welchen die Unternehmen registriert sind. Diese Information ist wichtig, um mit der Handelsregisternummer und dem Amtsgericht ein Unternehmen eindeutig zu identifizieren.
Die Tabelle **person** speichert Personen, welche unterschiedliche Beziehungen zu Unternehmen haben können. Daraus ergibt sich eine n:m Beziehung (many-to-many), da jede Person mehrere Beziehungen zu einem Unternehmen haben kann bz. jedes Unternehmen mehrfach mit einer Person in Verbindung steht. \
Um diese Relation aufzulösen, wird eine Beziehungstabelle **person_relation** benötigt, um die n:m Beziehung auf zwei 1:n Beziehungen zu reduzieren. Diese enthält die Fremdschlüssel der bezogenen Tabellen, um die Beziehung zu modellieren.
Abschließend gibt es noch die Tabelle **company_relation**, welche die Verbindung zwischen Unternehmen modelliert. Hierfür wurde ein Enumaration-Typ erzeugt, welcher die Art der Beziehung angibt (wird_beliefert_von, arbeitet_mit, ist_beteiligt_an, hat_Anteile_an).
### 4.2 Staging DB
Die Staging DB ist eine dokumentbasierte Datenbank zu Speicherung von unstrukturierten und semi-strukturierten Daten. Sie dient als Zwischenspeicher oder "Rohdatenbank" für die Extraktions-Pipelines. \
Aufgaben der Staging-DB:\
**1. Datenvorbereitung:** Sammlung und Speicherung von Rohdaten aus verschiedenen Quellen\
**2. Überprüfung:** Entsprechen die Daten den Anforderungen ggfs. Ermittlung von Fehlern oder Inkonsistenzen\
**3. Testumgebung:** Die Rohdaten aus der Staging DB können mehrfach verwendet werden, um verschiedene Szenarien und Funktionalitäten der Extraktionspipelines zu erproben\
**4. Backup:** Wenn sich im Laufe des Projekts eine Datenquelle ändert (z.B. Struktur oder Zugang zum Bundesanzeiger) sind die Daten weiterhin verfügbar oder wenn es Änderungen am Schema der Production DB gibt, kann durch eine Änderung am Data Loader das neue Tabellenschema implementiert werden
Die Staging DB erhält Collections der unterschiedlichen Quellen, unter welchen die Dokumente gespeichert werden.
![Staging_DB](images/Staging_DB.PNG)
### 4.3 SQL Alchemy
SQL Alchemy ist eine Python Bibliothek, um mit relationalen Datenbanken zu kommunizieren.
Dieses ORM (Object-Relational-Mapping) Framework bildet die Datenbanktabellen als Pythonklassen an und vereinfacht damit das Erstellen, Lesen, Aktualsieren und Löschen von Daten aus Pythonanwendungen.\
Wichtige Eigenschaften:
- erleichterte Entwicklung: durch die Abbildung von Datenbanktabellen als Pythonklassen wird durchgängig Pythoncode verwendet
- Flexibilität: Durch Verwendung eines Backend-Treibers für die unterschiedlichen Datenbanken, muss der Code nicht geändert werden. Wenn eine andere Datenbank zum Einsatz kommt, muss nur der Treiber ausgetauscht werden (Plattformunabhängigkeit)
- Erhöhung der Produktivität: Es werden keine Kompetenzen für SQL Programierung und Wartung benötigt.
## 5. Proof of Concept
### 5.1 Docker
Für die Umsetzung der bisher vorgestellten theoretischen Betrachtungen wird ein Docker Container verwendet. Dieser Container beinhaltet eine relationale und eine dokumentbasierte Datenbank. \
Mit Jupyter Notebooks soll die Implementierung und Befüllung der Datenbank erprobt werden, um als Startpunkt für die anstehende Softwareentwicklung zu dienen.
```yaml
version: "3.8"
services:
db:
image: postgres:14.1-alpine
container_name: postgres
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- ./PostgreSQL:/var/lib/postgresql/data
pgadmin:
image: dpage/pgadmin4:7.2
container_name: pgadmin4_container
restart: always
ports:
- "5050:80"
environment:
PGADMIN_DEFAULT_EMAIL: admin@fh-swf.de
PGADMIN_DEFAULT_PASSWORD: admin
volumes:
- ./pgadmin:/var/lib/pgadmin
mongodb:
image: mongo:7.0.0-rc4
ports:
- '27017:27017'
volumes:
- ./mongo:/data/db
```
|Eintrag|Beschreibung|
|---|---|
|version|Version von docker-compose|
|services|Definition der Services, welche gestartet werden|
|Option|Beschreibung|
|---|---|
|image|Angabe des zu verwendenden Image|
|restart|Option, um Container erneut zu starten, falls dieser gestoppt wurde|
|environment|Umgebungsvariablen, wie z.B. Username und Passwort|
|Ports|Mapping des Containerports zum Port der Hostmaschine|
|volumes|Angabe eines Volumes zum Persistieren der Containerdaten|
Beim Ausführen der docker-compose werden in diesem Verzeichnis Ordner für die Datenablage angelegt. Da zum Verfassungszeitpunkt noch nicht feststeht, wie im Projekt der Datenaustausch stattfindet, könnten diese Ordner bzw. die Volumes einfach untereinander ausgetauscht werden.
Zum Starten des Containers den folgenden Befehl ausführen:
```
docker-compose -f docker-compose.yml up
```
### 5.2 PG Admin
PG Admin ist ein grafisches Administartionstool für Postgres. Wenn der Container gestartet ist, kann man sich über http://localhost:5050/browser/ mit dem Web-UI verbinden. \
Dieses Tool dient lediglich der Überprüfung von Commits der Tabellen und daten.
Die Anmeldedaten lauten:
>User: admin@fh-swf.de \
>Passwort: admin
![PGAdmin_landing](images/PG_Admin_Board.PNG)
Zuerst muss der Server angelegt werden, dafür einen Rechtsklick auf Server und den Button „Register“ auswählen. Im geöffneten Dialog muss die Konfiguration festgelegt werden.
|Reiter|Parameter|Wert|
|---|---|---|
|General|Name|postgres|
|Connection|Host name/address|postgres (siehe docker-compose)|
|Connection|Username|postgres (siehe docker-compose)|
|Connection|Password|postgres (siehe docker-compose)|
![PGAdmin_Conf](images/PG_Admin_Conf.PNG)
### 5.3 Erstellen von Mock Daten
**Unternehmensstammdaten:**\
Um das Konzept und den Umgang mit den ausgewählten Datenbanken zu überprüfen, sollen Daten in die Datenbank geschrieben werden. Hier für wurde auf Statista recherchiert, welches die größten deutschen Unternehmen sind, um einen kleinen Stamm an Unternehmensdaten zu generieren (01_Stammdaten_Unternehmen_HR.csv). /
Die Relation zu den Amtsgerichten ist frei erfunden und wurde nicht recherchiert.
![biggest_companies](images/Statista_Companies.png)
**Amtsgerichte:**
Die Amtsgerichte sind aus https://www.gerichtsverzeichnis.de/ extrahiert, wobei lediglich 12 Amstgerichte eingefügt wurden (Amtsgerichte.csv).
**Finanzdaten:** Es wurden für drei Unternehmen (EON, Telekom, BASF) die Finanzdaten bezüglich Umsatz, Ebit und Ebitda auf Statista ermittelt und als separate Dateien gespeichert (BASF_data.csv, Telekom_data.csv, EON_data.csv).
**Personen:** Die Personentabelle ist frei erfunden. Mit einer Onlinebibliothek wurde 1000 Vor- und Nachnamen erzeugt und gespeichert (Person1000.csv).
**Personen-Unternehmens-Beziehung:** Diese Tabelle ist zufällig erzeugt und dient lediglich für weitere Experimente. Hierfür wurde ein Python-Skript erstellt, welches mit der mehreren Random-Funktionen die Beziehungen zufälloig generiert.
**Sentiment:** keine Mock-Daten vorhanden
**Unternehmens-Unternehmens-Beziehung:** keine Mock-Daten vorhanden
### 5.4 Anlegen der relationalen Tabellen
Für das Verbinden zu der Postgre Datenbank und das Anlegen der Tabellen wird ein Jupyter Notebooks verwendet (11_Create_Tables_with_SQL-Alchemy.ipynb). \
Die benötigten Bibliotheken werden importiert und das Erstellen von Tabellen als Python-Objekte beschrieben. \
Nach dem Anlegen der Tabellen werden die Mock-Daten in die Datenbank geschrieben. \
Eine Überprüfung, ob die Daten abgelegt wurden ist sehr einfach mit PGAdmin möglich.
![finance_data](images/finance_data.PNG)
Das grundsätzliche Vorgehen bei der Verwendung von SQLAlchemy ist:
1. Verbindung zur Datenbank herstellen
```python
from sqlalchemy import create_engine
# Connection URL für postgres
url = URL.create(
drivername="postgresql",
username="postgres",
password="postgres",
host="localhost",
database="postgres")
#Verbindung zur Datenbank
engine = create_engine(database_url)
```
2. Erstellen einer Klasse als Repräsentation der Tabelle.
> Es ist üblich und empfehlenswert die Klassendefinitionen in einer separaten Datei vorzunehmen (model.py), damit diese auch in andere Modulen importiert und verwendet werden können
```python
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
Base = declarative_base()
class MyClass(Base):
__tablename__ = 'company'
id = Column(Integer, primary_key=True)
name = Column(String)
city = Column(String)
```
3. Starten einer Session/Verbindung, um Daten lesen und schreiben zu können
```python
from sqlalchemy.orm import sessionmaker
#starte die Verbindung
Session = sessionmaker(bind=engine)
session = Session()
```
4. Daten abfragen
```python
# Alle Daten der Klasse/Tabelle abrufen
data = session.query(MyClass).all()
```
5. Daten speichern, wenn z.B. Datensätze in die Datenbank geschrieben werden, muss dies mit der **commit()**-Funktion ausgeführt werden. Das folgende Snippet iteriert durch einen Dataframe, um jede Zeile in die Datenbank zu schreiben.
```python
for i in range(len(df)):
#get data from dataframe
myNewData=MyClass(
name = str(df['Name'].iloc[i]),
city = str(df['Surname'].iloc[i])
)
session.add(myNewData)
session.commit()
```
### 5.5 Abfragen der Datenbank
Der folgende Code-Snippet zeigt, wie man eine Abfrage gestaltet.
```python
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
# Erstelle eine SQLite-Datenbankdatei oder gib den Pfad zur vorhandenen Datei an
url = URL.create(
drivername="postgresql",
username="postgres",
password="postgres",
host="localhost",
database="postgres"
)
#Erstelle eine Engine zur Verbindung mit der Datenbank
engine = create_engine(url)
#Erstelle eine Klasse, die eine Tabelle repräsentiert
Base = declarative_base()
class Company(Base):
__tablename__ = 'company'
hr = Column(Integer(), nullable=False, primary_key=True)
court_id = Column(Integer, ForeignKey("district_court.id"), nullable=False, primary_key=True)
name = Column(String(100), nullable=False)
street = Column(String(100), nullable=False)
zip = Column(Integer(), nullable=False)
city = Column(String(100), nullable=False)
sector = Column(String(100), nullable=False)
__table_args__ = (
PrimaryKeyConstraint('hr', 'court_id', name='pk_company_hr_court'),
)
#starte die Verbindung zur Datenbank
Session = sessionmaker(bind=engine)
session = Session()
#Abfrage aller Spalten der Tabelle/Klasse Company
Comps = session.query(Company).all()
#Gebe die Spalten name, hr und court_id der Tabelle company aus
for comp in Comps:
print(comp.name, comp.hr, comp.court_id)
```
<div style="page-break-after: always;"></div>
## 6. Zusammenfassung
Die vorliegende Seminararbeit behandelt das Thema der Datenspeicherung mit Fokus auf dem Projekt Transparenzregister. Es wurde erläutert, warum Daten gespeichert werden und welche Art von Daten es gibt.\
Für das Projekt sind Daten und die Speicherung eine Kernkomponente, um die geforderten Analysen bezüglich Verflechtungen, unternehmerischen Erfolgs und Aussenwahrnehmung zu ermöglichen.
Es wurden Datencluster definiert und entsprechende Quellen gefunden, welche über geeignete Extraktionspipelines die erforderlichen Informationen extrahieren. Zum Speichern dieser extrahierten Daten wurde ein relationales Modell erarbeitet, um ein Konzept für die folgende Implementierung zu haben.
Um das Konzept zu überprüfen, wurde ein Proof of Concept durchgeführt, um geeignete Werkzeuge zu erproben und das Modell auf seine Tauglichkeit zu überprüfen. \
Hierbei wurde ein Dockercontainer eingesetzt, um die Datenbankumgebung bereitzustellen. Mithilfe der SQL-Alchemy-Bibliothek, wurden die Tabellen innerhalb der Datenbank erstellt.\
Anschließend wurden die Tabellen mit eigenen Mock-Daten befüllt, um die Funktionalität der Datenbank zu testen.
Insgesamt bietet die Seminararbeit einen umfassenden Überblick über die Bedeutung der Datenspeicherung und die verschiedenen Arten von Datenbanken.
Es wurde ein erstes relationales Modell und ein High level design für die Softwarearchitektur erarbeitet.
Diese Arbeit hat grundsätzliche Fragen geklärt und Verständnis für die Datenspeicherung im Zusammenhang mit dem Projekt Transparenzregister geschaffen und unterstützt die weitere Entwicklung.
<div style="page-break-after: always;"></div>
## Quellen
Klug, Uwe: SQL-Der Einstieg in die deklarative Programmierung, 2. Auflage, Dortmund, Springer, 2017\
Steiner, Rene: Grundkurs relationale Datenbanken, 10. Auflage, Wiesbaden, Springer, 2021\
https://backupchain.de/daten-backup-tipps-3-wie-oft-daten-sichern/ \
https://www.talend.com/de/resources/strukturierte-vs-unstrukturierte-daten/ \
https://www.sqlservercentral.com/articles/creating-markdown-formatted-text-for-results-from-sql-server-tables \
https://www.sqlalchemy.org/ \
https://medium.com/@arthurapp98/using-sqlalchemy-to-create-and-populate-a-postgresql-database-with-excel-data-eb6049d93402

View File

@ -0,0 +1,18 @@
### Action List "Datenspeicherung
- [x] Erstelle ein relationales Schema für Unternehmens- und Finanzdaten, bei welchem die Jahre berücksichtigt werden
- [x] Erstelle docker-compose für postgresgl, pgadmin, neo4j
- [x] Erstelle eine Kurzanleitung für die Handhabung von Docker
- [x] erstelle Jupyter Notebook zum Verbinden mit Datenbank und Anlegen von Tabellen
- [x] Recherchiere nach den 10 größten deutschen Unternehmen und ermittel Finanzdaten (Umsatz, Ebit, Ebitda)
- [x] Erstelle ein Jupyter Notebook um diese Daten in die Datenbank zu übertragen
- [x] Erstelle ein Jupyter Notebook, um die Daten abzufragen
- [x] Erstelle ein Schema für Stimmungsdaten
- [x] Erstelle ein Schema für Verflechtungen
- [ ] Erzeuge Beispieldaten für Stimmung
- [x] Erzeuge Beispieldaten für Verflechtung
- [ ] Erstelle eine Prototypen GUI in Mercury zur einfachen Abfrage von Daten
- [ ] Verwende SQLalchemy, um eine Verbindung zur Datenbank aufzubauen, Tabellen anzulegen und Daten zu schreiben -->
- [x] Ersetze den enumeration type in den Finanzdaten gegen einzelne (eindeutig bezeichnete) Spalten
- [x] Lade das DB Schema hoch, um es den anderen Teammitgliedern bereitzustellen
- [ ]

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2023-06-09T06:52:32.151Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/19.0.3 Chrome/102.0.5005.63 Electron/19.0.3 Safari/537.36" etag="YzJ30O3iCiKXb3qmuW1k" version="19.0.3" type="device"><diagram id="M31xxMy7zny7NdG5GnKM" name="Seite-1">5Vxbc9o4G/41zOxepOMTxr4MadI9tZMt7e52b74RtrDV2BIrywnh13+SLYOFFIITDITeJFjyied93rPEwL3KFx8omKcfSQyzgWPFi4H7fuA4juXa/J8YeaxHbMf165GEorges9YDE7SE8sRmtEQxLJQTGSEZQ3M5KB8QEYxhxJQxQCl5UE+bkSxWBuYggcrdxcAkAhnUTvsbxSyVo7Yfrid+gShJ5aMDZ1RP5KA5Wd64SEFMHlpD7vXAvaKEsPpTvriCmUBPxeXmidnVi1GI2S4XfL/BX6KhxW4W/+GbICK/f/jwy4Ut3/YeZKX8xvJt2WMDQUJJOdefJl/gHlIGFyZZgGkGN78uJwokOWT0kZ/XXCUfKSkyrI8e1mg7nnzLtAW0HcgTgZRwsrrxGgT+QeLQBRP/eUw4JDiG4i72wB0/pIjByRxEYvaBawIfS1meyekZwUwym39Xfoyy7IpkhFb3cuMhDGKPjxeMkjvYmgmcqev7fEZHf7s0N2WiY38QeOc3C6f4CuPfbuH1n39ef7v963/lha2h+xUzSDFMc4g1oIsHlGcAw15AaMyU/26oUtDXOGiHlgEky+oJJEcD6RPI4cDxM/7o8ZTyT4n49IEOrtzB+ArHJU6K7yCl+jkTBnBMKNNnxhTgKDXdFhb8JYsoBTNWzAjNNblwaJnKcpChBPPPGZyJGQE/4nb0Ug7nKI7FxWMKC7SUtsHix3OCMKvwG44Hw/fiTiUjhdQXTS0wqcjQ1iE5pPNjK/92pkfjiiQ5HFcnh+Xr5Bh5Pdkn3TxxCed5DJhBf3Q57QpnI88ICvXcJlGT+VsbSKuxgPKlNi2i16dqh+6Gagea8HyDYrt70GvjN2ief0x/63oqoUe6tXNDVwdl2IRu+/e43oE9LoDBLDJ5XD8K4HTGZxIKYsSxf9bGbBdzJ0d8YNRdDfSPiAE6hRxauixnFMEYYv4ubA9euQMicjYIN1S3Majt0MUJDYiFPQGms/RfFSVLuDAewHIv5lg8F+L+1JpUsc3b9J9bafNS/+mGuv/0jRFoT2LUU54JQ3kuAijpQzfDoWZEmBVFjP5/JWkmLmrIL/kJtjNf1JfJ+eZGP+3tThMuJMQDZh7bgeyxWMVwHJH63vVpPz8xft5xQndjY4/UJNTRSXrQOEEPEz6BKE1BxlBydyyL7KoY2UNHDxwcQyRs9wZTqMF0wQ85Dgm3ywXHClYWmHK1TpAhzxFnl/kDzNiMQk7EDFXpkHVLSVzesSeumIi8aCYMhXVPxN/LymkW80wkY5ceW5qMiLjyV4zJPWCIaw6uFRzDUjyQJ1xRWl/NM65c1NEyMc7fif/9AqMUc63j3+GJG38BFM2mqEoDzWdcIyzoU82rr0353Q3JobioyswLVueYbNm+uCBLBLIKBI7Wd3hXWc4bbkpn4iE7pSJvxeV11hQ1cHEMAbZt0hPL6SvAtjRF+bpB+6NZFS3Oc0I9w3ZsQ6Bn225feOlFKqEOn2FcLhGktR6IujTXKwwp10v+facUlFFaGDTpU9noDo8FS34mR5GurzXp9EeEUb56lNRXnplUJiLLnrIDpsuuc1QUtclxfJALr4unxXy3KOCtqOiK4S/V0ZGBc47OOb+3yoBe1rksiwLiB5BWxdFKpEfQT99WgPJsg3aODNbM7yt+d/QA/pYzi6H7ddaFYQLqAZAJLf0M8B2qdAKU4lhEU5Rbvd1KZm9FCVYceqESNIUhRbS2wfD2JdomUGxJA8YJbFICQllKEsIznuv16EYKsT7nD0LmEufvkLFHmUgIEajihQvE/ml9/iZu9W40lIfvF/LW1cFjO1VplZhqUTY9wqFRaBLKgpQ0gtuMmZQjAzSBW62eLEkIkLaKm8JM6ANU3mP/BZLhMcVnvRu2BGhvlR4XCX38p33QFro4Xl9XHZ2U2Juu+qmI/QSayIHlKaYs0BN4xzN4qTDoy5bZw+dR2WdRG9rxEI5MRe3QH7mgQxvZe2EbuS94jW08vRj7N6JMtiznsi06E8HAq2OmDng0HWWVjEPXsKjBMtSTRn31k3Uu/mbsFZu7zG8zRNpKmxd3f3W7MuypMGh8fz1L+JoXgC1PgebBsVmu+yEzyydlnr/RlsxWUry4JaOndH1Vu43vr1e7r8e/fjkFStujY3NaL3H/GJzu3sI5LU4bSq5jxNm7LIyCOgK3Hf/Y3DaUWX8McnevVp4aux3dZKME4jswRwxwIjOIsm0kL3iS22QzjntA1rvDo7NeX3jzg7De6Sq7U2O9nnRe4iVIxYWttVMnyXvPOzrvd01Cz473r006D8h7cylLE9xfhBZiWfkpxDG+ob/eG7PNfZcdiS2qK+fUb3rtUvpmQVFLcJ6hz9+ctne56QbpX7EgBlIE8Q+wnL675oVqL9jR5XfY1fR6jnVKRWBXAWtk62gd2Eztmm6dm51yXp1uHdlQNYqmLA6ZFWIBQ0HBPtZtvZ7eoaHjdlh675pXnR29X51XHZveel415piy5WlY7qBxe8ejdpf+3VlR+9Wp05Gp7QWaNI62osnZvqJpvSbm3WoVzLf23CkviWmKCyeyJMbVQy2NB/tc/DGbQT8y7miMR+HUsrYJocMGkI2do76hG+41i9gV9Qp7A1qPjH7nUFGSZVO4RDB9ZtmsKoRNlHfeBdoZSs8KVChHBh8zMliqZqvc/pHUwyexovxSlvKtemHtGIpDlNQLzAGu/vCpaiOI8kMOpuXpl3gJ60059d2UC67EsNilIx8id5FYKZh28mnPZ9i9ebVN/uzo5VYk3pk+FxutPENtNzBsJu7Nzbl6BFf1g1iZF6eth56K5MgzpTEGk9bbz8+4eqx3oSpepRXiIY12PrFP7WPJuCJUe9zqbWRELHjnjnT94x7nrlidw0c18nf1Led2GBxSr/QlTepWwdNWLt9X4Aw8ww/r+AY71Z+T05caCf1IYA4RLqrFj6vtjGal+gPBGaSiwY05EFIQGcOoOG9N6pxE2xu1YoMquQd1UfpKqltIi3pf3OnpjhuoAWJo8PGuaVdkb7rj6dX2z0RsU642Mj9VeL+qfFdTzBFHauVSjDzZTTwrDQp3pkDjffSUwDX90lRv27E8PYudkAgBcWH1g487COxt9Me6u7bAUdTTN/To7cYEvrIZxg/XPxNZzbV+bdO9/j8=</diagram></mxfile>

View File

@ -0,0 +1,70 @@
https://geshan.com.np/blog/2021/12/docker-postgres/
https://belowthemalt.com/2021/06/09/run-postgresql-and-pgadmin-in-docker-for-local-development-using-docker-compose/
https://thibaut-deveraux.medium.com/how-to-install-neo4j-with-docker-compose-36e3ba939af0
https://towardsdatascience.com/how-to-run-postgresql-and-pgadmin-using-docker-3a6a8ae918b5
# Installation Docker Desktop
## Starten eines Containers:
> docker run --name basic-postgres --rm -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=4y7sV96vA9wv46VR -e PGDATA=/var/lib/postgresql/data/pgdata -v /tmp:/var/lib/postgresql/data -p 5432:5432 -it postgres:14.1-alpine
Dieser Befehl startet einen Container mit dem Postgres14.1-alpine Image, welches von Dockerhub geladen wird. Der Container läuft unter dem Namen basic-postgres
| Syntax | Attribut | Beschreibung |
| ----------- | ----------- | ----------- |
| basic-postgres | --name | Angabe des Containernamens|
| | --rm | Bei Beendigung des Containers wird das erstellte Dateisystem entfernt|
| |-e| Verwende Umgebungsvariablen |
| POSTGRES_USER | | Umgebungsvariable für den anzulegenden Benutzer: postgres|
|POSTGRES_PASSWORD| | Umgebungsvariable für das anzulegende Passwort: 4y7sV96vA9wv46VR |
| PGDATA | | Umgebungsvariable für den Ort der Datenbank|
| | -v | Einzubindendes Volumen: /tmp:/var/lib/postgresql/data |
| |-p | Angabe des Containerports und des öffentlich zugänglichen Ports |
| | -it | Interactive: der Container bleibt aktiv, damit mit diesem interagiert werden kann |
Mit einem zweiten Terminalfenster kann man auf die Bash des Containers öffnen und auf die Datenbank zugreifen.
> docker exec -it basic-postgres /bin/sh
Die folgenden Befehle starten die Postgres CLI, Ausgabe aller Datenbanken und beendet die CLI.
> Psql username postgres \
> \l \
Exit
Der Container kann durch Betätigung von STRG + C beendet werden.
## Docker Compose
Das oben erklärte Vorgehen zum Starten eines Containers, festlegen der Umgebungsvariablen und zusätzliche verlinken zu einer Anwendung wird nun in einer yml-Datei beschrieben, um die Verwaltung und das Erstellen zu vereinfachen.
| | | Beschreibung |
| ----------- | ----------- | ----------- |
|Version | | Version von docker-compose |
|Services| |Definition der Services, wobei jeder ein eigenen docker-run Befehl ausführt.|
| | image | Angabe des zu verwendenden Images |
| | restart | Option um Container erneut zu starten, falls dieser gestoppt wird |
| | Environment | Umgebungsvariablen: Username und Passwort |
| | Ports | Mapping des Containerports zum Port der Hostmaschine |
| | Volumes | Angabe eines Volumes zum Persistieren der Containerdaten, damit nach einem Neustart die Daten wieder verfügbar sind |
Nun kann der Container mittels Docker-Compose gestartet werden.
> docker-compose -f /.../docker-compose-postgres.yml up
## pgAdmin
pgAdmin ist ein grafisches Administrationswerkezug für postgreSQL und macht die oben gezeigte Administration komfortabler. \
Erreichbar ist das Interface über: http://localhost:5050 \
Als Login werden die Daten aus der docker-compose verwendet:
>User: admin@fh-swf.de
>Passwort: admin
### Anlegen eines Servers
Zuerst muss der Server angelegt werden, dafür einen Rechtsklick auf Server und den Button „Register“ auswählen. \
Im geöffneten Dialog muss die Konfiguration festgelegt werden.
| Reiter | Parameter | Wert |
| ----------- | ----------- | ----------- |
| General| Name | postgres_docker |
| Connection | Host name/address | local_pgdb (siehe docker-compose) |
| Connection | Username | postgres (siehe docker-compose) |
| Connection | Password | postgres (siehe docker-compose) |

View File

@ -0,0 +1,13 @@
HR;Amtsgericht;Name;Strasse;PLZ;Stadt;Branche
12334;2;Volkswagen;Berliner Ring 2;38440;Wolfsburg;Automobil
64566;2;Mercedes-Benz Group;Mercedesstra<72>e 120;70372;Stuttgart;Automobil
5433;3;Allianz;Reinsburgstra<72>e 19;70178;Stuttgart;Versicherung, Finanzdienstleistung
12435;4;BMW Group;Petuelring 130;80809;M<>nchen;Automobil
12336;5;Deutsche Telekom;Landgrabenweg 151;53227;Bonn;Telekommunikation, Informationstechnologie
559;6;Deutsche Post DHL Group;Charles-de-Gaulle-Str. 20;53113;Bonn;Logistik
555;7;Bosch Group;Robert-Bosch-Platz 1;70839;Gerlingen-Schillerh<72>he;Kraftfahrzeugtechnik, Industrietechnik, Gebrauchsg<73>ter, Energie- und Geb<65>udetechnik
12384;8;BASF;Carl-Bosch-Stra<72>e 38;67056;Ludwigshafen;Chemie
64345;9;E.ON;Arnulfstra<72>e 203;80634;M<>nchen;Energie
4344;10;Munich Re Group;K<>niginstr. 107;80802;M<>nchen;Versicherung
866;11;Siemens;Werner-von-Siemens-Stra<72>e 1;80333;M<>nchen;Automatisierung, Digitalisierung
9875;12;Deutsche Bahn;Potsdamer Platz 2;10785;Berlin;Transport, Logistik
1 HR Amtsgericht Name Strasse PLZ Stadt Branche
2 12334 2 Volkswagen Berliner Ring 2 38440 Wolfsburg Automobil
3 64566 2 Mercedes-Benz Group Mercedesstraße 120 70372 Stuttgart Automobil
4 5433 3 Allianz Reinsburgstraße 19 70178 Stuttgart Versicherung, Finanzdienstleistung
5 12435 4 BMW Group Petuelring 130 80809 München Automobil
6 12336 5 Deutsche Telekom Landgrabenweg 151 53227 Bonn Telekommunikation, Informationstechnologie
7 559 6 Deutsche Post DHL Group Charles-de-Gaulle-Str. 20 53113 Bonn Logistik
8 555 7 Bosch Group Robert-Bosch-Platz 1 70839 Gerlingen-Schillerhöhe Kraftfahrzeugtechnik, Industrietechnik, Gebrauchsgüter, Energie- und Gebäudetechnik
9 12384 8 BASF Carl-Bosch-Straße 38 67056 Ludwigshafen Chemie
10 64345 9 E.ON Arnulfstraße 203 80634 München Energie
11 4344 10 Munich Re Group Königinstr. 107 80802 München Versicherung
12 866 11 Siemens Werner-von-Siemens-Straße 1 80333 München Automatisierung, Digitalisierung
13 9875 12 Deutsche Bahn Potsdamer Platz 2 10785 Berlin Transport, Logistik

View File

@ -0,0 +1,13 @@
HR;Amtsgericht;Name;Strasse;PLZ;Stadt;Branche
12334;2;Volkswagen;Berliner Ring 2;38440;Wolfsburg;Automobil
64566;2;Mercedes-Benz Group;Mercedesstra<72>e 120;70372;Stuttgart;Automobil
5433;3;Allianz;Reinsburgstra<72>e 19;70178;Stuttgart;Versicherung, Finanzdienstleistung
12334;4;BMW Group;Petuelring 130;80809;M<>nchen;Automobil
12336;5;Deutsche Telekom;Landgrabenweg 151;53227;Bonn;Telekommunikation, Informationstechnologie
555;6;Deutsche Post DHL Group;Charles-de-Gaulle-Str. 20;53113;Bonn;Logistik
555;7;Bosch Group;Robert-Bosch-Platz 1;70839;Gerlingen-Schillerh<72>he;Kraftfahrzeugtechnik, Industrietechnik, Gebrauchsg<73>ter, Energie- und Geb<65>udetechnik
12384;8;BASF;Carl-Bosch-Stra<72>e 38;67056;Ludwigshafen;Chemie
64345;9;E.ON;Arnulfstra<72>e 203;80634;M<>nchen;Energie
4344;1;Munich Re Group;K<>niginstr. 107;80802;M<>nchen;Versicherung
866;1;Siemens;Werner-von-Siemens-Stra<72>e 1;80333;M<>nchen;Automatisierung, Digitalisierung
9875;1;Deutsche Bahn;Potsdamer Platz 2;10785;Berlin;Transport, Logistik
1 HR Amtsgericht Name Strasse PLZ Stadt Branche
2 12334 2 Volkswagen Berliner Ring 2 38440 Wolfsburg Automobil
3 64566 2 Mercedes-Benz Group Mercedesstraße 120 70372 Stuttgart Automobil
4 5433 3 Allianz Reinsburgstraße 19 70178 Stuttgart Versicherung, Finanzdienstleistung
5 12334 4 BMW Group Petuelring 130 80809 München Automobil
6 12336 5 Deutsche Telekom Landgrabenweg 151 53227 Bonn Telekommunikation, Informationstechnologie
7 555 6 Deutsche Post DHL Group Charles-de-Gaulle-Str. 20 53113 Bonn Logistik
8 555 7 Bosch Group Robert-Bosch-Platz 1 70839 Gerlingen-Schillerhöhe Kraftfahrzeugtechnik, Industrietechnik, Gebrauchsgüter, Energie- und Gebäudetechnik
9 12384 8 BASF Carl-Bosch-Straße 38 67056 Ludwigshafen Chemie
10 64345 9 E.ON Arnulfstraße 203 80634 München Energie
11 4344 1 Munich Re Group Königinstr. 107 80802 München Versicherung
12 866 1 Siemens Werner-von-Siemens-Straße 1 80333 München Automatisierung, Digitalisierung
13 9875 1 Deutsche Bahn Potsdamer Platz 2 10785 Berlin Transport, Logistik

View File

@ -0,0 +1,15 @@
Stadt;Name
Aschaffenburg;Amtsgericht Aschaffenburg
Bamberg;Amtsgericht Bamberg
Bayreuth;Amtsgericht Bayreuth
Duesseldorf;Amtsgericht Duesseldorf
Duisburg;Amtsgericht Duisburg
Duisburg;Amtsgericht Duisburg-Hamborn
Duisburg;Amtsgericht Duisburg-Ruhrort
Oberhausen;Amtsgericht Oberhausen
Wuppertal;Amtsgericht Wuppertal
Berlin;Amtsgericht Mitte
Berlin;Amtsgericht Ost
Berlin;Amtsgericht West
Berlin;Amtsgericht Nord
Berlin;Amtsgericht Sued
1 Stadt Name
2 Aschaffenburg Amtsgericht Aschaffenburg
3 Bamberg Amtsgericht Bamberg
4 Bayreuth Amtsgericht Bayreuth
5 Duesseldorf Amtsgericht Duesseldorf
6 Duisburg Amtsgericht Duisburg
7 Duisburg Amtsgericht Duisburg-Hamborn
8 Duisburg Amtsgericht Duisburg-Ruhrort
9 Oberhausen Amtsgericht Oberhausen
10 Wuppertal Amtsgericht Wuppertal
11 Berlin Amtsgericht Mitte
12 Berlin Amtsgericht Ost
13 Berlin Amtsgericht West
14 Berlin Amtsgericht Nord
15 Berlin Amtsgericht Sued

View File

@ -0,0 +1,25 @@
Company_HR;Company_Court;Jahr;Umsatz;Ebit;EBITDA
;12384;8;1999;29473;;
;12384;8;2000;35946;;
;12384;8;2001;32500;;
;12384;8;2002;32216;;
;12384;8;2003;33361;;
;12384;8;2004;37537;;
;12384;8;2005;42745;5830;
;12384;8;2006;52610;6750;
;12384;8;2007;57951;7316;
;12384;8;2008;62304;6463;9562
;12384;8;2009;50693;3677;7388
;12384;8;2010;63873;7761;11131
;12384;8;2011;73497;8586;11993
;12384;8;2012;72129;6742;10009
;12384;8;2013;73973;7160;10432
;12384;8;2014;74326;7626;11043
;12384;8;2015;70449;6248;10649
;12384;8;2016;57550;6275;10526
;12384;8;2017;61223;7587;10765
;12384;8;2018;60220;5974;8970
;12384;8;2019;59316;4201;8185
;12384;8;2020;59149;-191;6494
;12384;8;2021;78598;7677;11355
;12384;8;2022;87327;6548;10748
1 Company_HR;Company_Court;Jahr;Umsatz;Ebit;EBITDA
2 ;12384;8;1999;29473;;
3 ;12384;8;2000;35946;;
4 ;12384;8;2001;32500;;
5 ;12384;8;2002;32216;;
6 ;12384;8;2003;33361;;
7 ;12384;8;2004;37537;;
8 ;12384;8;2005;42745;5830;
9 ;12384;8;2006;52610;6750;
10 ;12384;8;2007;57951;7316;
11 ;12384;8;2008;62304;6463;9562
12 ;12384;8;2009;50693;3677;7388
13 ;12384;8;2010;63873;7761;11131
14 ;12384;8;2011;73497;8586;11993
15 ;12384;8;2012;72129;6742;10009
16 ;12384;8;2013;73973;7160;10432
17 ;12384;8;2014;74326;7626;11043
18 ;12384;8;2015;70449;6248;10649
19 ;12384;8;2016;57550;6275;10526
20 ;12384;8;2017;61223;7587;10765
21 ;12384;8;2018;60220;5974;8970
22 ;12384;8;2019;59316;4201;8185
23 ;12384;8;2020;59149;-191;6494
24 ;12384;8;2021;78598;7677;11355
25 ;12384;8;2022;87327;6548;10748

View File

@ -0,0 +1,17 @@
Company_HR;Company_Court;Jahr;Umsatz;Ebit;EBITDA
;64345;9;2007;66912;;
;64345;9;2008;84873;;
;64345;9;2009;79974;;
;64345;9;2010;92863;;
;64345;9;2011;112954;;
;64345;9;2012;132093;7010;
;64345;9;2013;119615;5640;
;64345;9;2014;113095;4700;
;64345;9;2015;42656;3600;
;64345;9;2016;38173;3100;
;64345;9;2017;37965;3100;
;64345;9;2018;30084;2990;4840
;64345;9;2019;41284;3220;5558
;64345;9;2020;60944;3780;6905
;64345;9;2021;77358;4720;7889
;64345;9;2022;115660;5200;8059
1 Company_HR;Company_Court;Jahr;Umsatz;Ebit;EBITDA
2 ;64345;9;2007;66912;;
3 ;64345;9;2008;84873;;
4 ;64345;9;2009;79974;;
5 ;64345;9;2010;92863;;
6 ;64345;9;2011;112954;;
7 ;64345;9;2012;132093;7010;
8 ;64345;9;2013;119615;5640;
9 ;64345;9;2014;113095;4700;
10 ;64345;9;2015;42656;3600;
11 ;64345;9;2016;38173;3100;
12 ;64345;9;2017;37965;3100;
13 ;64345;9;2018;30084;2990;4840
14 ;64345;9;2019;41284;3220;5558
15 ;64345;9;2020;60944;3780;6905
16 ;64345;9;2021;77358;4720;7889
17 ;64345;9;2022;115660;5200;8059

View File

@ -0,0 +1,13 @@
Name;Straße;PLZ;Stadt;Branche
Volkswagen;Berliner Ring 2;38440;Wolfsburg;Automobil
Mercedes-Benz Group;Mercedesstraße 120;70372;Stuttgart;Automobil
Allianz;Reinsburgstraße 19;70178;Stuttgart;Versicherung, Finanzdienstleistung
BMW Group;Petuelring 130;80809;München;Automobil
Deutsche Telekom;Landgrabenweg 151;53227;Bonn;Telekommunikation, Informationstechnologie
Deutsche Post DHL Group;Charles-de-Gaulle-Str. 20;53113;Bonn;Logistik
Bosch Group;Robert-Bosch-Platz 1;70839;Gerlingen-Schillerhöhe;Kraftfahrzeugtechnik, Industrietechnik, Gebrauchsgüter, Energie- und Gebäudetechnik
BASF;Carl-Bosch-Straße 38;67056;Ludwigshafen;Chemie
E.ON;Arnulfstraße 203;80634;München;Energie
Munich Re Group;Königinstr. 107;80802;München;Versicherung
Siemens;Werner-von-Siemens-Straße 1;80333;München;Automatisierung, Digitalisierung
Deutsche Bahn;Potsdamer Platz 2;10785;Berlin;Transport, Logistik
1 Name Straße PLZ Stadt Branche
2 Volkswagen Berliner Ring 2 38440 Wolfsburg Automobil
3 Mercedes-Benz Group Mercedesstraße 120 70372 Stuttgart Automobil
4 Allianz Reinsburgstraße 19 70178 Stuttgart Versicherung, Finanzdienstleistung
5 BMW Group Petuelring 130 80809 München Automobil
6 Deutsche Telekom Landgrabenweg 151 53227 Bonn Telekommunikation, Informationstechnologie
7 Deutsche Post DHL Group Charles-de-Gaulle-Str. 20 53113 Bonn Logistik
8 Bosch Group Robert-Bosch-Platz 1 70839 Gerlingen-Schillerhöhe Kraftfahrzeugtechnik, Industrietechnik, Gebrauchsgüter, Energie- und Gebäudetechnik
9 BASF Carl-Bosch-Straße 38 67056 Ludwigshafen Chemie
10 E.ON Arnulfstraße 203 80634 München Energie
11 Munich Re Group Königinstr. 107 80802 München Versicherung
12 Siemens Werner-von-Siemens-Straße 1 80333 München Automatisierung, Digitalisierung
13 Deutsche Bahn Potsdamer Platz 2 10785 Berlin Transport, Logistik

View File

@ -0,0 +1,479 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "dbd6eae9",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import ipywidgets as widgets\n",
"pd.options.plotting.backend = \"plotly\""
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "8b447b09",
"metadata": {},
"outputs": [],
"source": [
"df=pd.read_csv('Telekom_Data_NewOrder.csv', sep=';',decimal=',') "
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "5fc7b7d2",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Metrik</th>\n",
" <th>Datum</th>\n",
" <th>Summe [Milliarden €]</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2005</td>\n",
" <td>59.600</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2006</td>\n",
" <td>61.300</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2007</td>\n",
" <td>62.500</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2008</td>\n",
" <td>61.700</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2009</td>\n",
" <td>64.600</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2010</td>\n",
" <td>62.420</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2011</td>\n",
" <td>58.650</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2012</td>\n",
" <td>58.170</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2013</td>\n",
" <td>60.130</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2014</td>\n",
" <td>62.660</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2015</td>\n",
" <td>69.230</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2016</td>\n",
" <td>73.100</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2017</td>\n",
" <td>74.950</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2018</td>\n",
" <td>75.660</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2019</td>\n",
" <td>80.530</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2020</td>\n",
" <td>99.950</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2021</td>\n",
" <td>107.610</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2022</td>\n",
" <td>114.200</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2005</td>\n",
" <td>7.600</td>\n",
" </tr>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2006</td>\n",
" <td>5.300</td>\n",
" </tr>\n",
" <tr>\n",
" <th>20</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2007</td>\n",
" <td>5.300</td>\n",
" </tr>\n",
" <tr>\n",
" <th>21</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2008</td>\n",
" <td>7.000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>22</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2009</td>\n",
" <td>6.000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>23</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2010</td>\n",
" <td>5.510</td>\n",
" </tr>\n",
" <tr>\n",
" <th>24</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2011</td>\n",
" <td>5.560</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2012</td>\n",
" <td>-3.960</td>\n",
" </tr>\n",
" <tr>\n",
" <th>26</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2013</td>\n",
" <td>4.930</td>\n",
" </tr>\n",
" <tr>\n",
" <th>27</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2014</td>\n",
" <td>7.250</td>\n",
" </tr>\n",
" <tr>\n",
" <th>28</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2015</td>\n",
" <td>7.030</td>\n",
" </tr>\n",
" <tr>\n",
" <th>29</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2016</td>\n",
" <td>9.160</td>\n",
" </tr>\n",
" <tr>\n",
" <th>30</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2017</td>\n",
" <td>9.380</td>\n",
" </tr>\n",
" <tr>\n",
" <th>31</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2018</td>\n",
" <td>8.000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>32</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2019</td>\n",
" <td>9.460</td>\n",
" </tr>\n",
" <tr>\n",
" <th>33</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2020</td>\n",
" <td>12.370</td>\n",
" </tr>\n",
" <tr>\n",
" <th>34</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2021</td>\n",
" <td>12.580</td>\n",
" </tr>\n",
" <tr>\n",
" <th>35</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2022</td>\n",
" <td>15.410</td>\n",
" </tr>\n",
" <tr>\n",
" <th>36</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2018</td>\n",
" <td>23.333</td>\n",
" </tr>\n",
" <tr>\n",
" <th>37</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2019</td>\n",
" <td>24.731</td>\n",
" </tr>\n",
" <tr>\n",
" <th>38</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2020</td>\n",
" <td>35.017</td>\n",
" </tr>\n",
" <tr>\n",
" <th>39</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2021</td>\n",
" <td>37.330</td>\n",
" </tr>\n",
" <tr>\n",
" <th>40</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2022</td>\n",
" <td>40.208</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Metrik Datum Summe [Milliarden €]\n",
"0 Umsatz 01.01.2005 59.600\n",
"1 Umsatz 01.01.2006 61.300\n",
"2 Umsatz 01.01.2007 62.500\n",
"3 Umsatz 01.01.2008 61.700\n",
"4 Umsatz 01.01.2009 64.600\n",
"5 Umsatz 01.01.2010 62.420\n",
"6 Umsatz 01.01.2011 58.650\n",
"7 Umsatz 01.01.2012 58.170\n",
"8 Umsatz 01.01.2013 60.130\n",
"9 Umsatz 01.01.2014 62.660\n",
"10 Umsatz 01.01.2015 69.230\n",
"11 Umsatz 01.01.2016 73.100\n",
"12 Umsatz 01.01.2017 74.950\n",
"13 Umsatz 01.01.2018 75.660\n",
"14 Umsatz 01.01.2019 80.530\n",
"15 Umsatz 01.01.2020 99.950\n",
"16 Umsatz 01.01.2021 107.610\n",
"17 Umsatz 01.01.2022 114.200\n",
"18 EBIT 01.01.2005 7.600\n",
"19 EBIT 01.01.2006 5.300\n",
"20 EBIT 01.01.2007 5.300\n",
"21 EBIT 01.01.2008 7.000\n",
"22 EBIT 01.01.2009 6.000\n",
"23 EBIT 01.01.2010 5.510\n",
"24 EBIT 01.01.2011 5.560\n",
"25 EBIT 01.01.2012 -3.960\n",
"26 EBIT 01.01.2013 4.930\n",
"27 EBIT 01.01.2014 7.250\n",
"28 EBIT 01.01.2015 7.030\n",
"29 EBIT 01.01.2016 9.160\n",
"30 EBIT 01.01.2017 9.380\n",
"31 EBIT 01.01.2018 8.000\n",
"32 EBIT 01.01.2019 9.460\n",
"33 EBIT 01.01.2020 12.370\n",
"34 EBIT 01.01.2021 12.580\n",
"35 EBIT 01.01.2022 15.410\n",
"36 EBITDA 01.01.2018 23.333\n",
"37 EBITDA 01.01.2019 24.731\n",
"38 EBITDA 01.01.2020 35.017\n",
"39 EBITDA 01.01.2021 37.330\n",
"40 EBITDA 01.01.2022 40.208"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df"
]
},
{
"cell_type": "markdown",
"id": "d5c6c68d",
"metadata": {},
"source": [
"---------------------------------\n",
"# Schreibe Unternehmensdaten in PostgreSQL"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "6c09bdca",
"metadata": {},
"outputs": [],
"source": [
"import psycopg2"
]
},
{
"cell_type": "markdown",
"id": "383fb9a9",
"metadata": {},
"source": [
"### Verbinde zur Datenbank"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "3e1ea224",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Database connected successfully\n"
]
}
],
"source": [
"conn = psycopg2.connect(\n",
" host=\"localhost\",\n",
" database=\"transparenz\",\n",
" user=\"postgres\",\n",
" password=\"postgres\")\n",
"\n",
"print(\"Database connected successfully\")"
]
},
{
"cell_type": "markdown",
"id": "22b9ab1d",
"metadata": {},
"source": [
"## Iteriere durch Dataframe und schreibe Datensätze in Tabelle *Company*"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "961ac836",
"metadata": {},
"outputs": [],
"source": [
"cur = conn.cursor()\n",
"\n",
"PK_ID=5 #BASF hat den PK 8, deshalb wird dieser manuell hinzugefügt\n",
"\n",
"\n",
"for i in range(len(df)):\n",
" #get data from dataframe\n",
" kind_of=str(df['Metrik'].iloc[i])\n",
" date=str(df['Datum'].iloc[i])\n",
" amount=float(df['Summe [Milliarden €]'].iloc[i])\n",
" \n",
" postgres_insert_query = \"\"\" INSERT INTO finance (company_id,kind_of, date, sum) VALUES (%s,%s,%s,%s)\"\"\" \n",
" record_to_insert = (PK_ID,kind_of,date,amount)\n",
" cur.execute(postgres_insert_query, record_to_insert) \n",
" #print(postgres_insert_query, record_to_insert)\n",
" \n",
"conn.commit()\n",
"conn.close()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "46b5be7c",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,416 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "dbd6eae9",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import ipywidgets as widgets\n",
"pd.options.plotting.backend = \"plotly\""
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "8b447b09",
"metadata": {},
"outputs": [],
"source": [
"df=pd.read_csv('EON_Data_NewOrder.csv', sep=';',decimal=',') "
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "5fc7b7d2",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Metrik</th>\n",
" <th>Datum</th>\n",
" <th>Summe [Milliarden €]</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2007</td>\n",
" <td>66.912</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2008</td>\n",
" <td>84.873</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2009</td>\n",
" <td>79.974</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2010</td>\n",
" <td>92.863</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2011</td>\n",
" <td>112.954</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2012</td>\n",
" <td>132.093</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2013</td>\n",
" <td>119.615</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2014</td>\n",
" <td>113.095</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2015</td>\n",
" <td>42.656</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2016</td>\n",
" <td>38.173</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2017</td>\n",
" <td>37.965</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2018</td>\n",
" <td>30.084</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2019</td>\n",
" <td>41.284</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2020</td>\n",
" <td>60.944</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2021</td>\n",
" <td>77.358</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>Umsatz</td>\n",
" <td>01.01.2022</td>\n",
" <td>115.660</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2012</td>\n",
" <td>7.010</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2013</td>\n",
" <td>5.640</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2014</td>\n",
" <td>4.700</td>\n",
" </tr>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2015</td>\n",
" <td>3.600</td>\n",
" </tr>\n",
" <tr>\n",
" <th>20</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2016</td>\n",
" <td>3.100</td>\n",
" </tr>\n",
" <tr>\n",
" <th>21</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2017</td>\n",
" <td>3.100</td>\n",
" </tr>\n",
" <tr>\n",
" <th>22</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2018</td>\n",
" <td>2.990</td>\n",
" </tr>\n",
" <tr>\n",
" <th>23</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2019</td>\n",
" <td>3.220</td>\n",
" </tr>\n",
" <tr>\n",
" <th>24</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2020</td>\n",
" <td>3.780</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2021</td>\n",
" <td>4.720</td>\n",
" </tr>\n",
" <tr>\n",
" <th>26</th>\n",
" <td>EBIT</td>\n",
" <td>01.01.2022</td>\n",
" <td>5.200</td>\n",
" </tr>\n",
" <tr>\n",
" <th>27</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2018</td>\n",
" <td>4.840</td>\n",
" </tr>\n",
" <tr>\n",
" <th>28</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2019</td>\n",
" <td>5.558</td>\n",
" </tr>\n",
" <tr>\n",
" <th>29</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2020</td>\n",
" <td>6.905</td>\n",
" </tr>\n",
" <tr>\n",
" <th>30</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2021</td>\n",
" <td>7.889</td>\n",
" </tr>\n",
" <tr>\n",
" <th>31</th>\n",
" <td>EBITDA</td>\n",
" <td>01.01.2022</td>\n",
" <td>8.059</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Metrik Datum Summe [Milliarden €]\n",
"0 Umsatz 01.01.2007 66.912\n",
"1 Umsatz 01.01.2008 84.873\n",
"2 Umsatz 01.01.2009 79.974\n",
"3 Umsatz 01.01.2010 92.863\n",
"4 Umsatz 01.01.2011 112.954\n",
"5 Umsatz 01.01.2012 132.093\n",
"6 Umsatz 01.01.2013 119.615\n",
"7 Umsatz 01.01.2014 113.095\n",
"8 Umsatz 01.01.2015 42.656\n",
"9 Umsatz 01.01.2016 38.173\n",
"10 Umsatz 01.01.2017 37.965\n",
"11 Umsatz 01.01.2018 30.084\n",
"12 Umsatz 01.01.2019 41.284\n",
"13 Umsatz 01.01.2020 60.944\n",
"14 Umsatz 01.01.2021 77.358\n",
"15 Umsatz 01.01.2022 115.660\n",
"16 EBIT 01.01.2012 7.010\n",
"17 EBIT 01.01.2013 5.640\n",
"18 EBIT 01.01.2014 4.700\n",
"19 EBIT 01.01.2015 3.600\n",
"20 EBIT 01.01.2016 3.100\n",
"21 EBIT 01.01.2017 3.100\n",
"22 EBIT 01.01.2018 2.990\n",
"23 EBIT 01.01.2019 3.220\n",
"24 EBIT 01.01.2020 3.780\n",
"25 EBIT 01.01.2021 4.720\n",
"26 EBIT 01.01.2022 5.200\n",
"27 EBITDA 01.01.2018 4.840\n",
"28 EBITDA 01.01.2019 5.558\n",
"29 EBITDA 01.01.2020 6.905\n",
"30 EBITDA 01.01.2021 7.889\n",
"31 EBITDA 01.01.2022 8.059"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df"
]
},
{
"cell_type": "markdown",
"id": "d5c6c68d",
"metadata": {},
"source": [
"---------------------------------\n",
"# Schreibe Unternehmensdaten in PostgreSQL"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "6c09bdca",
"metadata": {},
"outputs": [],
"source": [
"import psycopg2"
]
},
{
"cell_type": "markdown",
"id": "383fb9a9",
"metadata": {},
"source": [
"### Verbinde zur Datenbank"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "3e1ea224",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Database connected successfully\n"
]
}
],
"source": [
"conn = psycopg2.connect(\n",
" host=\"localhost\",\n",
" database=\"transparenz\",\n",
" user=\"postgres\",\n",
" password=\"postgres\")\n",
"\n",
"print(\"Database connected successfully\")"
]
},
{
"cell_type": "markdown",
"id": "22b9ab1d",
"metadata": {},
"source": [
"## Iteriere durch Dataframe und schreibe Datensätze in Tabelle *Company*"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "961ac836",
"metadata": {},
"outputs": [],
"source": [
"cur = conn.cursor()\n",
"\n",
"PK_ID=9 #BASF hat den PK 8, deshalb wird dieser manuell hinzugefügt\n",
"\n",
"\n",
"for i in range(len(df)):\n",
" #get data from dataframe\n",
" kind_of=str(df['Metrik'].iloc[i])\n",
" date=str(df['Datum'].iloc[i])\n",
" amount=float(df['Summe [Milliarden €]'].iloc[i])\n",
" \n",
" postgres_insert_query = \"\"\" INSERT INTO finance (company_id,kind_of, date, sum) VALUES (%s,%s,%s,%s)\"\"\" \n",
" record_to_insert = (PK_ID,kind_of,date,amount)\n",
" cur.execute(postgres_insert_query, record_to_insert) \n",
" #print(postgres_insert_query, record_to_insert)\n",
" \n",
"conn.commit()\n",
"conn.close()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "46b5be7c",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,10 @@
Stadt;Name
Aschaffenburg;Amtsgericht Aschaffenburg
Bamberg;Amtsgericht Bamberg
Bayreuth;Amtsgericht Bayreuth
Duesseldorf;Amtsgericht Duesseldorf
Duisburg;Amtsgericht Duisburg
Duisburg;Amtsgericht Duisburg-Hamborn
Duisburg;Amtsgericht Duisburg-Ruhrort
Oberhausen;Amtsgericht Oberhausen
Wuppertal;Amtsgericht Wuppertal
1 Stadt Name
2 Aschaffenburg Amtsgericht Aschaffenburg
3 Bamberg Amtsgericht Bamberg
4 Bayreuth Amtsgericht Bayreuth
5 Duesseldorf Amtsgericht Duesseldorf
6 Duisburg Amtsgericht Duisburg
7 Duisburg Amtsgericht Duisburg-Hamborn
8 Duisburg Amtsgericht Duisburg-Ruhrort
9 Oberhausen Amtsgericht Oberhausen
10 Wuppertal Amtsgericht Wuppertal

View File

@ -0,0 +1,58 @@
Metrik;Datum;Summe [Milliarden €]
Umsatz;01.01.1999;29,473
Umsatz;01.01.2000;35,946
Umsatz;01.01.2001;32,5
Umsatz;01.01.2002;32,216
Umsatz;01.01.2003;33,361
Umsatz;01.01.2004;37,537
Umsatz;01.01.2005;42,745
Umsatz;01.01.2006;52,61
Umsatz;01.01.2007;57,951
Umsatz;01.01.2008;62,304
Umsatz;01.01.2009;50,693
Umsatz;01.01.2010;63,873
Umsatz;01.01.2011;73,497
Umsatz;01.01.2012;72,129
Umsatz;01.01.2013;73,973
Umsatz;01.01.2014;74,326
Umsatz;01.01.2015;70,449
Umsatz;01.01.2016;57,55
Umsatz;01.01.2017;61,223
Umsatz;01.01.2018;60,22
Umsatz;01.01.2019;59,316
Umsatz;01.01.2020;59,149
Umsatz;01.01.2021;78,598
Umsatz;01.01.2022;87,327
EBIT;01.01.2005;5,83
EBIT;01.01.2006;6,75
EBIT;01.01.2007;7,316
EBIT;01.01.2008;6,463
EBIT;01.01.2009;3,677
EBIT;01.01.2010;7,761
EBIT;01.01.2011;8,586
EBIT;01.01.2012;6,742
EBIT;01.01.2013;7,16
EBIT;01.01.2014;7,626
EBIT;01.01.2015;6,248
EBIT;01.01.2016;6,275
EBIT;01.01.2017;7,587
EBIT;01.01.2018;5,974
EBIT;01.01.2019;4,201
EBIT;01.01.2020;-0,191
EBIT;01.01.2021;7,677
EBIT;01.01.2022;6,548
EBITDA;01.01.2008;9,562
EBITDA;01.01.2009;7,388
EBITDA;01.01.2010;11,131
EBITDA;01.01.2011;11,993
EBITDA;01.01.2012;10,009
EBITDA;01.01.2013;10,432
EBITDA;01.01.2014;11,043
EBITDA;01.01.2015;10,649
EBITDA;01.01.2016;10,526
EBITDA;01.01.2017;10,765
EBITDA;01.01.2018;8,97
EBITDA;01.01.2019;8,185
EBITDA;01.01.2020;6,494
EBITDA;01.01.2021;11,355
EBITDA;01.01.2022;10,748
1 Metrik Datum Summe [Milliarden €]
2 Umsatz 01.01.1999 29,473
3 Umsatz 01.01.2000 35,946
4 Umsatz 01.01.2001 32,5
5 Umsatz 01.01.2002 32,216
6 Umsatz 01.01.2003 33,361
7 Umsatz 01.01.2004 37,537
8 Umsatz 01.01.2005 42,745
9 Umsatz 01.01.2006 52,61
10 Umsatz 01.01.2007 57,951
11 Umsatz 01.01.2008 62,304
12 Umsatz 01.01.2009 50,693
13 Umsatz 01.01.2010 63,873
14 Umsatz 01.01.2011 73,497
15 Umsatz 01.01.2012 72,129
16 Umsatz 01.01.2013 73,973
17 Umsatz 01.01.2014 74,326
18 Umsatz 01.01.2015 70,449
19 Umsatz 01.01.2016 57,55
20 Umsatz 01.01.2017 61,223
21 Umsatz 01.01.2018 60,22
22 Umsatz 01.01.2019 59,316
23 Umsatz 01.01.2020 59,149
24 Umsatz 01.01.2021 78,598
25 Umsatz 01.01.2022 87,327
26 EBIT 01.01.2005 5,83
27 EBIT 01.01.2006 6,75
28 EBIT 01.01.2007 7,316
29 EBIT 01.01.2008 6,463
30 EBIT 01.01.2009 3,677
31 EBIT 01.01.2010 7,761
32 EBIT 01.01.2011 8,586
33 EBIT 01.01.2012 6,742
34 EBIT 01.01.2013 7,16
35 EBIT 01.01.2014 7,626
36 EBIT 01.01.2015 6,248
37 EBIT 01.01.2016 6,275
38 EBIT 01.01.2017 7,587
39 EBIT 01.01.2018 5,974
40 EBIT 01.01.2019 4,201
41 EBIT 01.01.2020 -0,191
42 EBIT 01.01.2021 7,677
43 EBIT 01.01.2022 6,548
44 EBITDA 01.01.2008 9,562
45 EBITDA 01.01.2009 7,388
46 EBITDA 01.01.2010 11,131
47 EBITDA 01.01.2011 11,993
48 EBITDA 01.01.2012 10,009
49 EBITDA 01.01.2013 10,432
50 EBITDA 01.01.2014 11,043
51 EBITDA 01.01.2015 10,649
52 EBITDA 01.01.2016 10,526
53 EBITDA 01.01.2017 10,765
54 EBITDA 01.01.2018 8,97
55 EBITDA 01.01.2019 8,185
56 EBITDA 01.01.2020 6,494
57 EBITDA 01.01.2021 11,355
58 EBITDA 01.01.2022 10,748

View File

@ -0,0 +1,33 @@
Metrik;Datum;Summe [Milliarden €]
Umsatz;01.01.2007;66,912
Umsatz;01.01.2008;84,873
Umsatz;01.01.2009;79,974
Umsatz;01.01.2010;92,863
Umsatz;01.01.2011;112,954
Umsatz;01.01.2012;132,093
Umsatz;01.01.2013;119,615
Umsatz;01.01.2014;113,095
Umsatz;01.01.2015;42,656
Umsatz;01.01.2016;38,173
Umsatz;01.01.2017;37,965
Umsatz;01.01.2018;30,084
Umsatz;01.01.2019;41,284
Umsatz;01.01.2020;60,944
Umsatz;01.01.2021;77,358
Umsatz;01.01.2022;115,66
EBIT;01.01.2012;7,01
EBIT;01.01.2013;5,64
EBIT;01.01.2014;4,7
EBIT;01.01.2015;3,6
EBIT;01.01.2016;3,1
EBIT;01.01.2017;3,1
EBIT;01.01.2018;2,99
EBIT;01.01.2019;3,22
EBIT;01.01.2020;3,78
EBIT;01.01.2021;4,72
EBIT;01.01.2022;5,2
EBITDA;01.01.2018;4,84
EBITDA;01.01.2019;5,558
EBITDA;01.01.2020;6,905
EBITDA;01.01.2021;7,889
EBITDA;01.01.2022;8,059
1 Metrik Datum Summe [Milliarden €]
2 Umsatz 01.01.2007 66,912
3 Umsatz 01.01.2008 84,873
4 Umsatz 01.01.2009 79,974
5 Umsatz 01.01.2010 92,863
6 Umsatz 01.01.2011 112,954
7 Umsatz 01.01.2012 132,093
8 Umsatz 01.01.2013 119,615
9 Umsatz 01.01.2014 113,095
10 Umsatz 01.01.2015 42,656
11 Umsatz 01.01.2016 38,173
12 Umsatz 01.01.2017 37,965
13 Umsatz 01.01.2018 30,084
14 Umsatz 01.01.2019 41,284
15 Umsatz 01.01.2020 60,944
16 Umsatz 01.01.2021 77,358
17 Umsatz 01.01.2022 115,66
18 EBIT 01.01.2012 7,01
19 EBIT 01.01.2013 5,64
20 EBIT 01.01.2014 4,7
21 EBIT 01.01.2015 3,6
22 EBIT 01.01.2016 3,1
23 EBIT 01.01.2017 3,1
24 EBIT 01.01.2018 2,99
25 EBIT 01.01.2019 3,22
26 EBIT 01.01.2020 3,78
27 EBIT 01.01.2021 4,72
28 EBIT 01.01.2022 5,2
29 EBITDA 01.01.2018 4,84
30 EBITDA 01.01.2019 5,558
31 EBITDA 01.01.2020 6,905
32 EBITDA 01.01.2021 7,889
33 EBITDA 01.01.2022 8,059

View File

@ -0,0 +1,42 @@
Metrik;Datum;Summe [Milliarden €]
Umsatz;01.01.2005;59,6
Umsatz;01.01.2006;61,3
Umsatz;01.01.2007;62,5
Umsatz;01.01.2008;61,7
Umsatz;01.01.2009;64,6
Umsatz;01.01.2010;62,42
Umsatz;01.01.2011;58,65
Umsatz;01.01.2012;58,17
Umsatz;01.01.2013;60,13
Umsatz;01.01.2014;62,66
Umsatz;01.01.2015;69,23
Umsatz;01.01.2016;73,1
Umsatz;01.01.2017;74,95
Umsatz;01.01.2018;75,66
Umsatz;01.01.2019;80,53
Umsatz;01.01.2020;99,95
Umsatz;01.01.2021;107,61
Umsatz;01.01.2022;114,2
EBIT;01.01.2005;7,6
EBIT;01.01.2006;5,3
EBIT;01.01.2007;5,3
EBIT;01.01.2008;7
EBIT;01.01.2009;6
EBIT;01.01.2010;5,51
EBIT;01.01.2011;5,56
EBIT;01.01.2012;-3,96
EBIT;01.01.2013;4,93
EBIT;01.01.2014;7,25
EBIT;01.01.2015;7,03
EBIT;01.01.2016;9,16
EBIT;01.01.2017;9,38
EBIT;01.01.2018;8
EBIT;01.01.2019;9,46
EBIT;01.01.2020;12,37
EBIT;01.01.2021;12,58
EBIT;01.01.2022;15,41
EBITDA;01.01.2018;23,333
EBITDA;01.01.2019;24,731
EBITDA;01.01.2020;35,017
EBITDA;01.01.2021;37,33
EBITDA;01.01.2022;40,208
1 Metrik Datum Summe [Milliarden €]
2 Umsatz 01.01.2005 59,6
3 Umsatz 01.01.2006 61,3
4 Umsatz 01.01.2007 62,5
5 Umsatz 01.01.2008 61,7
6 Umsatz 01.01.2009 64,6
7 Umsatz 01.01.2010 62,42
8 Umsatz 01.01.2011 58,65
9 Umsatz 01.01.2012 58,17
10 Umsatz 01.01.2013 60,13
11 Umsatz 01.01.2014 62,66
12 Umsatz 01.01.2015 69,23
13 Umsatz 01.01.2016 73,1
14 Umsatz 01.01.2017 74,95
15 Umsatz 01.01.2018 75,66
16 Umsatz 01.01.2019 80,53
17 Umsatz 01.01.2020 99,95
18 Umsatz 01.01.2021 107,61
19 Umsatz 01.01.2022 114,2
20 EBIT 01.01.2005 7,6
21 EBIT 01.01.2006 5,3
22 EBIT 01.01.2007 5,3
23 EBIT 01.01.2008 7
24 EBIT 01.01.2009 6
25 EBIT 01.01.2010 5,51
26 EBIT 01.01.2011 5,56
27 EBIT 01.01.2012 -3,96
28 EBIT 01.01.2013 4,93
29 EBIT 01.01.2014 7,25
30 EBIT 01.01.2015 7,03
31 EBIT 01.01.2016 9,16
32 EBIT 01.01.2017 9,38
33 EBIT 01.01.2018 8
34 EBIT 01.01.2019 9,46
35 EBIT 01.01.2020 12,37
36 EBIT 01.01.2021 12,58
37 EBIT 01.01.2022 15,41
38 EBITDA 01.01.2018 23,333
39 EBITDA 01.01.2019 24,731
40 EBITDA 01.01.2020 35,017
41 EBITDA 01.01.2021 37,33
42 EBITDA 01.01.2022 40,208

View File

@ -0,0 +1,20 @@
Mohammed;Klein
Myriam;Koch
Dorothe;Zerusedemeiner
Emine;Puviplau
Galina;Tosewede
Hans-Walter;M<>didostein
Ludmilla;Krause
Jessica;Lesibedemeiner
Franz;Lowufohein
Krzysztof;Gaselatem<65>ller
Gerolf;Navusedeson
Sibylla;Sutedihein
Nina;Golebede
Alicja;Revibodomeiner
Meryem;Kadeduhein
Janina;Zimmermann
Hendrik;Kr<4B>ger
Oskar;Podadi
Maria-Luise;Nelaflodeson
Nadine;Niwogatemeiner
1 Mohammed Klein
2 Myriam Koch
3 Dorothe Zerusedemeiner
4 Emine Puviplau
5 Galina Tosewede
6 Hans-Walter Mädidostein
7 Ludmilla Krause
8 Jessica Lesibedemeiner
9 Franz Lowufohein
10 Krzysztof Gaselatemüller
11 Gerolf Navusedeson
12 Sibylla Sutedihein
13 Nina Golebede
14 Alicja Revibodomeiner
15 Meryem Kadeduhein
16 Janina Zimmermann
17 Hendrik Krüger
18 Oskar Podadi
19 Maria-Luise Nelaflodeson
20 Nadine Niwogatemeiner

View File

@ -0,0 +1,19 @@
Company_HR;Company_Court;Jahr;Umsatz;Ebit;EBITDA
;12336;5;2005;59600;7600;
;12336;5;2006;61300;5300;
;12336;5;2007;62500;5300;
;12336;5;2008;61700;7000;
;12336;5;2009;64600;6000;
;12336;5;2010;62420;5510;
;12336;5;2011;58650;5560;
;12336;5;2012;58170;-3960;
;12336;5;2013;60130;4930;
;12336;5;2014;62660;7250;
;12336;5;2015;69230;7030;
;12336;5;2016;73100;9160;
;12336;5;2017;74950;9380;
;12336;5;2018;75660;8000;23333
;12336;5;2019;80530;9460;24731
;12336;5;2020;99950;12370;35017
;12336;5;2021;107610;12580;37330
;12336;5;2022;114200;15410;40208
1 Company_HR;Company_Court;Jahr;Umsatz;Ebit;EBITDA
2 ;12336;5;2005;59600;7600;
3 ;12336;5;2006;61300;5300;
4 ;12336;5;2007;62500;5300;
5 ;12336;5;2008;61700;7000;
6 ;12336;5;2009;64600;6000;
7 ;12336;5;2010;62420;5510;
8 ;12336;5;2011;58650;5560;
9 ;12336;5;2012;58170;-3960;
10 ;12336;5;2013;60130;4930;
11 ;12336;5;2014;62660;7250;
12 ;12336;5;2015;69230;7030;
13 ;12336;5;2016;73100;9160;
14 ;12336;5;2017;74950;9380;
15 ;12336;5;2018;75660;8000;23333
16 ;12336;5;2019;80530;9460;24731
17 ;12336;5;2020;99950;12370;35017
18 ;12336;5;2021;107610;12580;37330
19 ;12336;5;2022;114200;15410;40208

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
version: "3.8"
services:
db:
image: postgres:14.1-alpine
container_name: postgres
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
#- db:/var/lib/postgresql/data
- ./PostgreSQL:/var/lib/postgresql/data
pgadmin:
image: dpage/pgadmin4:7.2
container_name: pgadmin4_container
restart: always
ports:
- "5050:80"
environment:
PGADMIN_DEFAULT_EMAIL: admin@fh-swf.de
PGADMIN_DEFAULT_PASSWORD: admin
volumes:
# - pgadmin:/var/lib/pgadmin
- ./pgadmin:/var/lib/pgadmin
mongodb:
image: mongo:7.0.0-rc4
ports:
- '27017:27017'
volumes:
# - dbdata6:/data/db
- ./mongo:/data/db

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

View File

@ -0,0 +1,457 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Visualisierung eines Netzwerks\n",
"\n",
"In diesem Beispiel wird ein Graph mit networkx erstellt und anschließend mit pyvis visualisiert. Der Graph basiert auf Beispieldaten. Es werden erste Optionen in den Bereichen Größe, Farbe und Form der Knoten und Mouse-Over-Texte gezeigt.\n",
"\n",
"Der Code basiert auf den Dokumentationen der beiden Bibliotheken:\n",
"- [Networkx Dokumentation](https://networkx.org/documentation/stable/)\n",
"- [Pyvis Dokumentation](https://pyvis.readthedocs.io/en/latest/index.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Installation der Bibliotheken\n",
"\n",
"Networkx ist eine Python Bibliothek zur Erstellung und Analyse von Netzwerken. Pyvis ist eine Python Bibliothek zur interaktiven Visualisierung von Netzwerkgraphen. Beide können mit `pip` installiert werden. "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: networkx in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (2.6.3)\n",
"Requirement already satisfied: pyvis in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (0.3.2)\n",
"Requirement already satisfied: jinja2>=2.9.6 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from pyvis) (2.11.3)\n",
"Requirement already satisfied: networkx>=1.11 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from pyvis) (2.6.3)\n",
"Requirement already satisfied: ipython>=5.3.0 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from pyvis) (7.29.0)\n",
"Requirement already satisfied: jsonpickle>=1.4.1 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from pyvis) (3.0.1)\n",
"Requirement already satisfied: backcall in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (0.2.0)\n",
"Requirement already satisfied: pexpect>4.3 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (4.8.0)\n",
"Requirement already satisfied: jedi>=0.16 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (0.18.0)\n",
"Requirement already satisfied: traitlets>=4.2 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (5.1.0)\n",
"Requirement already satisfied: decorator in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (5.1.0)\n",
"Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (3.0.20)\n",
"Requirement already satisfied: matplotlib-inline in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (0.1.2)\n",
"Requirement already satisfied: appnope in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (0.1.2)\n",
"Requirement already satisfied: pygments in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (2.10.0)\n",
"Requirement already satisfied: pickleshare in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (0.7.5)\n",
"Requirement already satisfied: setuptools>=18.5 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from ipython>=5.3.0->pyvis) (58.0.4)\n",
"Requirement already satisfied: parso<0.9.0,>=0.8.0 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from jedi>=0.16->ipython>=5.3.0->pyvis) (0.8.2)\n",
"Requirement already satisfied: MarkupSafe>=0.23 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from jinja2>=2.9.6->pyvis) (1.1.1)\n",
"Requirement already satisfied: ptyprocess>=0.5 in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from pexpect>4.3->ipython>=5.3.0->pyvis) (0.7.0)\n",
"Requirement already satisfied: wcwidth in /Users/kim/opt/anaconda3/lib/python3.9/site-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython>=5.3.0->pyvis) (0.2.5)\n"
]
}
],
"source": [
"# install networkx and pyvis using pip\n",
"!pip install networkx\n",
"!pip install pyvis"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Erstellen eines Netzwerks mit Networkx\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import networkx as nx\n",
"\n",
"# create graph and use MultiGraph for nodes with multiple edges\n",
"G = nx.MultiGraph()\n",
"\n",
"# create list of nodes with attributes as a dictionary\n",
"nodes = [(1, {'label': 'Firma 1', 'branche': 'Branche 1', 'land': 'Land 1'}), \n",
" (2, {'label': 'Firma 2', 'branche': 'Branche 1', 'land': 'Land 2'}),\n",
" (3, {'label': 'Firma 3', 'branche': 'Branche 1', 'land': 'Land 3'}),\n",
" (4, {'label': 'Firma 4', 'branche': 'Branche 2', 'land': 'Land 4'}),\n",
" (5, {'label': 'Firma 5', 'branche': 'Branche 2', 'land': 'Land 1'}),\n",
" (6, {'label': 'Firma 6', 'branche': 'Branche 2', 'land': 'Land 3'}),\n",
" (7, {'label': 'Firma 7', 'branche': 'Branche 3', 'land': 'Land 3'}),\n",
" (8, {'label': 'Firma 8', 'branche': 'Branche 3', 'land': 'Land 2'}),\n",
" (9, {'label': 'Firma 9', 'branche': 'Branche 4', 'land': 'Land 1'}),\n",
" (10, {'label': 'Firma 10', 'branche': 'Branche 4', 'land': 'Land 4'}),\n",
" ]\n",
"\n",
"# create list of edges with attributes as a dictionary\n",
"edges = [\n",
" (1, 2, {'label': 'beziehung1'}), \n",
" (5, 2, {'label': 'beziehung2'}), \n",
" (1, 3, {'label': 'beziehung3'}), \n",
" (2, 4, {'label': 'beziehung3'}), \n",
" (2, 6, {'label': 'beziehung4'}), \n",
" (2, 5, {'label': 'beziehung4'}),\n",
" (8, 10, {'label': 'beziehung4'}),\n",
" (9, 10, {'label': 'beziehung3'}), \n",
" (3, 7, {'label': 'beziehung2'}), \n",
" (6, 8, {'label': 'beziehung1'}), \n",
" (6, 9, {'label': 'beziehung1'}), \n",
" (1, 6, {'label': 'beziehung2'})\n",
" ]\n",
"\n",
"# add nodes to the graph\n",
"G.add_nodes_from(nodes)\n",
"\n",
"# add edges to the graph, to hide arrow heads of the edges use option arrows = 'false'\n",
"G.add_edges_from(edges, arrows = 'false')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Information für das Mouse-Over hinterlegen\n",
"\n",
"Anforderung: Wenn man mit der Maus über einzelne Knoten fährt, sollten weitere Informationen sichtbar werden\n",
"\n",
"Aktuelle Umsetzung: 'title' wird als String für jeden Knoten gesetzt aus Name der Firma und Anzahl der Verbindungen.\n",
"\n",
"Erweiterungen/offene Fragen: Weitere Stammdaten-Informationen sind möglich, sofern sie zur Verfügung stehen."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"for node in G.nodes:\n",
" G.nodes[node]['title'] = G.nodes[node]['label'] + '\\n' + 'Anzahl Verbindungen: ' + str(G.degree[node])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Ändern der Größe der Knoten\n",
"\n",
"Anforderung: Größe in Abhängigkeit bestimmter Attribute ändern.\n",
"\n",
"Aktuelle Umsetzung: Setzen der Größe anhand der Anzahl der Kanten.\n",
"\n",
"Erweiterungen/offene Fragen: Weitere Attribute wie EBIT, Umsatz sollten möglich sein. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Erster Test zum Bestimmen der Verbindungen und der Anzahl"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2, 3, 6]\n",
"3\n"
]
}
],
"source": [
"# get all nodes connected to node 1\n",
"print(list(G.adj[1]))\n",
"\n",
"# get number of nodes connected to node 1\n",
"print(G.degree[1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Skalieren der Größe "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# scaling the size of the nodes by 5*degree\n",
"scale = 5 \n",
"\n",
"# getting all nodes and their number of connections\n",
"d = dict(G.degree)\n",
"\n",
"# updating dict\n",
"d.update((x, scale*(y+1)) for x, y in d.items())\n",
"\n",
"# setting size attribute according to created dictionary\n",
"nx.set_node_attributes(G,d,'size')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Visualisierung mit Pyvis\n",
"\n",
"Beim Anlegen des Netzwerks kann mit `neighborhood_highlight=True` bereits aktiviert werden, dass ein Klick auf einen Knoten benachbarte Knoten hervorhebt"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from pyvis.network import Network\n",
"\n",
"# create network, 'directed = true' allows multiple edges between nodes\n",
"nt = Network('1000px', '1000px', neighborhood_highlight=True, notebook=True, cdn_resources='in_line', directed=True)\n",
"\n",
"# populates the nodes and edges data structures\n",
"nt.from_nx(G)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Erste Tests zum Ändern der Art und Farbe eines einzelnen Knotens\n",
"\n",
"Change shape of one node:\n",
"`nt.nodes[1]['shape'] = 'square'`\n",
"\n",
"Change color of one node:\n",
"`nt.nodes[1]['color'] = 'red'`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Ändern der Farbe aller Knoten \n",
"\n",
"Anforderung: Ändere die Farbe basierend auf den Attributen \"Branche\" oder \"Land\"\n",
"\n",
"Aktuelle Umsetzung: Funktion, die die Farbe der Knoten anhand des ausgewählten Attributs (type) setzt.\n",
"\n",
"Erweiterungen/offene Fragen: Mögliche Branchen und Länder haben eine festcodierte Farbe, geht das generischer? Wie können weitere Attribute integriert werden?\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# define new function that sets the color of the nodes\n",
"def color_type (net, type):\n",
" ''' color_type sets the color of a network depending on an attribute of the nodes\n",
" net: network\n",
" type: 'branche' or 'land' '''\n",
"\n",
" colormap = {'Branche 1': '#87CEEB',\n",
" 'Branche 2': '#0f4c81',\n",
" 'Branche 3': '#B2FFFF', \n",
" 'Branche 4': '#191970',\n",
" 'Land 1': '#F8D568', \n",
" 'Land 2': '#F58025', \n",
" 'Land 3': '#CC5500', \n",
" 'Land 4': '#C0362C'}\n",
" for node in net.nodes:\n",
" node['color'] = colormap[node[type]]\n",
" return net\n",
"\n",
"# set color based on attribute\n",
"nt = color_type(nt, 'branche')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Ändern der Farbe aller Kanten\n",
"Normalerweise übernehmen die Kanten die Farben von ihren Knoten. Mit der Option 'color' kann für alle Kanten die gleiche Farbe gesetzt werden."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# set all edge colors \n",
"nt.options.edges.color = 'grey'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Speichern des Netzwerks als HTML\n",
"\n",
"Die Ausrichtung und Spannkräfte des Netzwerks können mit den 'physics options' gesetzt werden."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Netzwerk_Verflechtungsanalyse.html\n"
]
},
{
"data": {
"text/html": [
"\n",
" <iframe\n",
" width=\"1000px\"\n",
" height=\"1000px\"\n",
" src=\"Netzwerk_Verflechtungsanalyse.html\"\n",
" frameborder=\"0\"\n",
" allowfullscreen\n",
" \n",
" ></iframe>\n",
" "
],
"text/plain": [
"<IPython.lib.display.IFrame at 0x10b82b940>"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# activate physics options to try out different solver\n",
"#nt.show_buttons(filter_=['physics'])\n",
"\n",
"# set physics options\n",
"nt.barnes_hut(gravity=-8000, central_gravity=0.3, spring_length=200, spring_strength=0.1, damping=0.09, overlap=0)\n",
"\n",
"# create html and save in same folder\n",
"nt.show('Netzwerk_Verflechtungsanalyse.html')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Erstellen eines minimalen Netzwerks"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Netzwerk.html\n"
]
},
{
"data": {
"text/html": [
"\n",
" <iframe\n",
" width=\"1000px\"\n",
" height=\"1000px\"\n",
" src=\"Netzwerk.html\"\n",
" frameborder=\"0\"\n",
" allowfullscreen\n",
" \n",
" ></iframe>\n",
" "
],
"text/plain": [
"<IPython.lib.display.IFrame at 0x10bedbf70>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import networkx as nx\n",
"from pyvis.network import Network\n",
"\n",
"sn = nx.Graph()\n",
"sn_nodes = [1,2,3,4,5,6,7]\n",
"sn_edges = [(1,4),(2,4),(3,4),(4,5),(5,6),(5,7)]\n",
"\n",
"sn.add_nodes_from(sn_nodes, color = '#00509b')\n",
"sn.add_edges_from(sn_edges)\n",
"\n",
"net = Network('1000px', '1000px', notebook=True, cdn_resources='in_line')\n",
"\n",
"net.from_nx(sn)\n",
"net.show('Netzwerk.html')\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49"
},
"kernelspec": {
"display_name": "Python 3.10.1 64-bit",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.1"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,131 @@
from;to;label
1;50;AR
1;41;V
1;46;WP
1;48;AR
1;40;V
1;48;WP
1;37;AR
2;44;V
2;36;WP
2;50;AR
2;49;V
2;46;WP
2;48;AR
14;36;V
15;38;WP
16;44;AR
17;35;V
18;49;WP
19;31;AR
20;49;V
21;38;WP
22;31;AR
23;32;V
6;31;WP
25;39;AR
26;31;V
27;40;WP
28;46;AR
29;36;V
3;31;WP
1;35;AR
2;35;V
3;42;WP
4;33;AR
5;45;V
6;43;WP
7;45;AR
8;35;V
9;37;WP
10;32;AR
11;38;V
12;37;WP
13;35;AR
14;35;V
15;35;WP
16;35;AR
17;35;V
18;5;WP
19;47;AR
20;45;V
21;44;WP
22;49;AR
4;34;V
5;43;WP
25;43;AR
26;41;V
27;37;WP
28;33;AR
29;35;V
3;32;WP
1;38;AR
2;43;V
3;43;WP
4;35;AR
5;50;V
6;50;WP
6;50;AR
31;40;KOLL
32;41;KOLL
33;37;KOLL
1;38;AR
2;49;V
3;47;WP
4;50;AR
5;41;V
6;40;WP
7;46;AR
8;40;V
9;35;WP
10;32;AR
11;41;V
12;44;WP
13;38;AR
14;34;V
15;44;WP
16;31;AR
17;44;V
18;48;WP
19;32;AR
20;34;V
21;39;WP
22;45;AR
23;41;V
9;37;WP
25;44;AR
26;48;V
27;48;WP
28;47;AR
3;32;V
30;49;WP
1;37;AR
2;39;V
3;40;WP
4;31;AR
5;33;V
6;41;WP
7;32;AR
8;31;V
9;34;WP
10;31;AR
11;35;V
12;38;WP
13;36;AR
14;37;V
15;32;WP
16;45;AR
17;44;V
18;49;WP
19;37;AR
20;41;V
21;43;WP
22;35;AR
10;35;V
24;35;WP
25;50;AR
26;43;V
27;42;WP
28;34;AR
29;32;V
30;40;WP
1 from to label
2 1 50 AR
3 1 41 V
4 1 46 WP
5 1 48 AR
6 1 40 V
7 1 48 WP
8 1 37 AR
9 2 44 V
10 2 36 WP
11 2 50 AR
12 2 49 V
13 2 46 WP
14 2 48 AR
15 14 36 V
16 15 38 WP
17 16 44 AR
18 17 35 V
19 18 49 WP
20 19 31 AR
21 20 49 V
22 21 38 WP
23 22 31 AR
24 23 32 V
25 6 31 WP
26 25 39 AR
27 26 31 V
28 27 40 WP
29 28 46 AR
30 29 36 V
31 3 31 WP
32 1 35 AR
33 2 35 V
34 3 42 WP
35 4 33 AR
36 5 45 V
37 6 43 WP
38 7 45 AR
39 8 35 V
40 9 37 WP
41 10 32 AR
42 11 38 V
43 12 37 WP
44 13 35 AR
45 14 35 V
46 15 35 WP
47 16 35 AR
48 17 35 V
49 18 5 WP
50 19 47 AR
51 20 45 V
52 21 44 WP
53 22 49 AR
54 4 34 V
55 5 43 WP
56 25 43 AR
57 26 41 V
58 27 37 WP
59 28 33 AR
60 29 35 V
61 3 32 WP
62 1 38 AR
63 2 43 V
64 3 43 WP
65 4 35 AR
66 5 50 V
67 6 50 WP
68 6 50 AR
69 31 40 KOLL
70 32 41 KOLL
71 33 37 KOLL
72 1 38 AR
73 2 49 V
74 3 47 WP
75 4 50 AR
76 5 41 V
77 6 40 WP
78 7 46 AR
79 8 40 V
80 9 35 WP
81 10 32 AR
82 11 41 V
83 12 44 WP
84 13 38 AR
85 14 34 V
86 15 44 WP
87 16 31 AR
88 17 44 V
89 18 48 WP
90 19 32 AR
91 20 34 V
92 21 39 WP
93 22 45 AR
94 23 41 V
95 9 37 WP
96 25 44 AR
97 26 48 V
98 27 48 WP
99 28 47 AR
100 3 32 V
101 30 49 WP
102 1 37 AR
103 2 39 V
104 3 40 WP
105 4 31 AR
106 5 33 V
107 6 41 WP
108 7 32 AR
109 8 31 V
110 9 34 WP
111 10 31 AR
112 11 35 V
113 12 38 WP
114 13 36 AR
115 14 37 V
116 15 32 WP
117 16 45 AR
118 17 44 V
119 18 49 WP
120 19 37 AR
121 20 41 V
122 21 43 WP
123 22 35 AR
124 10 35 V
125 24 35 WP
126 25 50 AR
127 26 43 V
128 27 42 WP
129 28 34 AR
130 29 32 V
131 30 40 WP

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,318 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Networkx und Pyvis - Minimal Working Example"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Referenzen: \n",
"- [Networkx Dokumentation](https://networkx.org/documentation/stable/)\n",
"- [Pyvis Dokumentation](https://pyvis.readthedocs.io/en/latest/index.html)\n",
"- [Introduction to Python for Humanists](https://python-textbook.pythonhumanities.com/06_sna/06_01_05_networkx_pyvis.html)\n",
"\n",
"\n",
"Networkx ist eine Python Bibliothek zur Erstellung und Analyse von Netzwerken. Pyvis ist eine Python Bibliothek zur interaktiven Visualisierung von Netzwerkgraphen. Beide können mit `pip` installiert werden. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# install networkx and pyvis using pip\n",
"!pip install networkx\n",
"!pip install pyvis"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Panda Dataframe mit Beispieldaten\n",
"\n",
"Um ein Netzwerk aufbauen zu können, brauchen wir Daten für die Knoten (nodes) und Kanten (edges). Die Daten speichern wir jeweils in einem Panda Dataframe. Pandas kann ebenfalls mit `pip` installiert werden. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# install pandas using pip\n",
"!pip install pandas"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Knoten unseres Netzwerks sollen die Unternehmen und Personen darstellen. Eine `id` ermöglicht die eindeutige Identifizierung eines Knoten und hilft Duplikate zu vermeiden. Um Unternehmen von Personen differenzieren zu können, wurde zusätzlich die Information `type` aufgenommen. Sie dient in unserem Beispiel dazu, die Form des Knoten zu bestimmen. Durch `label` bekommt der Knoten eine für den User verständliche Bezeichnung. Weitere Informationen, wie zum Beispiel `branche`, können später für das Mouse Over oder die Größe oder Farbe der Knoten verwendet werden. \n",
"\n",
"Um in einem späteren Schritt die Attribute der Knoten an das Netzwerk zu übergeben, generieren wir zusätzlich eine Spalte `shape`, eine Spalte `color` und eine Spalte `title`."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" id label type branche shape color title\n",
"0 1 Firma 1 Company Branche 1 dot #f3e8eeff Firma 1\\nBranche 1\n",
"1 2 Firma 2 Company Branche 2 dot #bacdb0ff Firma 2\\nBranche 2\n",
"2 3 Firma 3 Company Branche 3 dot #729b79ff Firma 3\\nBranche 3\n",
"3 4 Firma 4 Company Branche 4 dot #475b63ff Firma 4\\nBranche 4\n",
"4 5 Firma 5 Company Branche 5 dot #2e2c2fff Firma 5\\nBranche 5\n"
]
}
],
"source": [
"# import pandas\n",
"import pandas as pd\n",
"\n",
"# create dataframe based on the sample data\n",
"df_nodes = pd.read_csv('nodes.csv', sep = ';')\n",
"\n",
"# define shape based on the type\n",
"node_shape = {'Company': 'dot', 'Person': 'triangle'}\n",
"df_nodes['shape'] = df_nodes['type'].map(node_shape)\n",
"\n",
"# define color based on branche\n",
"node_color = {'Branche 1': ' #f3e8eeff', 'Branche 2': '#bacdb0ff', 'Branche 3': '#729b79ff', 'Branche 4': '#475b63ff', 'Branche 5': '#2e2c2fff'}\n",
"df_nodes['color'] = df_nodes['branche'].map(node_color)\n",
"\n",
"# add information column that can be used for the mouse over in the graph\n",
"df_nodes = df_nodes.fillna('')\n",
"df_nodes['title'] = df_nodes['label'] + '\\n' + df_nodes['branche']\n",
"\n",
"# show first five entries of the dataframe\n",
"print(df_nodes.head())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Kanten visualisieren die Beziehungen zwischen den Unternehmen und Personen. Um in Pyvis eine Kante darzustellen braucht es minimal die Information zwischen welchen beiden Knoten eine Kante dargestellt werden soll. In den Beispieldaten entspricht dies `from` und `to`. Es wird jeweils auf die eindeutige `id` der jeweiligen Knoten referenziert. `label` bezeichnet hier die Art der Beziehung, z.B. AR = Aufsichtsrat. "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" from to label\n",
"0 1 50 AR\n",
"1 1 41 V\n",
"2 1 46 WP\n",
"3 1 48 AR\n",
"4 1 40 V\n"
]
}
],
"source": [
"# create dataframe based on the sample data\n",
"df_edges = pd.read_csv('edges.csv', sep = ';')\n",
"\n",
"# show first five entries of the dataframe\n",
"print(df_edges.head())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Erstellung eines Netzwerks mit networkx\n",
"\n",
"Zur Erstellung des Netzwerks nutzen wir `networkx`, da diese Bibliothek bessere Analysemöglichkeiten hat als `pyvis`. Das mit `networkx` erstellte Netzwerk können wir später an `pyvis` zur interaktiven Visualisierung übergeben werden. \n",
"\n",
"Wir erstellen die Knoten und Kanten auf Basis unsere beiden Dataframes."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# import networkx\n",
"import networkx as nx\n",
"\n",
"# initiate graph\n",
"graph = nx.MultiGraph()\n",
"\n",
"# create edges from dataframe\n",
"graph = nx.from_pandas_edgelist(df_edges, source = 'from', target = 'to', edge_attr= 'label')\n",
"\n",
"# update node attributes from dataframe\n",
"nodes_attr = df_nodes.set_index('id').to_dict(orient = 'index')\n",
"nx.set_node_attributes(graph, nodes_attr)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Mit Hilfe von `single_source_shortest_path_length` lässt sich die Anzahl der Nachbarn in unterschiedlichen Ebenen bestimmen. Durch die Eingrenzung des `cutoff` listet es alle Nachbarn und bis dahin benötigte Schritte. "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[{'id': 1, 'k=1': 8, 'k=2': 40, 'k=3': 49}, {'id': 50, 'k=1': 6, 'k=2': 23, 'k=3': 47}, {'id': 41, 'k=1': 8, 'k=2': 28, 'k=3': 48}, {'id': 46, 'k=1': 4, 'k=2': 21, 'k=3': 48}, {'id': 48, 'k=1': 5, 'k=2': 20, 'k=3': 47}]\n"
]
}
],
"source": [
"# create empty list to save k-neighbours for each node\n",
"k_neighbours = []\n",
"\n",
"# loop all nodes in the graph\n",
"for node in graph.nodes:\n",
" # create empty dictionary\n",
" dict = {}\n",
" # get node id\n",
" dict['id'] = node\n",
" # get k-neighbours for k=1,2,3, subtract -1 since output of single_source_shortest_path_length contains node itself\n",
" dict['k=1'] = len(nx.single_source_shortest_path_length(graph, node, cutoff=1))-1\n",
" dict['k=2'] = len(nx.single_source_shortest_path_length(graph, node, cutoff=2))-1\n",
" dict['k=3'] = len(nx.single_source_shortest_path_length(graph, node, cutoff=3))-1\n",
" # append list for each node\n",
" k_neighbours.append(dict)\n",
"\n",
"print(k_neighbours[:5])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Visualisierung des Netzwerks mit pyvis\n",
"\n",
"Für die Visualisierung importieren wir `Network` von `pyvis.network` und initialisiern das `pyvis` Netzwerk. Mit der Methode `from_nx` können wir das `networkx` Netzwerk übergeben. \n",
"\n",
"Die Größe der Knoten bestimmen wir je nach Auswahl entweder aufgrund der Anzahl der Verbindungen zu anderen Knoten oder anhand der Eigenvektor-Zentralität. Knoten mit vielen Verbindungen bzw. höherer Zentralität werden größer dargestellt."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# visualize using pyvis\n",
"from pyvis.network import Network\n",
"\n",
"# initiate network\n",
"net = Network(directed=False, neighborhood_highlight=True, bgcolor = \"white\", font_color=\"black\")\n",
"\n",
"# pass networkx graph to pyvis\n",
"net.from_nx(graph)\n",
"\n",
"# set edge options \n",
"net.inherit_edge_colors(False)\n",
"net.set_edge_smooth('dynamic')\n",
"\n",
"# chose size format\n",
"size_type = 'edges' # select 'edges' or 'eigen'\n",
"\n",
"adj_list = net.get_adj_list()\n",
"\n",
"if size_type == 'eigen':\n",
" eigenvector = nx.eigenvector_centrality(graph)\n",
"\n",
"# calculate and update size of the nodes depending on their number of edges\n",
"for node_id, neighbors in adj_list.items():\n",
" if size_type == 'edges':\n",
" size = len(neighbors)*5\n",
" if size_type == 'eigen':\n",
" size = eigenvector[node_id]*200\n",
" next((node.update({'size': size}) for node in net.nodes if node['id'] == node_id), None)\n",
"\n",
"# set the node distance and spring lenght using repulsion\n",
"net.repulsion(node_distance=250, spring_length=150)\n",
"\n",
"# activate physics buttons to further explore the available solvers:\n",
"# barnesHut, forceAtlas2Based, repulsion, hierarchicalRepulsion\n",
"net.show_buttons(filter_=['physics'])\n",
"\n",
"# save graph as HTML\n",
"net.save_graph('networkx_pyvis.html')\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Offene Fragen\n",
"- Gibt es Knoten ohne Verbindung? Wenn erst die Kanten generiert werden, werden diese vermutlich bisher nicht berücksichtigt.\n",
"- Bei der Auswahl eines Unternehmens werden verbundene Knoten nicht farblich angezeigt\n",
"- Bei mehreren Verbindung zwischen zwei Knoten wird derzeit nur die erste angezeigt. Dies kann umgehen werden, wenn man das Netzwerk die Option `directed = True` mitgibt. Allerdings werden dadurch die Kanten zu Pfeilen und man muss bei der Speicherung der Verbindungen aufpassen. Gibt es auch Möglichkeiten für undirected graphs?\n",
"- Sollen die Kanten zusätzlich gewichtet werden? "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Resultierende Anforderungen an die Daten\n",
"\n",
"Relationale Daten für die Kanten und Ecken sind ausreichend. Für die Knoten (= Unternehmen, Personen) werden benötigt:\n",
"- Eindeutige ID\n",
"- Bezeichnung, z.B. Name des Unternehmens bzw. der Person\n",
"- Weitere Informationen, die im Mouse Over angezeigt oder nach denen die Farben oder Größen der Knoten konfiguriert werden sollen\n",
"\n",
"Für die Kanten (= Verbindungen) werden benötigt:\n",
"- Eindeutige IDs zwischen denen die Verbindung besteht\n",
"- Art der Verbindung\n",
"- Ggfs. Gewichtungen\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49"
},
"kernelspec": {
"display_name": "Python 3.10.1 64-bit",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.1"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,51 @@
id;label;type;branche
1;Firma 1;Company;Branche 1
2;Firma 2;Company;Branche 2
3;Firma 3;Company;Branche 3
4;Firma 4;Company;Branche 4
5;Firma 5;Company;Branche 5
6;Firma 6;Company;Branche 1
7;Firma 7;Company;Branche 2
8;Firma 8;Company;Branche 3
9;Firma 9;Company;Branche 4
10;Firma 10;Company;Branche 5
11;Firma 11;Company;Branche 1
12;Firma 12;Company;Branche 2
13;Firma 13;Company;Branche 3
14;Firma 14;Company;Branche 4
15;Firma 15;Company;Branche 5
16;Firma 16;Company;Branche 1
17;Firma 17;Company;Branche 2
18;Firma 18;Company;Branche 3
19;Firma 19;Company;Branche 4
20;Firma 20;Company;Branche 5
21;Firma 21;Company;Branche 1
22;Firma 22;Company;Branche 2
23;Firma 23;Company;Branche 3
24;Firma 24;Company;Branche 4
25;Firma 25;Company;Branche 5
26;Firma 26;Company;Branche 1
27;Firma 27;Company;Branche 2
28;Firma 28;Company;Branche 3
29;Firma 29;Company;Branche 4
30;Firma 30;Company;Branche 5
31;Person 1;Person;
32;Person 2;Person;
33;Person 3;Person;
34;Person 4;Person;
35;Person 5;Person;
36;Person 6;Person;
37;Person 7;Person;
38;Person 8;Person;
39;Person 9;Person;
40;Person 10;Person;
41;Person 11;Person;
42;Person 12;Person;
43;Person 13;Person;
44;Person 14;Person;
45;Person 15;Person;
46;Person 16;Person;
47;Person 17;Person;
48;Person 18;Person;
49;Person 19;Person;
50;Person 20;Person;
1 id label type branche
2 1 Firma 1 Company Branche 1
3 2 Firma 2 Company Branche 2
4 3 Firma 3 Company Branche 3
5 4 Firma 4 Company Branche 4
6 5 Firma 5 Company Branche 5
7 6 Firma 6 Company Branche 1
8 7 Firma 7 Company Branche 2
9 8 Firma 8 Company Branche 3
10 9 Firma 9 Company Branche 4
11 10 Firma 10 Company Branche 5
12 11 Firma 11 Company Branche 1
13 12 Firma 12 Company Branche 2
14 13 Firma 13 Company Branche 3
15 14 Firma 14 Company Branche 4
16 15 Firma 15 Company Branche 5
17 16 Firma 16 Company Branche 1
18 17 Firma 17 Company Branche 2
19 18 Firma 18 Company Branche 3
20 19 Firma 19 Company Branche 4
21 20 Firma 20 Company Branche 5
22 21 Firma 21 Company Branche 1
23 22 Firma 22 Company Branche 2
24 23 Firma 23 Company Branche 3
25 24 Firma 24 Company Branche 4
26 25 Firma 25 Company Branche 5
27 26 Firma 26 Company Branche 1
28 27 Firma 27 Company Branche 2
29 28 Firma 28 Company Branche 3
30 29 Firma 29 Company Branche 4
31 30 Firma 30 Company Branche 5
32 31 Person 1 Person
33 32 Person 2 Person
34 33 Person 3 Person
35 34 Person 4 Person
36 35 Person 5 Person
37 36 Person 6 Person
38 37 Person 7 Person
39 38 Person 8 Person
40 39 Person 9 Person
41 40 Person 10 Person
42 41 Person 11 Person
43 42 Person 12 Person
44 43 Person 13 Person
45 44 Person 14 Person
46 45 Person 15 Person
47 46 Person 16 Person
48 47 Person 17 Person
49 48 Person 18 Person
50 49 Person 19 Person
51 50 Person 20 Person

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,698 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"jupyter": {
"outputs_hidden": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# DevOps for the Transparenzregister analysis"
]
},
{
"cell_type": "markdown",
"metadata": {
"jupyter": {
"outputs_hidden": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Dependency management in Python\n",
"### Tools\n",
"\n",
"- `The requirements.txt` lists all the dependencies of a project with version number and optionally with hashes and additional indexes and conditions for system specific differences.\n",
" - Changes are difficult because auf interdependency. \n",
" - Sync with requirements.txt is impossible via pip.\n",
" - All indirekt requirements need to be changed manually. \n",
" - Security and other routine upgrades for bugfixes are annoying and difficult to solve.\n",
" - Adding new requirements is complex."
]
},
{
"cell_type": "markdown",
"metadata": {
"jupyter": {
"outputs_hidden": false
},
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"- `pip-tools` is the next level up.\n",
" - Generates `requirements.txt` from `requirements.ini`\n",
" - Allows for sync with ``requirements.txt`\n",
" - No solution to manage multiple combinations of requirements for multiple problems.\n",
" - Applications or packages with dev and build tools\n",
" - Applications or packages with test and lint tools\n",
" - packages with additional typing packages\n",
" - A combination there of\n",
"- `pip-compile-multi` is an extension of `pip-tools` and allows for the generation of multiple requirements files.\n",
" - Only configured combinations of dependency groups are allowed.\n",
" - Different configurations may find different solutions."
]
},
{
"cell_type": "markdown",
"metadata": {
"jupyter": {
"outputs_hidden": false
},
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"- `poetry` is the most advanced tool to solve python dependencies\n",
" - Comparable to Javas `maven`\n",
" - Finds a complete solution for all requirement groups and installed groups as defined\n",
" - Allows for upgradable packages in defined bounds.\n",
" - Exports a solution that can be used on multiple machines to guarantee the same environment\n",
" - Handling of Virtual environments\n",
" - Automatically includes requirements in metadata and other entries for wheel when building\n",
" - Build and publication management\n",
" - Complete packaging configuration in `pyproject.toml` as required in **PEP 621**\n",
" - Supports plugins"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Defined Poetry dependency groups in our project\n",
"| Group | Contents & Purpose |\n",
"|:--------|:--------------------------------------------------------------------|\n",
"| root | The packages needed for the package itself |\n",
"| develop | Packages needed to support the development such as `jupyter` |\n",
"| lint | Packages needed for linting such as `mypy`, `pandas-stubs` & `ruff` |\n",
"| test | Packages needed for testing such as `pytest` |\n",
"| doc | Packages needed for the documentation build such as `sphinx` |"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"### How to use poetry\n",
"- `poetry new <project-name>` command creates a new poject with folder structure and everything.\n",
"- `poetry init` adds a poetry configuration to an existing project.\n",
"\n",
"- `poetry install` If the project is already configured will install the dependencies.\n",
" - kwarg `--with dev` force it to install the dependencies to develop with. In our case that would be a jupyter setup.\n",
" - kwarg `--without lint,test` forces poetry to not install the dependencies for the groups lint and test. For our case that would include pytest, mypy and typing packages."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"- `poetry add pandas_typing<=2` would add pandas with a versions smaller than `2.0.0` as a dependency.\n",
" - kwarg `--group lint` would configure it as part of the dependency group typing.\n",
" - A package can be part of multiple groups.\n",
" - By default, it is part of the package requirements that are part of the requirements if a build wheel is installed.\n",
" - Only direct requirements are configured! Indirect requirements are solved.\n",
"- `poetry update` updates the dependency solution and syncs the new dependencies.\n",
"- Requirement files can be exported.\n",
"\n",
"The full documentation can be found [here](https://python-poetry.org/)!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Linter\n",
"\n",
"Python is an\n",
"\n",
"- interpreted\n",
"- weak typed\n",
"\n",
"programing language.\n",
"Without validation of types and other compile mechanisms that highlight some errors.\n",
"\n",
"Lint stands for *lint is not a software testing tool* and analyses the code for known patterns that can lead to different kinds of problems."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Why lint: Application perspective:\n",
"- In Compiled programming languages many errors a thrown when a software is build. This is a first minimum quality gate for code.\n",
"- Hard typing also enforces a certain explicit expectation on arguments are expected. This is a secondary quality gate for code python does not share.\n",
"- This allows for a certain flexibility but allows for careless mistakes.\n",
"- Helps to find inconsistencies\n",
"- Helps to find security vulnerabilities"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Why lint: Human perspective:\n",
"- Certainty that naming conventions are followed allows for an easier code understanding.\n",
"- Auto whitespace formatting (Black) \n",
" - Absolut whitespace formatting allows for a clean differentials when versioning with git.\n",
" - The brain does not need to adapt on how somebody else formats his code\n",
" - No time wasted on beatification of code through whitespace\n",
"- Classic linter\n",
" - Faster increas in abilities\n",
" - Nobody needs to read a long styleguide\n",
" - Reminds the programmer of style rules when they are violated\n",
" - Contributers from otside the project can contribute easier\n",
" - Code simplifications are pointed out\n",
" - Reduces the number of variances for the same functionality"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Collection of Recommended linter\n",
"\n",
"- Black for an automatic and absolut whitespace formatting. (No configuration options)\n",
"- Ruff faster rust implementation of many commonly used linters.\n",
" - Reimplementation of the following tools:\n",
" - flake8 (Classic python linter, unused imports, pep8)\n",
" - isort Automatic import sorting (Vanilla python, third party, your package)\n",
" - bandit (Static code analysis for security problems)\n",
" - pylint (General static code analysis)\n",
" - many more\n",
" - Fixes many things that have `simple` fixes\n",
" - Relatively new\n",
" - Endorsed from project like pandas, FastAPI, Hugging Face, SciPy"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"- mypy\n",
" - Checks typing for python\n",
" - Commonly used linter for typing\n",
" - Often needs support of typing tools\n",
" - Sometimes additional typing information is needed from packages such as `pandas_stubs`."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"- pip-audit checks dependencies against vulnarability db\n",
"- pip-license checks if a dependency has an allowed license"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Testing with Pytest\n",
"\n",
"Even tough python comes with its own testing framework a much more lightweight and more commonly used testing framework is `pytest`\n",
"\n",
"``tests/basic_test.py``\n",
"\n",
"```python\n",
"from ... import add\n",
"\n",
"def test_addition():\n",
" assert add(4, 3) == 7, \"The addtion did not result into the correct result\"\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Parametizeed Test\n",
"\n",
"In addition, pytest contains the functionality to parameter its inputs\n",
"\n",
"``tests/parametriesed_test.py``\n",
"\n",
"```python\n",
"import pytest\n",
"\n",
"from ... import add\n",
"\n",
"@pytest.mark.parametize(\"inputvalues,output_value\", [[(1,2,3), 6], [(21, 21), 42]])\n",
"def test_addition(inputvalues: tuple[float, ...], output_value: [float]):\n",
" assert add(*inputvalues) == output_value\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Tests with setup and teardown\n",
"\n",
"Setting up an enviroment and cleaning it up afterwords is possible with `pytest`'s `fixture`\n",
"\n",
"``tests/setup_and_teardown_test.py`` \n",
"\n",
"```python\n",
"import pytest\n",
"\n",
"from sqlalchemy.orm import Session\n",
"\n",
"@pytest.fixture()\n",
"def create_test_sql() -> Generator[Session, None, None]:\n",
" # create_test_sql_table\n",
" # create sql connection\n",
" yield sql_session\n",
" # delete sql connection\n",
" # delete sql tables\n",
" \n",
"def test_sql_table(create_test_sql) -> None:\n",
" assert sql_engine.query(HelloWorldTable).get(\"hello\") == \"world\"\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Tests are run with the following command\n",
"\n",
"```bash\n",
"poetry run pytest tests/\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Code Coverage\n",
"\n",
"Code coverage reports count how many times a line was executed and therfore tested.\n",
"\n",
"They can eiter be integrated into an IDE for higliting of missing code or reviewed directly.\n",
"\n",
"Either over third party software or by the html version that can be found with the build artifacts."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## pre-commits\n",
"\n",
"Git is a filesystem based versioning application.\n",
"That includes parts of its code are accessible and ment to be manipulated.\n",
"At different times of the application a manipulate script can be executed.\n",
"Typicle moments are on:\n",
"- pull\n",
"- push / push received\n",
"- pre-commit / pre-merge / pre-rebase\n",
"\n",
"The `pre-commit` package hooks into the commit and implements a set of programms before committing\n",
"Files can be **edited** or **validated**"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"`pre-commit` execute fast tests on changed files to ensure quality of code.\n",
"\n",
"**Bohems Law**\n",
"\n",
"![Bohems Law](bohems-law.png)\n",
"\n",
"Since they are executed on commit on only the newly committed files a response is much faster.\n",
"The normally only include linting and format validation tools no testing.\n",
"Sometimes autofixer such as black, isort and ruff."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![Pre-commit.PNG](Pre-commit.PNG)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Configured pre-commit hooks:\n",
"\n",
"- format checker + pretty formatter (xml,json,ini,yaml,toml)\n",
"- secret checker => No passwords or private keys\n",
"- file naming convention checker for tests\n",
"- syntax checker\n",
"- ruff => Linter\n",
"- black => Whitespace formatter\n",
"- poetry checker\n",
"- mypy => typing checker\n",
"- md-toc => Adds a table oc contents to an *.md where `<!--TOC-->` is placed"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Pre commits are installed with the command\n",
"```bash\n",
"pre-commit install\n",
"```\n",
"The pre commits after that executed on each commit.\n",
"\n",
"If the pre-commits need to be skipped the -n option skips them on commit.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Documentation build with sphinx\n",
"\n",
"There is no single way to use to build a python documentation.\n",
"Sphinx is a commonly used libarary.\n",
"\n",
"- Builds a package documentation from code\n",
"- Native in rest\n",
"- Capable of importing *.md, *.ipynb\n",
"- Commonly used read the docs theme\n",
"- Allows links to third party documentations via inter-sphinx (pandas, numpy, etc.)\n",
"\n",
"Currently implemented to build a documentation on pull_requests and the main branch.\n",
"\n",
"Automatically deployed from the main branch."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## GitHub\n",
"\n",
"GitHub is a central hub for git repositories to be stored and manged.\n",
"\n",
"In addition, it hosts project management tools and devops tools for:\n",
"- testing\n",
"- linting\n",
"- analysing\n",
"- building\n",
"- deploying code\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Example GitHub action workflow\n",
"\n",
"Workflows are defined in `.github/workflows/some-workflow.yaml`\n",
"```yaml\n",
"name: Build\n",
"\n",
"on: # when to run the action\n",
" pull_request:\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"A single action of a workflow.\n",
"\n",
"```yaml\n",
"jobs:\n",
" build:\n",
" runs-on: ubuntu-latest # on what kind of runner to run an action\n",
" steps:\n",
" - uses: actions/setup-python@v4 # setup python\n",
" with:\n",
" python-version: 3.11\n",
" - uses: snok/install-poetry@v1 # setup poetry\n",
" with:\n",
" version: 1.4.2\n",
" virtualenvs-path: ~/local/share/virtualenvs\n",
" - uses: actions/checkout@v3\n",
" - run: |\n",
" poetry install --without develop,doc,lint,test\n",
" poetry build\n",
" - uses: actions/upload-artifact@v3\n",
" with:\n",
" name: builds\n",
" path: dist/\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Test and Build-pipeline with GitHub actions\n",
"On push and pull request:\n",
"- Lint + license check + dependency security audit\n",
" - Problem summaries in GitHub actions + Problem notification via mail\n",
"- Test with pytest + coverage reports + coverage comment on pull request\n",
"- Python Build\n",
"- Documentation Build\n",
"- Documentation deployment to GitHub pages (on push to main)\n",
"\n",
"On Tag:\n",
"- Push: Docker architecture and CD context still unclear"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Build artifacts\n",
"\n",
"- Dependencies / versions and licenses\n",
"- Security report\n",
"- Unit test reports and coverage report as `.coverage` / `coverage.xml` / `html`!\n",
"- Build wheel\n",
"- Build documentation\n",
"- probably. one or more container\n",
"- if needed documentation as pdf"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![Action Snapshot](Action.PNG)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![Action Summary](Action-Summary.PNG)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![Lint-error.PNG](Lint-error.PNG)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![Coverage.PNG](Coverage.PNG)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![Pull Request](Pull_request.PNG)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Dependabot\n",
"\n",
"Dependabot is a GitHub tool to refresh dependencies if newer ones come available or if the currently used ones develop security flaws.\n",
"Dependabot is currently not python compatible.\n",
"Dependabot is a tool for a passive maintenance of a project without the need for much human overside."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### GitHub Runner Configuration and what does not work\n",
"\n",
"Most GitHub actions for python reley on the `actions/python-setup` action.\n",
"This action is not available for linux arm.\n",
"Workarounds with a python docker container / an installation of python on the runner and other tools do not work well."
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0"
},
"rise": {
"scroll": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,21 @@
# Dev Ops
## Roadmap
My plan for this coursework is to explore the dev ops thema and how it applies to the AI theme and this project in specific.
There are the following things in the theme of dev ops I want to explore:
1. Python dependency management via poetry
2. Write a documentation around pre-commit hooks and how they can be used for this project with arguments for and against each of the hooks.
3. Add a GitHub Runner on my own hardware to the repository and build a pipline with GitHub actions.
- Add linter (black, flake8, pylint, mypy, bandit, pip-audit)
- Testing setup in the pipline via pytest
- Explore the ability of GitHub to summaries the linting and testing results.
- Add SonarQube to the project if the test and lint summaries in GitHub does not suffice.
- Build the artifacts. Something like python wheels, Docker container and deployment files.
- Startup to new build and see if it crashes in the first 60s if a framework is shown.
- Build the documentation via sphinx for this project via the pipline.
4. How to deploy the collection of Docker containers via docker-compose and/or kubernetes.
5. Evaluate the use of dependabot to upgrade the poetry dependency groups.
6. Steadily grow the build pipline as the application grows.

View File

@ -0,0 +1,48 @@
# Verflechtungsanalyse
## Entwurf des Inhaltsverzeichnis + Stichpunkte
1 Einleitung
1.1 Problemstellung
1.2 Zielsetzung und Aufbau der Arbeit
2 Graphentheorie
2.1 Begriffliche Definition
2.2 Sociometry
- sociometry: quantitatives Methode um soziale Beziehungen zu messen.
2.3 Sociogram/ Social Graph
- Ist ein graph der ein Soziales netzwerk darstellt
- Basiert auf der Graphentheorie
- Wurde offiziell Sociogram genannt
- von facebook in der F8 2007 vorgestellt
2.4 Social Network Analysis (SNA)
- Social Network Analysis (SNA): Untersuchen von Sozialen Strukturen anhand von Netzwerken und Graphtheorie.
3 Ein Social Graph für das Transparentsregister
3.5 Handlungsempfehlung
4 Zusammenfassung
4.1 Kritische Reflexion
4.2 Fazit
4.3 Ausblick
## Abstract
In der Seminararbeit zum Thema: "Verpflechtungsanalyse der Unternehmen und Personen im Transparenzregister" soll einerseits die Theorie für die Analyse von Verflechtungen vermittelt sowie anhand des Projektess aufgezeigt werden wie diese angewendet werden kann.
Als Fundament dient die Graphentheorie, welche Grundlegen für die Analyse von Netzstrukturen ist. Zunächst werden die wichtigsten Begriffe definiert und es wird eine Einführung ins Thema der Graphentheorie mit Beispielen und Erläuterung gegeben. Darauffolgend wird tiefer in das Thema eingetaucht und sich mit dem Bereich Sociogram/ Social Graph auseinandergesetzt. Ein Sociogram ist ein Model eines Netzwerks von sozialen Verbindungen die durch einen Graphen repräsentiert werden. Diese Idee wurde 2007 von Facebook als Social Graph in der F8 vorgestellt. Diese Art von Graph basiert auf der Graphentheorie. Die stärken dieses Graphen liegen in der Veranschaulichung der sozialen Verflechtungen. Daher wird der Social Graph für die Analyse der Verflechtungen innerhalb des Transparenzregisters genutzt.
Im Hauptteil der Seminararbeit wird aufgezeigt wie der Social Graph auf das Transparenzregister angewendet werden könnte. Es wird gezeigt welche Komponenten gebildet werden müssten und wie die Daten aufbereitet werden um einen Social graph bauen zu können. Des Weiteren wird auf die Formel und Algorithmen eingegangen die zur Erstellung des Graphen nötig sind. Dabei orientiert sich die Arbeit an Beispielen um die Theorie nachvollziebar zu vermitteln. Dieser Abschnitt wird mit einer Handlungsempfehlung für das Projekt abgeschlossen.
Abgeschlossen wird das Werk mit einer kritischen Reflexion, gefolgt von einem Fazit und einem Ausblick.

View File

@ -1,75 +1,71 @@
```mermaid
%%{init:
{
"theme": "neutral"
}
}%%
gantt
%%Timeline created 11-04-2023
%%use Mermaid.js for visualization
title Timeline PG Transparenzregister
dateFormat YYYY-MM-DD
section Organisation
Kennenlernen des Projektteams : done, a1, 2023-03-30, 1d
Erstellen des Organigramms : done, after a1 , 1d
GitHub : done, 2023-04-06, 7d
Zeitplanung SoSe : active , 2023-04-06, 7d
# Timeline
```{mermaid}
section Dokumentation
Meeting Notes: active, 2023-03-30, 10w
Seminarthemen: active, 2023-04-13, 8w
Lastenheft: active, 2023-04-06, 5w
Pflichtenheft: milestone, 2023-05-11
Reserve: crit, 2023-06-08, 1w
gantt
title Timeline PG Transparenzregister
dateFormat YYYY-MM-DD
section Organisation
Kennenlernen des Projektteams : done, a1, 2023-03-30, 1d
Erstellen des Organigramms : done, after a1 , 1d
GitHub : done, 2023-04-06, 7d
Zeitplanung SoSe : active , 2023-04-06, 7d
section Dokumentation
Meeting Notes: active, 2023-03-30, 10w
Seminarthemen: active, 2023-04-13, 8w
Lastenheft: active, 2023-04-06, 5w
Pflichtenheft: milestone, 2023-05-11
Reserve: crit, 2023-06-08, 1w
section Meeting
Weekly 1 : done, 2023-03-30, 0.5h
Statustermin 1 : done ,2023-03-30 , 1h
Weekly 2 : done, 2023-04-06, 2h
section Meeting
Weekly 1 : done, 2023-03-30, 0.5h
Statustermin 1 : done ,2023-03-30 , 1h
Weekly 2 : done, 2023-04-06, 2h
Statustermin 2 : active, 2023-04-13, 1h
Weekly 3 : active, 2023-04-13, 0.5h
Weekly 4 : active, 2023-04-20, 2h
Statustermin 2 : active, 2023-04-13, 1h
Weekly 3 : active, 2023-04-13, 0.5h
Weekly 4 : active, 2023-04-20, 2h
Weekly 5 : active, 2023-04-27, 0.5h
Statustermin 3 : active, 2023-04-27, 1h
Weekly 5 : active, 2023-04-27, 0.5h
Statustermin 3 : active, 2023-04-27, 1h
Weekly 6 : active, 2023-05-04, 2h
Weekly 6 : active, 2023-05-04, 2h
Weekly 7 : active, 2023-05-11, 0.5h
Statustermin 4 : active, 2023-05-11, 1h
Weekly 7 : active, 2023-05-11, 0.5h
Statustermin 4 : active, 2023-05-11, 1h
Weekly 8 : active, 2023-05-18, 2h
Weekly 9 : active, 2023-05-25, 0.9h
Statustermin 5 : active, 2023-05-25, 1h
Weekly 8 : active, 2023-05-18, 2h
Weekly 9 : active, 2023-05-25, 0.9h
Statustermin 5 : active, 2023-05-25, 1h
Weekly 10 : active, 2023-06-01, 2h
Weekly 11 : active, 2023-06-01, 0.9h
Statustermin 6 : active, 2023-06-08, 1h
Weekly 10 : active, 2023-06-01, 2h
Weekly 11 : active, 2023-06-01, 0.9h
Statustermin 6 : active, 2023-06-08, 1h
section Recherche
Unternehmensformen : active, 2023-04-06, 14d
Kennzahlen : active, 2023-04-10, 14d
Datenquellen : active, 2023-04-10, 14d
rechtliche Verwendbarkeit: active, 2023-04-06, 18d
Verwendete Metriken, Datenquellen, Rechtmäßigkeit: milestone, 2023-04-24
Reserve: crit, 2023-04-24, 3d
section Recherche
Unternehmensformen : active, 2023-04-06, 14d
Kennzahlen : active, 2023-04-10, 14d
Datenquellen : active, 2023-04-10, 14d
rechtliche Verwendbarkeit: active, 2023-04-06, 18d
Verwendete Metriken, Datenquellen, Rechtmäßigkeit: milestone, 2023-04-24
Reserve: crit, 2023-04-24, 3d
section Definition
fachl. Aufgabe : active, 2023-04-27, 1d
techn. Aufgabe : active, 2023-04-27, 1d
Funktionelle Anf. : active, 2023-04-27, 7d
Qualitative Anf. : active, 2023-04-27, 7d
Modell: active, 2023-05-04, 7d
Hierarchie: active, 2023-05-04, 7d
Definition der Anforderungen : milestone, 2023-05-11
Reserve: crit, 2023-05-11, 1w
section Definition
fachl. Aufgabe : active, 2023-04-27, 1d
techn. Aufgabe : active, 2023-04-27, 1d
Funktionelle Anf. : active, 2023-04-27, 7d
Qualitative Anf. : active, 2023-04-27, 7d
Modell: active, 2023-05-04, 7d
Hierarchie: active, 2023-05-04, 7d
Definition der Anforderungen : milestone, 2023-05-11
Reserve: crit, 2023-05-11, 1w
section Proof of concept
Project Proposal : active, 2023-05-18, 10d
Vorstellung Project Proposal: milestone, 2023-05-28
Implementierung des Proposals: active, 2023-05-25, 14d
Vorstellung Proof of Concept: milestone, 2023-06-08
Reserve: crit, 2023-06-08, 1w
section Proof of concept
Project Proposal : active, 2023-05-18, 10d
Vorstellung Project Proposal: milestone, 2023-05-28
Implementierung des Proposals: active, 2023-05-25, 14d
Vorstellung Proof of Concept: milestone, 2023-06-08
Reserve: crit, 2023-06-08, 1w
```