Data SciencePower BIPythonSoftware

Mehr Power in Power BI mit Python -Teil II

– Python Skripte als Abfrage in Power BI – JSON mit Python verarbeiten – Daten aus dem Web abfragen –

Warum Python als Abfrage nutzen?

Ein Bild sagt mehr als tausend Worte...

Und tatsächlich gibt es in Power BI durchaus Szenarien, in denen der Einsatz von Python als Abfrage sinnvoll sein kann.

 

 

Die Aufgabe — Fonds-Daten aus dem Netz

Screenshot der Quelle

Die Daten erscheinen dann in einem modalen Fenster.

Daten aus dem Web...

Daten aus dem Web — Power BI versagt… (I)

Url eingeben

Power BI findet auf der Internetseite alle möglichen (Layout-)Tabellen, aber nichts, was mit unseren Daten auch nur im Entferntesten zu tun hätte.

Web-Abfrage

Auch mit dem erweiterten Link wird es nichts.

Um Sprungsmarke erweiterter Link

Die vermutliche Ursache für diesen Misserfolg kann man mit den Chrome Browser Tools relativ gut ausfindig machen. Siehe Aufzeichnung unten.

Analyse mit Chrome Developer Tools

JSON Daten — Power BI versagt… (II)
…oder wie es umständlicher kaum sein könnte

Da wir nun schon den Quellcode der Seite untersuchen, können wir damit auch kurz fortfahren und unsere obige Theorie zum Versagen von Power BI verifizieren.

JSON Format der Daten analysieren

Hier sehen wir, dass die Seite unsere Steuerdaten im JSON Format heruntergeladen hat. Also, Theorie bestätigt und neue Herausforderung angenommen. Wenn die Daten im JSON-Format in unserem Browser verfügbar sind, verdammt, dann muss es doch möglich sein, diese Daten auch in unser Power BI zu bekommen.

Und ja, ein Lösungsansatz liegt direkt vor uns. Wir haben hier die URL.

URL zu unseren Daten

Damit haben wir mindestens zwei Möglichkeiten. Entweder wir laden die JSON-Datei einfach herunter um Sie anschließend in Power BI zu laden…

Download JSON File

…oder wir lassen Power BI die Daten für uns abrufen. Wie wir unten sehen, klappt auch dies!

Direktes Laden der Daten in Power BI

Das Ergebnis aaData:List entspricht genau dem, was wir auch in der Browser-Konsole gesehen haben: Einen Objekt-Schlüssel namens “aaData” und als Wert ein Array/ eine Liste…

Struktur der Daten

Wie ist also der JSON-File aufgebaut?

{
   "aaData":[
      [
         "0,0000",
         "0,4564",
         "17,3647",
         "0,45646",
         {
            "display":"29.05.2017",
            "raw":20171229
         }
      ]
      ...,
      ...,
      ...,
   ]
}
0,0000    0,4564       17,3647       0,45646     29.05.2017
...
...
...
Vergebliche Versuche I

Was äußerlich wenig bringt…

Vergebliche Versuche II

…uns aber einen Drilldown ermöglicht…

Vergebliche Versuche III

… aber auch dieser zeigt uns nur eine Liste von Listen an, die wir dann wieder in eine Tabelle konvertieren können…

Vergebliche Versuche IV

Mit “Werte extrahieren…” rennen wir hier leider direkt in…

Vergebliche Versuche V

…einen Fehler.

Vergebliche Versuche VI
Vergebliche Versuche VII

Das Ergebnis ist diesmal kein Fehler, aber alle Werte stehen nun untereinander und unser Datumsobjekt wird als Record geführt… Wir könnten kaum weiter von unser Zielstruktur entfernt sein…

Vergebliche Versuche VIII
Verzweifelte Versuche...
Verzweifelte Versuche....
Verzweifelte Versuche....
Verzweifelte Versuche....

Abfrage mit Python

Python Abfrage erstellen

Nun erscheint für uns ein Fenster, in dem wir unseren Python-Code eingeben können.

Python Code

Hier noch mal der Code als Text.

1  import pandas as pd
2
3  path = "D:\\downloads\\Performance.json"
4
5  df1 = pd.DataFrame([[*(value[0:4])] + [value[4]["display"]] for value in pd.read_json(path).aaData])
6
7  df1.columns = ["Zwischengewinn", "Aktiengewinn_EStG", "Aktiengewinn_KStG", "Immobiliengewinn", "Datum"]
Python Code

Nein, nicht traurig sein.

Hier klicken wir einfach auf “Table” und unsere Daten sind im Wesentlichen in exakt der Form vorhanden, die wir uns vorgestellt haben.

Python Code

Alles wunderbar zerlegt, mit Überschriften, einfach schön! Wenige Zeilen Code statt zigfachem Klicken! Python ist hier mit Sicherheit ein Produktivitäts-Booster.

Wir müssen an dieser Stelle nur noch zusehen, dass unsere Zahlen auch echte Zahlen sind und das Datum zu einem echten Datum gewandelt wird.

Power BI hat diesen Schritt in den meisten Fällen für uns schon erledigt, zumindest für die Zahlen, für das Datum braucht Power BI noch einen kleinen “Schups”.

Wichtig ist dabei letztlich nur, dass wir hier als “locale” bzw. “culture” den Wert “de-DE” erfassen, sonst gibt es ein Problem mit unserem deutschen Dezimal-Komma.

Locale einstellen

Hinweis: Abhängig vom Update-Stand eurer Power BI Desktop Version und den Sprach- bzw. Gebietsschema-Einstellungen, kann es sein dass ihr hier überhaupt keine Probleme bekommt und Power BI bereits (fast alles) erkannt hat.

Zeichencodierung falsch
1  import pandas as pd
2
3  path = "D:\\downloads\\Performance.json"
4
5  df1 = pd.DataFrame([[*(value[0:4])] + [value[4]["display"]] for value in
6  pd.read_json(path, encoding='utf8').aaData])
7
8  df1.columns = ["Zwischengewinn", "Aktiengewinn_EStG", "Aktiengewinn_KStG",
9  "Immobiliengewinn", "Datum"]

Hierzu übergeben wir unserer read_json-Funktion einen zusätzlichen Parameter: encoding='utf8'.

Der Zeichencode ist damit jetzt richtig, allerdings kommt Power BI trotzdem nicht mit unserem März zurecht.

Wenn Ausgangsdaten einfach nur doof sind...
Alles fertig!

Ich liebe es wenn ein Plan funktioniert!
-Filmzitat für Kenner

Abfrage mit Python direkt aus dem Web

Es ist natürlich auch möglich, die Daten mit Python direkt aus dem Netz herunter zu laden. Bisher hatte ich ja unterstellt, die JSON-Datei sei schon heruntergeladen worden.

Möglich ist unser Vorhaben auf mehreren Wegen, unter anderem mit dem urllib-Modul(en). Ich habe mich jedoch für die die Requests-Bibliothek entschieden, die wir an dieser Stelle jedoch noch installieren müssen.

Bibliothek installieren

Unseren bisherigen Code ersetzen wir wie folgt.

Daten aus dem Web

Hier noch mal als Textversion.

 1  import pandas as pd
 2  import requests
 3  
 4  r = requests.get(
 5      ("https://www.ishares.com/de/privatanleger/"
 6       "de/produkte/258701/ishares-euro-stoxx-50-exfinancials-ucits-etf/"
 7       "1478358465945.ajax?tab=tax-figures&fileType=json")
 8  )
 9   r.encoding = 'utf-8-sig'
10  
11  df1 = pd.DataFrame([[*(value[0:4])] + [value[4]["display"]] for x in
12  r.json().aaData])

Mehrere Fonds laden und weniger hacky

https://www.ishares.com/de/privatanleger/de/produkte/
251861/ishares-msci-europe-ucits-etf-acc-fund/
Liste = [
     ("Fondsname 1", "/xxxxx/fonds-bezeichnung"),
     ("Fondsname 2", "/xxxxx/fonds-bezeichnung"),
     ...
] 
import requests
import pandas as pd

url_start = "https://www.ishares.com/de/privatanleger/de/produkte/"
url_end = "/1478358465945.ajax?tab=tax-figures&fileType=json"
funds = [
    ("iShares EURO STOXX 50 ex-Financials UCITS ETF", "258701/ishares-euro-stoxx-50-exfinancials-ucits-etf"),
    ("iShares Core DAX® UCITS ETF (DE)", "251464/ishares-dax-ucits-etf-de-fund"),
    ("iShares Core MSCI Europe UCITS ETF EUR (Acc)", "251861/ishares-msci-europe-ucits-etf-acc-fund")
]


def fullUrl(fondsSpecificURLPart):
    return url_start + fondsSpecificURLPart + url_end


dataframe = pd.DataFrame(columns=["Zwischengewinn", "Aktiengewinn_EStG",
                                  "Aktiengewinn_KStG", "Immobiliengewinn", "Datum", "Fondsname"]
                         )

for fund in funds:
    fondsName = fund[0]
    response = requests.get(fullUrl(fund[1]))
    response.encoding = 'utf-8-sig'
    dataframe_tmp = pd.DataFrame([[*(x[0:4])] + [x[4]["display"], fondsName] for x in response.json()["aaData"]])
    dataframe_tmp.columns = ["Zwischengewinn", "Aktiengewinn_EStG",
                             "Aktiengewinn_KStG", "Immobiliengewinn", "Datum", "Fondsname"]
    dataframe = dataframe.append(dataframe_tmp)
Daten aus dem Web

Perfekt! Über 3.500 Zeilen mit einem wenige Zeilen langen Skript aus dem Web geladen.

Nachbetrachtungen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.