Author Archive

Adressen parsen mit Python und libpostal/pypostal

Beim letzten Treffen der PyCologne habe ich meinen Ansatz vorgestellt, um „Straße Hausnummer“ Kombinationen aus verschiedenen Ländern zu parsen. Jemand in der Gruppe gab mir dann den Hinweis auf libpostal und seine Python-Bindings.

Unter Windows habe ich es nicht zum Laufen bekommen, die Installationsroutine setzt noch diverse Compiler voraus. Unter Linux klappt die Installation, wenn man sich genau an die Anleitung unter https://github.com/openvenues/pypostal hält.

Dann kann man mittels parse_address() die Adressdaten verarbeiten.

(base) uwe@Micro:~$ python
Python 3.7.4 (default, Aug 13 2019, 20:35:49)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from postal.parser import parse_address
>>> parse_address("Meisenweg 1")
[('meisenweg', 'road'), ('1', 'house_number')]
>>> parse_address("10 Downing Street")
[('10', 'house_number'), ('downing street', 'road')]
>>> parse_address("10, Rue de Pommes Frites")
[('10', 'house_number'), ('rue de pommes frites', 'road')]
>>> parse_address("Am Geldspeicher 1, 12345 Entenhausen")
[('am geldspeicher', 'road'), ('1', 'house_number'), ('12345', 'postcode'), ('entenhausen', 'city')]
>>>

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Vortragsfolien zum Thema „TDD mit Python“

Hier die Folien einer Präsentation, die ich auf den Python-Stammtischen in Düsseldorf und Köln gehalten habe.

PyDDF-TDD-UweZiegenhagen.pdf

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Fake-Adressen in Python erstellen

Für eine Übungsaufgabe meiner Skriptsprachen-Vorlesung an der FOM in Köln benötigte ich eine große Menge an „Straße Hausnummer“ Kombinationen. Mit faker gibt es ein Python-Modul, das nicht nur diese Adressen, sondern auch Namen, E-Mail-Adressen, ISBNs, etc. für diverse Locales schnell erzeugen kann.

Den folgenden Code habe ich benutzt:

from faker import Faker
 
locales = ['de_DE', 'cs_CS', 'nl_NL', 'pl_PL', 'fr_FR', 'dk_DK', 'en_US']
 
with open('musteradressen.txt','wt', encoding='utf-8') as file:
    for i in locales:
        fake = Faker(i)
 
        for j in range(100):
            t = fake.address()
            print(t)
            if '\n' in t:
                t = t[:t.index('\n'):]
            file.write(t + '\n')

Da ich nur die Straßennamen mit Hausnummern benötigte, habe ich jeweils die PLZ und Ortsinformation zusammen mit dem Zeilenumbruch gelöscht.

Händisch wurden dann US-Schiffsangaben und Unit/PO-BOX Angaben gelöscht.

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Benannte Referenzen in LaTeX

Neben \ref{} und \pageref{} gibt es mit \nameref noch einen weiteren Befehl zur Referenzierung von Labels. \nameref{} gibt dabei den Titel des referenzierten Abschnitts aus. Daraus kann man dann auch einen \niceref{} Befehl bauen, der sowohl den Titel als auch die Seitenzahl in Klammern referenziert.

\documentclass[12pt,ngerman]{scrartcl}
 
\usepackage{babel}
\usepackage[T1]{fontenc}
\usepackage{csquotes}
\usepackage{hyperref}
\usepackage{fdsymbol}
 
\newcommand{\niceref}[1]{\enquote{\nameref{sec:abschnitt}} (\(\triangleright\)~\pageref{sec:abschnitt})}
 
\begin{document}
 
Siehe Abschnitt \ref{sec:abschnitt} mit dem Namen \nameref{sec:abschnitt} auf Seite \pageref{sec:abschnitt}.\vspace*{1cm}
 
Siehe Abschnitt  \niceref{sec:abschnitt}.
 
\clearpage
 
\section{Ein Abschnitt im Dokument}\label{sec:abschnitt}
 
\end{document}

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Und() und Oder() in Excel-Formeln nutzen

Hier ein anschauliches Beispiel für die Nutzung der Und() und Oder() Formel in Excel.

Gesucht werden die Zeilen, in denen Spalte A gleiche Werte aufweist, in Spalte B jedoch nicht.

Die Lösung dafür liegt in einer verschachtelten Und()/Oder() Funktion, schauen wir uns das mal für die Zeile 6 an:

Ich suche die Zeilen, in denen der Wert von Spalte A (also A6) dem Wert der vorigen Zeile (also A5) entspricht UND gleichzeitig der Wert aus Spalte B nicht dem Wert aus der vorigen Zelle entspricht.

Dies resultiert in der Formel: UND(A6=A5;B6<>B5)

Ich muss jedoch nicht nur die vorherige Zeile prüfen, sondern auch die folgende. Analog Prüfung auf die vorherige Zeile ergibt sich: UND(A6=A7;B6<>B7)

Da ich die Zeilen suche, in der die eine oder die andere Bedingung gilt, verpacke ich die beiden Formeln in eine Oder() Funktion: =ODER(UND(A6=A5;B6<>B5);UND(A6=A7;B6<>B7)). Das Oder() ist dabei nicht exklusiv, es können auch beide Teile WAHR ergeben, damit die Oder() Funktion ein WAHR zurückgibt. (Für unseren Zweck ist das egal, bei drei in Spalte A gleichen/in Spalte B ungleichen Zeilen könnte das einen Unterschied machen)

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Meiner TUGboat-Artikel zur TUG 2019 in Palo Alto

Nachdem ich meine Präsentationen zur TUG 2019 bereits hochgeladen habe (LINK) folgen nun die Artikel, die in der TUGboat erscheinen werden.

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Aufgaben zum Bruchrechnen erstellen mit LaTeX und Python

Hier ein kurzes Beispiel, wie man mit Python eine TeX-Datei mit vielen Brüchen erzeugen kann. Nützlich, wenn Kinder Brüche kürzen oder erweitern sollen. In der nächsten Zeit werde ich sicher noch entsprechende Anpassungen für das Rechnen mit Brüchen hinzufügen.

EDIT: Erweitert um das Löschen der Hilfsdateien.

import os
import random
 
 
head = """
\\documentclass[14pt, twocolumn]{scrartcl}
\\usepackage[utf8]{inputenc}
\\usepackage[T1]{fontenc}
\\pagestyle{empty}
 
\\begin{document}
 
\\begin{itemize}"""
 
foot = """
\\end{itemize}
\\end{document}
"""
 
def create_bruch():
    zahlen = list(range(1,13))
    zaehler = random.choice(zahlen)
    zahlen.remove(zaehler)
    nenner = random.choice(zahlen)
    return '\\item \\( \\frac{'+ str(zaehler) + '}{' + str(nenner) + '} \\)\\vspace{1em}'
 
 
with open("Brueche.tex", "w") as document:
    document.write(head);
    for i in range(32):
        document.write(create_bruch());
    document.write(foot);
    document.close();
 
os.system("pdflatex Brueche.tex")
os.unlink("Brueche.log")
os.unlink("Brueche.aux")
os.unlink("Brueche.tex")

Brueche

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Slides for my TUG 2019 presentations in Palo Alto

This year I was able to visit the TUG 2019 meeting in Palo Alto, California. I gave two talks, one on LaTeX & Python, the other one on the creation of exams using the exam class. Find below the slides, all sources are included in the PDF and accessible at least via Adobe Reader.

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Kredit-Tilgungspläne mit Python und numpy/pandas erstellen

Als der Kauf unserer Wohnung anstand, wollte ich die entsprechende Angebote der Banken nachrechnen und habe mir ein Python-Skript geschrieben, das die entsprechenden Berechnungen vornimmt. Berücksichtigt werden dabei auch Sondertilgungen im Dezember eines Jahres sowie eine Wartezeit von n Jahren ohne Sondertilgung.

Hier jetzt das Skript:

# -*- coding: utf-8 -*-
 
import pandas as pd
import numpy as np
 
 
def berechne_jaehrliche_Annuitaet(kreditsumme, nominalzins_prozent, tilgungssatz_prozent):
    """ Berechnet die _jährliche_ Annuität.
        Jährliche_Rate = (nominalzins + tilgungssatz) * Kreditsumme
        Quelle: https://de.wikipedia.org/wiki/Annuit%C3%A4tendarlehen
    """ 
 
    zinssatz = nominalzins_prozent / 100
    tilgung = tilgungssatz_prozent / 100
    return round(kreditsumme * (zinssatz + tilgung), 2)
 
 
def berechne_monatliche_Annuitaet(kreditsumme, nominalzins_prozent, tilgungssatz_prozent):
    """ Berechnet die _monatliche_ Annuität.
        Jährliche_Rate = (nominalzins + tilgungssatz) * Kreditsumme
        Monatliche_Rate = Jährliche_Rate / 12
    """ 
 
    zinssatz = nominalzins_prozent / 100
    tilgung = tilgungssatz_prozent / 100
    return round(kreditsumme * (zinssatz + tilgung) / 12, 2)
 
def tilgungsplan_df(kreditsumme, nominalzins_prozent, tilgungssatz_prozent, sondert, wartezeit, monate):
    """ 
        Gibt DataFrame der monatlichen Tilgungen zurück
 
        "monate" für wieviele Monate wird der Tilgungsplan erstellt
        "sondert" Betrag der jährlichen Sondertilgung
        "wartezeit" Anzahl der Jahre ohne Sondertilgung
    """
 
    df = pd.DataFrame()
    restschuld = kreditsumme # Am Anfang entspricht die Restschuld der Kreditsumme
    zinssatz = nominalzins_prozent / 100
    tilgung = tilgungssatz_prozent / 100
 
    annuitaet = berechne_monatliche_Annuitaet(kreditsumme, nominalzins_prozent, tilgungssatz_prozent)
    zinsen = 0
 
    for j in range(1,monate+1):
        # Split der Annuität in ihre Komponenten Zinslast und Tilgung
        zinsen = restschuld * zinssatz / 12 
        # Wenn Restschuld kleiner Annuität, dann wird die komplette 
        # Restschuld getilgt
        tilgung = restschuld if restschuld < annuitaet else annuitaet - zinsen    
 
        anfangsschuld = restschuld
        jahr = ((j-1) // 12) + 1 # in welchem Monat befinden wir uns
 
        # Sondertilgungen im Dezember eines Jahres, wenn wir 
        # nicht in der Wartezeit sind
        if j % 12 == 0 and anfangsschuld > 0 and jahr > wartezeit:
            sondertilgung = sondert
        else:
            sondertilgung = 0
 
        # Restschuld_neu = Restschuld_alt minus Tilgung minus Sondertilgung
        restschuld = restschuld - tilgung - sondertilgung
 
        # Dataframe befüllen
        df = df.append({'Monat': j, 'Jahr': jahr,'Anfangsschuld': anfangsschuld, 
        'Zinsen':zinsen, 'Tilgung': tilgung, 'Sondertilgung': sondertilgung,
        'Restschuld': restschuld}, ignore_index=True)    
 
    # Indikatorspalte, "1" wenn der Kredit noch nicht abbezahlt ist, sonst "0"
    df['Indikator'] = np.where(df['Anfangsschuld']>0, 1, 0)
    # Umsortieren der Spalten
    df = df[['Monat', 'Jahr', 'Anfangsschuld', 'Zinsen', 'Tilgung', 'Sondertilgung', 'Restschuld', 'Indikator']]
 
    # Runden auf 2 Nachkommastellen
    for i in ['Anfangsschuld', 'Zinsen', 'Tilgung', 'Restschuld']:
        df[i] = df[i].apply(lambda x: round(x, 2))    
 
    # Monat als Index nutzen
    df.set_index('Monat', inplace=True)
    return df
 
print(berechne_jaehrliche_Annuitaet(200000, 2.0, 3.0), 'jährliche Annuität')
print(berechne_monatliche_Annuitaet(200000, 2.0, 3.0), 'monatliche Annuität')
 
tilgungsplan = tilgungsplan_df(200000, 2.0, 3.0, 5000, 0, 200)
#Wie lange läuft der Kredit
print('Gesamtlaufzeit:', round(tilgungsplan['Indikator'].sum(),1), 'Monate')
 
tilgungsplan.to_excel('tilgungsplan_gesamt.xlsx')

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Excel-Dateien schreiben mit Openpyxl: (Bedingte) Formatierung

This entry is part 6 of 6 in the series Openpyxl

Mit Openpyxl lassen sich auch Zellformatierungen und bedingte Formatierungen setzen. Das folgende Beispiel formatiert die ersten beiden Spalten grün, wenn der Zellwert „1“ beträgt und rot für alle anderen Inhalte. Die dritte Spalte wird mit blauem Hintergrund formatiert, hier jedoch ohne Bedingung.

import pandas as pd
import numpy as np
from openpyxl import Workbook
from openpyxl.utils.cell import get_column_letter
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.worksheet.table import Table, TableStyleInfo
 
from openpyxl.styles import Color, PatternFill, Font, Border
from openpyxl.formatting.rule import ColorScaleRule, CellIsRule, FormulaRule, Rule
 
 
dataframe = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])
rows = dataframe_to_rows(dataframe, index=False, header=True)
 
wb = Workbook()
ws = wb.active
 
for r_idx, row in enumerate(rows, 1):
    for c_idx, value in enumerate(row, 1):
        ws.cell(row=r_idx, column=c_idx, value=value)
 
# Set column widths based on title width or fixed number
widths = {}
for column in ws.columns:
    if column[0].value is None: # no column header => Fixed with
        widths[column[0].column] = 10.5
    else: # if column header is present => min width resp. maximum
        widths[column[0].column] = max(len(str(column[0].value)) * 1.45, 10.5)
 
ws.column_dimensions[get_column_letter(column[0].column)].width = widths[column[0].column]
 
# Insert formatted table from A1 to max column/max row
tab = Table(displayName="MeineTabelle", ref='A1:' + get_column_letter(ws.max_column) + str(ws.max_row))
style = TableStyleInfo(name="TableStyleLight9", showFirstColumn=False,
                       showLastColumn=False, showRowStripes=True, showColumnStripes=True)
tab.tableStyleInfo = style
ws.add_table(tab)
 
# conditional formatting
redFill = PatternFill(start_color='EE1111',end_color='EE1111',fill_type='solid')
greenFill = PatternFill(start_color='EE1111',end_color='11EE11',fill_type='solid')
ws.conditional_formatting.add('A2:B'+str(ws.max_row),CellIsRule(operator='equal', formula=[1], stopIfTrue=True, fill=greenFill))
ws.conditional_formatting.add('A2:B'+str(ws.max_row),CellIsRule(operator='notEqual', formula=[1], stopIfTrue=True, fill=redFill))
 
lightbluefill = PatternFill(start_color='CCCCFF',end_color='CCCCFF',fill_type='solid')
 
for rowNum in range(2, ws.max_row + 1):
    ws.cell(row=rowNum, column=3).fill = lightbluefill
 
wb.save('07.xlsx')
wb.close()

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website