Archive for the ‘Allgemein’ Category.

Lineare Gleichungen lösen mit numpy

Hier ein kurzes Beispiel aus der numpy-Dokumentation, wie man mit Hilfe von numpy lineare Gleichungssysteme lösen kann:

Zu lösen sind folgende Gleichungen:

  • 3 * x0 + 1 * x1 = 9
  • 1 * x0 + 2 * x1 = 8

Die Koeffizienten kommen in die entsprechenden numpy-Arrays, dann ruft man linalg.solve auf:

import numpy as np
 
a = np.array([[3,1], [1,2]])
b = np.array([9,8])
x = np.linalg.solve(a, b)
print(x) # gibt [ 2.  3.]

pff

Den Plot habe ich mit LaTeX erstellt, siehe http://uweziegenhagen.de/?p=3516.

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

Plots mit pgfplots

Hier ein kleines Beispiel für pgfplots, das ich aus diversen TSX Beiträgen für einen Python Artikel zusammengebaut habe:

\documentclass[12pt,english]{standalone}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\pagestyle{empty}
 
\begin{document}
\begin{tikzpicture}
\begin{axis}[
    domain=0:9,
    axis lines = center,
    xlabel = {$x$},
    ylabel = {$y = f(x)$},
    height=8cm, width=11cm, grid=major,grid style={dashed, gray!30},
    xmin=-1, xmax=10, ymin=-1, ymax=7,xtick={1,2,...,10},ytick={1,2,...,6}]
 
\addplot[draw=red,domain=0:8]{-0.5*x+4};
\addplot[draw=blue,domain=1:3]{-3*x+9};
\end{axis}
\end{tikzpicture}
\end{document}

pff

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

Luftfeuchtigkeits-Ampel mit dem Arduino

Vor ein paar Tagen habe ich ein kleines Projekt mit dem Arduino abgeschlossen. Eine LED sollte — ähnlich wie eine Ampel — über die aktuelle Luftfeuchtigkeit Auskunft geben. Dazu habe ich einen DHT 22 Sensor und eine 5mm Full-RGB LED an einen USB-Boarduino angeschlossen.

Hier der Code, eine Fritzing-Zeichnung werde ich noch nachliefern.

//
// Basis: dht22_test.ino by Rob Tillaart
#include <dht.h>
dht DHT;
#define DHT22_PIN 2
 
void setup()
{
  Serial.begin(9600);
  pinMode(5, OUTPUT); // Blau
  pinMode(4, OUTPUT); // ROT
  pinMode(3, OUTPUT); // GRÜN
 
  digitalWrite(4, HIGH);
  delay(1000);
  digitalWrite(3, HIGH);
  delay(1000);
  digitalWrite(5, HIGH);
  delay(1000);
 
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
}
 
void loop()
{
  int chk = DHT.read22(DHT22_PIN);
  float humidity = DHT.humidity;
  float temp = DHT.temperature;
 
  Serial.print("Humidity (%): ");
  Serial.println(humidity);
  Serial.print("Temperature (C): ");
  Serial.println(temp);
 
  if (humidity > 60) // ROT, wenn die L. zu hoch ist.
  {
    digitalWrite(4, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(5, LOW);
  }
 
  if (humidity < 40) // BLAU, wenn L. zu niedrig ist.
  {
    digitalWrite(5, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
  }
 
  if ((humidity >= 40) && (humidity <= 60) ) // Zwischen 40 und 60 zeige GRÜN
  {
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
  }
  delay(5000);
}

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

Daten aggregieren mit pandas

I recently came across a „challenge“ where I needed to combine various rows. Each row was identified by Key1 and Key2 and had two interesting columns, Foo and Bar. For each Key1 there may be a few Key2, for each Key2 n Foo/Bar entries. While all Foos are distinct per Key1 and Key2 the Bar column may appear j times.

The goal was to get a list of unique Bar items for each Key1/Key2 combination.

Key1 Key2 Foo Bar
0 C1 T1 a1 rc-1
1 C1 T1 a2 rc-1
2 C1 T1 a3 rc-1
3 C1 T1 a4 rc-1
4 C2 T2 b1 rc-1
5 C2 T2 b2 rc-2
6 C3 T3 c1 rc-3
7 C4 T4 d1 rc-4
8 C4 T4 d2 rc-5
9 C4 T4 d3 rc-4

The following Python code nicely did the job, thanks to http://stackoverflow.com/questions/17841149/pandas-groupby-how-to-get-a-union-of-strings

# -*- coding: utf-8 -*-
import pandas as pd
 
def unique(liste):
    """ takes a list of elements, separated by comma and returns sorted string of unique items separated by comma """
    a = liste.split(',')
    b = sorted(set(a))
    return ','.join(b)
 
df = pd.read_excel('groupb_Beispiel.xlsx')
print(df)
 
grouped = df.groupby(['Key1','Key2'],as_index=False)['Bar'].agg(lambda col: ','.join(col))
grouped = pd.DataFrame(grouped)
 
grouped['Unique'] = grouped['Bar'].apply(unique)
 
print(grouped)
 
grouped.to_excel('result.xlsx')
Key1 Key2 Bar Unique
0 C1 T1 rc-1,rc-1,rc-1,rc-1 rc-1
1 C2 T2 rc-1,rc-2 rc-1,rc-2
2 C3 T3 rc-3 rc-3
3 C4 T4 rc-4,rc-5,rc-4 rc-4,rc-5

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

Zeilen kombinieren mit pandas

Vor einiger Zeit hatte ich eine Excel-Datei zu bearbeiten, in der in einer Spalte die Spaltennamen, in einer anderen die korrespondieren Werte standen. Immer drei Zeilen bildeten den eigentlichen Datensatz. Mit wenigen Zeilen Pandas und cleverer Adressierung der Ergebnis-Zelle.

Spaltenname Wert
ColA Andi
ColB Berni
ColC Cesar
ColA Dorian
ColB Ernest
ColC Frank

 

import pandas as pd
 
# Lade die Daten
daten = pd.read_excel('combine.xlsx')
# Erstelle leeren Dataframe mit den Spaltennamen aus den Excelzeilen 
verarbeitet = pd.DataFrame(columns=['ColA','ColB','ColC'])
 
# Iteriere über die Daten
for i, row in daten.iterrows():
    # ganzzahliges Teilen, um die Zeile zu bestimmen
    # in die die Zelle gehört, Spalte ergibt sich aus dem Wert in 'Spalte'
    verarbeitet.loc[i // 3,row['Spalte']] = row['Wert']
 
print(verarbeitet)
ColA ColB ColC
0 Andi Berni Cesar
1 Dorian Ernest Frank

Nachtrag: Stephan vom Kölner Data Science Meetup hat mir noch einen alternativen Weg gezeigt:

import pandas as pd
 
data = {'A': ["cola", "colb", "colc", "cola", "colb", "colc"], "B": [1, 2, 3, 4, 5, 6]}
data = pd.DataFrame(data)
gb = data.groupby('A')
res = pd.DataFrame()
for key in gb.groups:
    res[key] = gb.get_group(key)['B'].values.flatten()
 
print(res)

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

Spendenbescheinigungen erstellen mit LaTeX und pandas

Nach Buchungen auswerten mit Python Pandas hier der zweite Artikel zum Thema pandas.

Ausgangspunkt bilden die Formulare der Finanzdirektion, die ich in LaTeX umgesetzt habe; ihr findet sie unter https://github.com/UweZiegenhagen/spendenquittungen-mit-latex.

Wenn man dieses Formular mit entsprechenden Jinja2 Variablen anreichert (dazu später mehr), erhält man Sammelbestaetigung_Geldzuwendung (PDF) (TeX Code)

Die Aufgabe, die sich jetzt für das automatische Befüllen mittels pandas stellt, ist die folgende:

  1. Lies die Stammdaten ein und bereite sie auf
  2. Lies die Buchungen (aus Quicken 2015) ein und bereite sie auf
  3. Befüll das entsprechende LaTeX-Template
  4. Erzeuge die fertige PDF Datei

Hier der Quellcode nebst Erläuterung:

  • jinja2 nutzen wir als Template-Engine, os für die pdflatex-Aufrufe, codecs für ein wenig UTF8-Gewusel
  • cleanPLZ und prepareAddress sind einfache Hilfsfunktionen. Die erste reinigt die PLZ (pandas nimmt an, das hier Floats drinstehen), die zweite erzeugt den Adressstring für die Ausgabe
  • kardinal erzeugt das Zahlwort, siehe dazu den verlinkten Beitrag vom Finanzamt.
  • Richtig los geht es ab „##################### Prepare Stammdaten #####################“:
    • Ich lade die Stammdaten in einen Dataframe und ersetzte fehlende Werte durch “
    • Die PLZ wird bereinigt (geht sicher auch einfacher), ehemalige Mitglieder (mit Status ‚E‘) werden entfernt
    • Die Buchungen werden geladen, fehlende Werte durch 0 bzw. “ ersetzt.
    • Relevant sind nur Buchungstypen wie Mitgliedsbeitrag und Aufnahmegebühr, alles andere wird entfernt.
    • Die Jinja2 Komponente wird konfiguriert
    • Für jeden Stammdatensatz werden die Stammdaten aufbereitet und die Buchungen eingesammelt.
    • Ein wenig Python/pandas Magie bereitet die daten auf und schreibt alles in das Template
    • Dieses Template wird dann in eine TeX Datei geschrieben und nach PDF übersetzt.

Hier der Link zur Zip-Datei mit allen benötigten Dateien: AlleDateien

Update vom 18.01.2021: Der Python-Code in der Datei hat nicht mehr funktioniert. In der folgenden Datei daher das Code-Update.

prepareSpenden-04

import pandas as pd # pandas selbst
 
import jinja2
import os
import codecs
 
def cleanPLZ(stringToClean):
    return stringToClean.replace('.0','')
 
# Eine Funktion, die die Adresse vorbereitet
# keine überflüssigen Leerzeichen, wenn Feld nicht gefüllt ist
def prepareAddress(id, vorname, name, strasse, plz, ort):
    address = '' # + str(id) + ': '
    if len(vorname)==0:
        address = address + name
    else:
        address = address + vorname + ' ' + name
    if len(strasse)>0:
        address = address + ", " + strasse    
    if len(plz)>0:
        address = address + ", " + plz + ' ' + ort
    return address
 
# Zerlege die Gesamtsumme in einzelne Bestandteile, um Zahlwort auszugeben
# Siehe http://www.steuer-schutzbrief.de/fileadmin/downloads/BMF-Schreiben/BMF-Schreiben-Zuwendungsbestaetigung-2012-08-30.pdf
def kardinal(summenstring,separator,indicator):
	zahlen = {"1" : "Eins", "2":"Zwei", "3":"Drei", "4":"Vier","5":"Fünf","6":"Sechs","7":"Sieben","8":"Acht","9":"Neun","0":"Null"}
	zahlwort = ''
	zahl = summenstring.split(',')[0]
	for i in zahl:
		zahlwort = zahlwort + zahlen[i]+ separator
	return indicator + separator + zahlwort + indicator
 
# Diverse Konfigurationsvariablen
# http://chrisalbon.com/python/pandas_list_unique_values_in_column.html
# Set ipython's max row display
pd.set_option('display.max_row', 10000)
# Set iPython's max column width to 50
pd.set_option('display.max_columns', 50)
# A set number format to 2 digits
pd.set_option('display.float_format', lambda x: '%.2f' % x)
# http://stackoverflow.com/questions/20625582/how-to-deal-with-this-pandas-warning
# komische Fehlermeldung beim Drop von Spalten loswerden
pd.options.mode.chained_assignment = None  # default='warn'
 
##################### Prepare Stammdaten ##################### 
# lade Daten
stammdaten = pd.read_excel('Stammdaten.xlsx', 'Tabelle1')
 
# Remove NaN values by " for strings
stammdaten['Vorname'].fillna(value='',inplace=True)
stammdaten['Name'].fillna(value='',inplace=True)
stammdaten['Adresszusatz'].fillna(value='',inplace=True)
stammdaten['Strasse'].fillna(value='',inplace=True)
stammdaten['PLZ'].fillna(value='',inplace=True)
stammdaten['Ort'].fillna(value='',inplace=True)
stammdaten['eMail'].fillna(value='',inplace=True)
stammdaten['Mitgliedsart'].fillna(value='',inplace=True)
 
# convert PLZ to string
# apply str function first, then run cleanPLZ on the string
stammdaten['PLZ']= stammdaten.PLZ.apply(str)
stammdaten['PLZ']= stammdaten.PLZ.apply(cleanPLZ)
 
# entferne ehemalige Mitglieder
stammdaten  = stammdaten[stammdaten.Mitgliedsart != 'E']
 
################################ Prepare Buchungen
# lade die Buchungen
buchungen = pd.read_excel('Buchungen.xlsx', 'Tabelle1')
buchungen[['Klasse']] = buchungen[['Klasse']].astype(str)
buchungen[['Betrag']] = buchungen[['Betrag']].astype(float)
 
# Change format of 'Buchungstag' to datetime
buchungen['Buchungstag'] = pd.to_datetime(buchungen['Buchungstag'],dayfirst=True)
 
# Remove NaN values by " for strings or 0 for numbers 
buchungen['Vorgang'].fillna(value=0,inplace=True)
buchungen['Empfänger'].fillna(value='',inplace=True)
buchungen['Verwendungszweck'].fillna(value='',inplace=True)
buchungen['Kategorie'].fillna(value='',inplace=True)
buchungen['Klasse'].fillna(value='',inplace=True)
buchungen['Relevant']=True
buchungen.Kategorie.str.match('^Aufnahmegebühr|Zweckspende|Mitgliedsbeitrag|Spende$')
 
# entferne irrelevante Buchungen
buchungen = buchungen[buchungen.Relevant != False]
 
# http://stackoverflow.com/questions/20937538/how-to-display-pandas-dataframe-using-a-format-string-for-columns
#pd.options.display.float_format = '{:,.2f} EUR'.format
 
class CommaFloatFormatter:
    def __mod__(self, x):
        return str(x).replace('.',',')
 
latex_jinja_env = jinja2.Environment(
    block_start_string = '\BLOCK{',
    block_end_string = '}',
    variable_start_string = '\VAR{',
    variable_end_string = '}',
    comment_start_string = '\#{',
    comment_end_string = '}',
    line_statement_prefix = '%-',
    line_comment_prefix = '%#',
    trim_blocks = True,
    autoescape = False,
    loader = jinja2.FileSystemLoader(os.path.abspath('.'))
)
 
# Laden des Templates aus einer Datei
template = latex_jinja_env.get_template('Sammelbestaetigung_Geldzuwendung.tex')
 
for index, row in stammdaten.iterrows():
    print("ID:",row["ID"])
    address = prepareAddress(row["ID"],row['Vorname'],row['Name'],row['Strasse'],row['PLZ'],row['Ort'])
    print(address)
    beitraege = buchungen[buchungen.Klasse.str.contains('^' +  str(row["ID"]) + '$')]
    beitraege.drop('Klasse',axis=1,inplace=True)
    beitraege.drop('Verwendungszweck',axis=1,inplace=True)
    beitraege.drop('Relevant',axis=1,inplace=True)
    beitraege.drop('Empfänger',axis=1,inplace=True)
    beitraege.drop('Konto',axis=1,inplace=True)
    beitraege.drop('Vorgang',axis=1,inplace=True)
    gesamtsumme = beitraege.sum()[0]
 
    beitraege['Buchungstag'] = beitraege['Buchungstag'].apply(lambda x: x.strftime('%d-%m-%Y'))
    texbuchungen = beitraege.applymap(lambda x: str(x).replace('.',',0')).to_latex(index=False)    
    texbuchungen = beitraege.to_latex(index=False)    
    summe = str(gesamtsumme).replace('.',',0') + ' EUR'
    # kardinal(summe,'-','xxx')
    dokument = template.render(Spender=address, ID=row['ID'],Summe=summe,kardinal=kardinal(summe,'-','xxx'),Buchungen=texbuchungen)
    with codecs.open(''+str(row['ID']) + ".tex", "w","utf-8") as letter:
        letter.write(dokument);
        letter.close();
        os.system("pdflatex -interaction=batchmode " + str(row['ID']) + ".tex")
 
os.system("del *.log")
os.system("del *.aux")

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

SVN auf dem Synology

Bislang habe ich Subversion immer auf einem externen Virtual-Root Server (1und1) betrieben, da ich aber auch ein Synology NAS habe, kann ich dies auch zuhause erledigen.

Zur Datensicherung der Repositories nutze ich ein Shellskript, das die jeweils aktuellste Version eines Repos in eine Datei dumpt, die dann über Amazon S3 in der Cloud gesichert wird.

Der SVN-Server wurde über den App-Store des NAS heruntergeladen und installiert

SVN Server

Im Aufgabenplaner wird das Dump-Skript nachts aufgerufen

syno-02

Das Skript dumpt jeweils die HEAD-Version in die entsprechende Datei

NAS> more svnbackupper.sh
#!/bin/ash
for i in $( ls /volume2/svn/); do
 svnadmin dump /volume2/svn/$i -rHEAD > /volume1/backups/synosvnbackups/$i.dump
 done

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

Satzspiegel konstruieren mit Geogebra

Hier ein Beispiel, wie man mit Geogebra Satzspiegel entwerfen kann.

Satzspiegel

satz

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

Eigene Zähler in LaTeX & Word 2013 definieren

Was ich an LaTeX so schätze, sind die Funktionen zum „Programmieren“ eigener Strukturen. Möchte ich einen Befehl zum Erfassen von Business Requirements erstellen, nutze ich einfach eine Kombination aus \newcounter, \the“counter“ und \addtocounter.

\documentclass[12pt,ngerman]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{babel}
 
\newcounter{br}
\addtocounter{br}{1}
\newcommand{\br}[1]{BR--\thebr\stepcounter{br}: #1}
 
\begin{document}
 \br{Button einbauen}
 \br{Zweiten Button einbauen}
\end{document}

In Word geht das auch, ist aber ein wenig komplizierter. Die folgende Beschreibung habe ich auf tips.net gefunden:

1. Schritt: Geh an die Stelle im Dokument, wo das Feld hin soll und drücke Strg-F9. Die erzeugt die Feldklammern.

01

2. Schritt: Innerhalb der Feldklammern füge „seq br“ ein, „br“ steht dabei für den Namen des Zählers. Mit Alt-F9 kannst Du jetzt zwischen Code und Darstellung hin- und herwechseln.

02

03

3. Schritt: Markiere den gesamten Code-Bereich, der später eingefügt werden soll und drücke Alt-F3. Dies öffnet das Menü für die Codebausteine. Gib einen kurzen prägnanten Titel („br“) ein und speichere den Baustein ab.

04

4. Schritt: Wenn Du jetzt irgendwo im Dokument den Zähler benutzen willst, drücke „br“ und der Baustein wird eingefügt.

Solltest Du diese Bausteine auch mal zwischen bereits gesetzte Bausteine setzen, kann ein Refresh der Felder notwendig sein. Dann einfach Text markieren, rechte Maustaste und „Felder aktualisieren“.

05

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

Github Grundlagen

Der folgende Artikel ist eher als Gedankenstütze für mich zu verstehen, um die wesentlichen GitHub Befehle parat zu haben. Bisher habe ich nur auf Subversion gesetzt, Github bietet dies jedoch aus verständlichen Gründen nicht an. (Nachtrag: Subversion geht wohl doch: https://github.com/blog/966-improved-subversion-client-support)

Klonen eines Github Repositories auf die lokale Platte

https://github.com/UweZiegenhagen/Rcourse.git

Hinzufügen einer Datei zum Repository

git add 'Dateiname'

Übertragen auf den Github Server

git push

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