Archive for the ‘Python / SciPy / pandas’ Category.

Excel Sylk Dateien parsen mit Python

Vor ein paar Wochen hatte ich das erste Mal mit Microsoft Sylk Dateien zu tun. SLK ist ein Microsoft Format, das von Excel gelesen werden kann, mehr dazu im entsprechenden Wikipedia-Artikel. Ein Vorteil dieses Formats ist es, dass auch gewisse Formatierungen und verbundene Zellen unterstützt werden. Leider gibt es keine offizielle API dafür, das Format unterstützt anscheinend auch nur Windows-Encoding.

In meinem konkreten Fall sah der Input so aus:

ID;PWXL;N;E
P;PGeneral
P;P0
P;P0.00
P;P0.000
P;P0.0000
P;P0.00000
P;P0.000000
P;Pdd.mm.yyyy
C;Y1;X1;K"Inhalt der Zelle A1"
C;Y1;X2;K"Inhalt der Zelle B1"
C;Y2;X1;K"Inhalt der Zelle A2"
C;Y2;X2;K"Inhalt der Zelle B2"
E

In den ersten Zeilen standen irgendwelche Format-Anweisungen, die mich glücklicherweise nicht interessieren mussten. Mir waren nur die Zeilen wichtig, die mit „C“ begannen.

Das folgende Python-Programm habe ich dann genutzt, um die Inhalte zu extrahieren.

import pandas as pd
 
 
def get_sylk_dimension(file):
        """
        Suche die maximale Zeile und Spalte mit Inhalt
        das ist die letzte Zeile mit einem 'C' am Anfang
        gib Tupel aus X und Y-Koordinate zurück
        """
 
        with open(file, 'r', encoding="latin-1") as input:
            for line in input:
                if line[0] in ('E', 'F', 'I','K', 'P'):
                    pass # nicht verarbeiten
                else:
                    contentline = line
                    contentlist = contentline.split(';')
            return int(contentlist[2][1:]), int(contentlist[1][1:])
 
 
def sylk2df(file):
    """
        Wandelt MS SYLK Datei in DataFrame um
    """
 
    x, y = get_sylk_dimension(file)
    df = pd.DataFrame(index=range(y),columns=range(x))
 
    with open(file, 'r', encoding="latin-1") as input:
        for line in input:
            # filtere non-C Zellen raus
            if line[0] in ('E', 'F', 'I','K', 'P'):
                pass
            else:
                columns = line.split(';')
 
                # Erstelle die Koordinaten
                columns[1] = int(columns[1].lstrip('Y'))
                columns[2] = int(columns[2].lstrip('X'))
 
                # bereinige den eigentlichen Inhalt
                columns[3] = columns[3].lstrip('K')
                columns[3] = columns[3].strip().replace('"','')
                columns[3] = columns[3].strip().replace('\n','')
 
                # trage die Inhalte ein
                df.at[columns[1]-1, columns[2]-1] = columns[3]
    return df
 
 
x = sylk2df('test.slk')
print(x)

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

Test-Driven Design mit Python

Am 12.06.2019 habe ich einen kurzen Vortrag zum Thema TDD (Test-Driven Design) bei der PyDDF in Düsseldorf gehalten. Hier die Folien.

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

Python-Skripte per Drag & Drop triggern

Hier ein Beispiel, wie man per Drag & Drop Python-Skripte ausführen kann.

In eine entsprechende Batch-Datei kommt der folgende Aufruf

C:\WinPython-32bit-3.3.5.5\python-3.3.5\python.exe dragdrop.py %1 > error.log 2>&1

In die dragdrop.py kommt dann der eigentliche Python-Code, hier wird die „gedroppte“ Excel-Datei in CSV umgewandelt.

import sys
import os
import pandas as pd

droppedFile = sys.argv[1]
filename = os.path.splitext(droppedFile)[0]

df = pd.read_excel(droppedFile, skiprows=[0,1,2,3])
df.to_csv(filename +'.csv', sep=';', index=False)

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

Python: Code-Rahmen für Auswertungen mit pandas

Für das „Rahmenwerk“ rund um eine Datenauswertung nutze ich immer den selben Code, der a) die Auswertung von Kommandozeilenparametern b) Zeitstempel und c) das Logging übernimmt. Geloggt wird auf STDOUT und in eine Datei.

import pandas as pd # pandas
import argparse # Kommandozeilenargumente
import logging # Logging
import sys # für das Logging
import time # für den Zeitstempel

# Zeitstempel
timestr = time.strftime('%Y%m%d') # '%Y%m%d-%H%M%S'

# Logger in Datei und auf die Konsole
logger = logging.getLogger("Logfile.log")
logger.propagate = False
logger.setLevel(logging.DEBUG)
 
fileHandler = logging.FileHandler(logger.name + '_' + timestr + ".log",mode='w')
fileHandler_format = logging.Formatter('%(asctime)s_%(levelname)s_%(message)s',datefmt='%H:%M:%S')
fileHandler.setFormatter(fileHandler_format)

consoleHandler = logging.StreamHandler(sys.stdout)
#formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
consoleHandler.setFormatter(fileHandler_format)

if logger.handlers:
    for handler in logger.handlers:
        logger.removeHandler(handler)

logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)

# Zum Auswerten der Kommandozeilenparameter (siehe Aufruf aus Excel)
# Definiere Parameter
parser = argparse.ArgumentParser("Was bin ich")
parser.add_argument('-c','--currentdate',dest='currentdate')
parser.add_argument('-l','--lastdate',dest='lastdate')
parser.add_argument('-o','--outputfile',dest='outputpath')

# verarbeite Kommandozeilenargumente

logger.info('Verarbeite die Kommandozeilenargumente')
args = parser.parse_args()

# no more "A value is trying to be set on a copy of a slice from a DF" warning
pd.options.mode.chained_assignment = None

print('args.currentdate', args.currentdate)
print('args.lastdate', args.lastdate)
print('args.outputpath', args.outputpath)

logging.shutdown()

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

Syntaxhighlighting mit Pygments und LaTeX (Beamer-Version)

Das minted-Syntaxhighlighting für eingebetteten Code funktioniert natürlich auch für Beamer-Präsentationen. (Hinweis: Python und pygments müssen installiert sein, --shell-escape muss aktiviert sein)

\documentclass[12pt]{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
 
\usepackage{xcolor}
\definecolor{colBack}{rgb}{1,1,0.8}
 
\usepackage{minted}
\setminted[python]{frame=lines, framesep=2mm, baselinestretch=1.2, bgcolor=colBack,fontsize=\footnotesize,linenos}
\setminted[text]{frame=lines, framesep=2mm, baselinestretch=1.2, bgcolor=colBack,fontsize=\footnotesize,linenos}
 
\usepackage{fancyvrb}
\makeatletter
\newenvironment{pycode}[1]%
  {\xdef\d@tn@me{#1}\xdef\r@ncmd{python #1.py > #1.plog}%
  \typeout{Writing file #1}\VerbatimOut{#1.py}% 
  }
  {\endVerbatimOut %
 \toks0{\immediate\write18}%
 \expandafter\toks\expandafter1\expandafter{\r@ncmd}%
 \edef\d@r@ncmd{\the\toks0{\the\toks1}}\d@r@ncmd %
 \noindent Input
 \inputminted{python}{\d@tn@me.py}%
 \noindent Output
 \inputminted{text}{\d@tn@me.plog}%
}
\makeatother
 
\begin{document}
 
\begin{frame}[containsverbatim]
\frametitle{Python Code Evaluation}
 
\begin{pycode}{abc}
import pandas as pd
print(pd.__version__);
print(123+456)
\end{pycode}
 
\end{frame}
 
\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

Syntaxhighlighting mit Pygments und LaTeX

Hier ein Beispiel, wie man aus LaTeX-Dateien heraus a) Dateien schreibt b) diese Dateien durch einen externen Interpreter (in diesem Fall Python) ausführen lässt, c) die Ergebnisse wieder in TeX anzeigt und d) dabei das Syntax-Highlighting durch pygments erledigen lässt.

Wichtig: --shell-escape muss aktiviert sein, eine Python-Distribution (ich bevorzuge Anaconda) muss installiert sein, Python im Pfad sein.

Das Beispiel lässt sich leicht auf alle anderen Sprachen ausweiten, die im Batch-Verfahren ausführbar sind.

English: The following example shows how one can write code for external interpreters directly in LaTeX. During compilation the code is written to external files, run be the interpreter, its results stored in the corresponding .plog output file. Syntax hightlighting is done via pygments. --shell-escape must be set for the TeX-compiler!

\documentclass[12pt]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{xcolor}
 
\definecolor{colBack}{rgb}{1,1,0.8}
 
\usepackage{minted}
 
\setminted[python]{frame=lines, framesep=2mm, baselinestretch=1.2, bgcolor=colBack,fontsize=\footnotesize,linenos}
\setminted[text]{frame=lines, framesep=2mm, baselinestretch=1.2, bgcolor=colBack,fontsize=\footnotesize,linenos}
 
\usepackage{fancyvrb}
 
\makeatletter
\newenvironment{pycode}[1]%
  {\xdef\d@tn@me{#1}\xdef\r@ncmd{python #1.py > #1.plog}%
  \typeout{Writing file #1}\VerbatimOut{#1.py}% 
  }
  {\endVerbatimOut %
 \toks0{\immediate\write18}%
 \expandafter\toks\expandafter1\expandafter{\r@ncmd}%
 \edef\d@r@ncmd{\the\toks0{\the\toks1}}\d@r@ncmd %
 \noindent Input
 \inputminted{python}{\d@tn@me.py}%
 \noindent Output
 \inputminted{text}{\d@tn@me.plog}%
}
\makeatother
 
 
\begin{document}
 
\begin{pycode}{abc}
import pandas as pd
print(pd.__version__);
print(1+123424)
\end{pycode}
 
 
\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

Retrieve MySQL/MariaDB data with Python

A while ago I had some issues retrieving data from MySQL using Python, as my Python was more up-to-date than the official bindings. A few days ago I found a nice GIST (https://gist.github.com/stefanthoss/364b2a99521d5bb76d51) that uses pymysql:

import pandas as pd
import pymysql
from sqlalchemy import create_engine
 
engine = create_engine('mysql+pymysql://<user>:<password>@<host>[:<port>]/<dbname>')
df = pd.read_sql_query('SELECT * FROM table', engine)
df.head()

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

Hue Programmierung via REST – Teil 2

This entry is part 3 of 4 in the series Hue Programmierung

Nachdem wir jetzt den API-Schlüssel erstellt haben, können wir ihn zur Abfrage der Konfiguration nutzen. Dazu geht man auf die /debug/clip.html Seite und trägt unter URL /api/#Schlüssel# ein. Nach dem Drücken des GET Buttons erhält man dann im Command Response Fenster die Ausgabe, die aus JSON-Teilen für Lampen, Gruppen und der Konfiguration besteht. Da ich einige Lampen und Gruppen habe, kommen bei mir etwas über 5000 Zeilen zurück.

Die JSON-Struktur ist hierarchisch aufgebaut, durch leichte Anpassungen der URL kann man auf die einzelnen Teile der Konfiguration zugreifen, so erhält man durch

  • /api/#Schlüssel#/lights den Abschnitt mit den Lampen
  • /api/#Schlüssel#/lights/1 den Abschnitt von Lampe 1
  • /api/#Schlüssel#/groups den Abschnitt mit den Gruppen
  • /api/#Schlüssel#/config die Systemkonfiguration

Lampen steuern

Um jetzt einzelne Eigenschaften wie an/aus, Helligkeit und Farbe zu setzen, müssen wir per „PUT“ (nicht „GET“) entsprechende JSON-Schnipsel absenden. Das folgende Beispiel schaltet Lampe 9 aus:

  • URL:
    /api/#Schlüssel#/lights/9/state
  • Message Body:
    {"on":false}

und das folgende wieder an:

  • URL:
    /api/#Schlüssel#/lights/9/state
  • Message Body:
    {"on":true}

Hier jetzt noch das wichtigste Beispiel, das nicht nur an/aus kontrolliert, sondern auch Farbe und Helligkeit:

  • URL:
    /api/#Schlüssel#/lights/9/state
  • Message Body:
    {"on":true, "sat":254,"bri":254, "hue":30000}

Im nächsten Teil dieser Serie schauen wir uns dann an, wie die einzelnen Komponenten umgewandelt werden müssen, um die gewünschte Farbe und Helligkeit zu erhalten.

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

Hue Programmierung via REST – Teil 1

This entry is part 2 of 4 in the series Hue Programmierung

Der folgende Artikel und seine Folgeartikel sind für diejenigen gedacht, die ein Philips Hue System ihr Eigen nennen und ein wenig tiefer in die Programmierung einsteigen möchten. Grundvoraussetzung ist eine aktive Hue Bridge im lokalen Netz und mindestens eine gekoppelte Lampe.

In diesem Artikel erstellen wir einen neuen Api-Schlüssel, den wir für alle weiteren Experimente brauchen. In den Folgeartikeln zeige ich dann, wie man mittels Webinterface, CURL und Python entsprechende Befehle an die Hue Bridge senden kann.

Grundsätzliches

Die IP-Adresse der Hue Bridge bekommen wir über den Router raus, sofern wir sie nicht kennen, Philips selbst zeigt noch andere Wege. Ruft man diese IP-Adresse im Browser auf, so kommt nur die Webseite des Systems zusammen mit den Hinweisen auf die entsprechenden Opensource-Lizenzen, nichts sonderlich spannendes.

Spannender wird es allerdings, wenn man die IP-Adresse mit der URL /debug/clip.html aufruft. Dann nämlich präsentiert sich ein Formular mit mehreren Textfeldern und Buttons, die wir im Laufe der Artikel noch näher kennenlernen werden.

Drückt man den GET-Button, kommt die folgende Meldung zurück:

[
	{
		"error": {
			"type": 1,
			"address": "/",
			"description": "unauthorized user"
		}
	}
]

Der Hue Bridge fehlt also der entsprechende Authentifizierungsschlüssel, ohne den keine Befehle angenommen werden. Um einen solchen Schlüssel zu erstellen, geht man wie folgt vor:

  1. Drücke den Link-Button oben auf der Hue Bridge
  2. Gib in der URL Box /api ein
  3. Gib in der Message Body Box einen Text analog zum folgenden Muster ein

    {"devicetype":"commandline#Uwe"}. Ich habe hier einen Hinweis auf meine Kommandozeile als Namen gewählt, letztlich ist man hier aber recht frei. So nennt sich IFFT bei mir „ifft2“, der Logitech Harmony Hub heißt einfach „Harmony Hub“

Wenn alles geklappt hat, dann antwortet die Bridge mit einer Antwort analog zur folgenden:

[
	{
		"success": {
			"username": "yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxt"
		}
	}
]

Der zufällige String hinter username, hier unkenntlich gemacht, ist der entsprechende Schlüssel, den wir bei jeder Anfrage an die HUE Bridge mitliefern müssen. Es empfiehlt sich daher, den in einer Textdatei zu parken und keinesfalls zu veröffentlichen.

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

Einfacher Dateidialog in Python

Manchmal möchte man innerhalb des Python-Skripts einen Dialog anzeigen, um den User z.B. eine Datei auswählen zu lassen. Mit TKinter geht das in Python recht einfach, den Fokus auf den Dialog zu setzen (ihn in den Vordergrund zu holen) ist dabei aber sehr sinnvoll. Folgender Code von Stackexchange (https://stackoverflow.com/questions/3375227/how-to-give-tkinter-file-dialog-focus) tut genau das:

import tkinter as tk
from tkinter import filedialog
 
# Make a top-level instance and hide since it is ugly and big.
root = tk.Tk()
root.withdraw()
 
# Make it almost invisible - no decorations, 0 size, top left corner.
root.overrideredirect(True)
root.geometry('0x0+0+0')
 
# Show window again and lift it to top so it can get focus,
# otherwise dialogs will end up behind the terminal.
root.deiconify()
root.lift()
root.focus_force()
 
filenames = filedialog.askopenfilenames(parent=root) # Or some other dialog
 
# Get rid of the top-level instance once to make it actually invisible.
root.destroy()

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