Literate Programming mit Python und Emacs org-mode
Inhaltsverzeichnis
1 Einleitung
Ich teste und untersuche hier, inwieweit mit Emacs org-mode und Python das „Literate Programming“ (nach Donald Knuth) möglich ist.
Weiterführenden Notizen zu Emacs und org-mode finden sich unter Emacs Notizen.
2 Ziele
- Im Dokument einzelne Code-Stücke unabhängig ausführen, und eventuell das Ergebnis unter dem Code-Stück einfügen.
- Einzelne Code-Stücke vom Ausführen beim Exportieren ausschließen.
- Exportieren des Dokuments in verschiedene Formate.
- Beim Exportieren
- mit Code und Ergebnissen
- mit Code ohne Ergebnisse
- ohne Code mit Ergebnissen
- ohne Code und ohne Ergebnissen
- Exportieren und Ausführen als Code-Datei.
3 Links
- Literate Programming
- Python und Emacs org-mode
- Python lernen
- http://www.python-kurs.eu/python3_kurs.php
- http://de.wikipedia.org/wiki/Python_(Programmiersprache)
- http://de.wikibooks.org/wiki/Python_unter_Linux:_ALLES
- http://openbook.galileocomputing.de/python/
- http://www.ssw.uni-linz.ac.at/Teaching/Lectures/Sem/2000/Pammer/
- http://python.net/~gherman/publications/tut-de/online/tut/
- http://docs.python.org/release/2.5.2/tut/tut.html
- http://www.wspiegel.de/pykurs/pykurs.htm
- http://showmedo.com/videotutorials/series?name=pythonHollandIntroToPythonSeries_german
- http://www.html-world.de/program/python_ov.php
- Andere IDEs für Python
4 Pakete und Einstellungen
4.1 Python
Die Version von Python bei mir ist:
python --version
Python 3.5.2
Bei IPython ist es
ipython --version
5.1.0
4.2 Emacs und Python
Bei mir installiert ist Emacs in der Version
(emacs-version)
GNU Emacs 25.1.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.20.9) of 2016-09-18
In Emacs habe ich die folgenden Pakete für die Arbeit mit Python geladen.
- anaconda-mode
- Code navigation, documentation lookup and completion for Python
- auto-virtualenv
- Auto activate python virtualenvs
- company-jedi
- company-mode completion back-end for Python JEDI
- ein
- Emacs IPython Notebook
- elpy
- Emacs Python Development Environment
- flymake-python-…
- A flymake handler for python-mode files using pyflakes (or flake8)
- jedi
- a Python auto-completion for Emacs
- jedi-direx
- Tree style source code viewer for Python buffer
- nose
- Easy Python test running in Emacs
- ob-ipython
- org-babel functions for IPython evaluation
- pungi
- Integrates jedi with virtualenv and buildout python environments
- py-autopep8
- Use autopep8 to beautify a Python buffer
- py-import-check
- Finds the unused python imports using importchecker
- py-isort
- Use isort to sort the imports in a Python buffer
- py-smart-operator
- smart-operator for python-mode
- pydoc-info
- Better Python support for info-lookup-symbol.
- pyenv-mode
- Integrate pyenv with python-mode
- pyenv-mode-auto
- Automatically activates pyenv version if .python-version file exists.
- python
- Python’s flying circus support for Emacs
- python-docstring
- Smart Python docstring formatting
- python-info
- Python info manual for Emacs
- python-mode
- Python major mode
- python3-info
- Python 3 info manual for Emacs
- pythonic
- Utility functions for writing pythonic emacs package.
- pyvenv
- Python virtual environment interface
- virtualenv
- Virtualenv for Python
- python
- Python’s flying circus support for Emacs
5 org-mode
5.1 Code Blöcke
Code Blöcke werden zwischen „Source Blocks“ eingeschlossen.
#+BEGIN_SRC python -n -r -k :var an_arg="Hallo" :exports both def testfunction(an_arg): """Eine Testfunktion. Das Ergebnis wird unter dem Code-Block als \"RESULT\" ausgegeben. """ return format("Das Argument \"%s\" wurde übergeben." % an_arg) return testfunction(an_arg) #+END_SRC #+RESULTS: : Das Argument "Hallo" wurde übergeben.
Hier das Ergebnis, wenn es nicht in #+BEGIN_EXAMPLE und #+END_EXAMPLE eingerahmt wird.
1: def testfunction(an_arg): 2: """Eine Testfunktion. Das Ergebnis wird unter dem Code-Block als 3: \"RESULT\" ausgegeben. 4: 5: """ 6: return format("Das Argument \"%s\" wurde übergeben." % an_arg) 7: 8: 9: return testfunction(an_arg)
Das Argument "Hallo" wurde übergeben.
Hinweis:
Um den Code zu bearbeiten, ist es angenehm mit C-c '
in den
Python-Editier-Modus zu wechseln. Dies erleichtert das Schreiben des
Codes, insbesondere die Einrückung, doch sehr.
5.2 BEGIN_SRC Optionen
Der #+BEGIN_SRC
Code-Block kennt meherere Optionen, die je nach
Sprache variieren können. Da es hier um Python geht, beschränke ich
mich darauf.
#+BEGIN_SRC <Sprache> <Optionen> Hier kommt der Code rein. #+END_SRC
- -n
- Zur Nummerierung der Codezeilen.
- -r
- Damit auf die Codezeilen referenziert werden kann. !Funktioniert nur für HTML Export!.
- -k
- Zeigt die Referenzen im Code an.
- :eval
- Code-Block Evaluierung. Möglich sind
never
oderno
für nie,query
für eine Abfrage,never-export
oderno-export
falls die Evaluierung mitC-c C-c
weiter möglich sein soll,query-export
für eine Abfrage während des Exports. - org-confirm-babel-evaluate
- Wenn in den org-mode Einstellungen
org-confirm-babel-evaluate
auft
(default) gesetzt ist, wird beim Exportieren abgefragt. Mitnil
wird gar nicht mehr gefragt, sondern blind evaluiert. - :var
- Die Variable wird an den Code weitergeleitet, und kann dort
genutzt werden. (
:var arg0="Hallo
) - :exports
- Der Code und das Ergebnis werden in das Dokument
exportiert. Möglich sind
none
,code
,results
undboth
. - :tangle
- Für das exportieren des Code-Blocks in die
Code-Datei. Möglich sind
no
,yes
undfilename
. Der Default-Wert istno
. - :session
- Diese Code-Blöcke gehören zu einer „Session“ in dem Dokument. Somit muss nicht jeder Code-Block für sich alleine funktionsfähig sein.
5.3 Inline src Blöcke
Code-Blöcke können auch inline, d.h. innerhalb einer Zeile gesetzt werden. Ihr Ergebnis wird beim Exportieren dann direkt in das Ergebnis umgeandelt. Die Syntax dafür ist
src_<language>{<code>}
oder Optional mit Argumenten
src_<language>[<Argumente>]{<code>}
Dies ist ein Beispiel für inline Code-Blöcke. Das Ergebnis ist src_emacs-lisp[:var arg=2]{(/ 100.0 pi arg)}.
Dies ist ein Beispiel für inline Code-Blöcke. Das Ergebnis ist
15.915494309189533
.
Das Ergebnis wird dabei verbatim
ausgegeben.
5.4 Code-Block Namen nutzen
Code-Blöcke können mit Namen versehen werden. Anhand des Namens kann das Ergebnis eines Code-Blocks an ein anderen Code-Block weitergegeben werden.
!!! Da die Namen einzigartig (unique) sein müssen, sind im Beispiel drei Unterstriche. Die "echten" Namen haben zwei Unterstriche. !!! #+NAME: ___DieWahrheitIst #+BEGIN_SRC emacs-lisp :exports none :eval no-exports (* 21 2) #+END_SRC #+NAME: ___DieGanzeWahrheit #+BEGIN_SRC emacs-lisp :var wahrheit=___DieWahrheitIst :exports none :eval no-exports (print wahrheit) #+END_SRC
Wenn man das inline macht, wird so das Ergebnis eines Code-Blocks in den Text eingefügt.
Die Wahrheit ist src_emacs-lisp[:var wahr=__DieWahrheitIst]{(print wahr)}.
Die Wahrheit ist 42
.
Noch einfacher geht das ganze dann mit der Call-Funktion.
#+CALL: <name>(<Argumente>) #+CALL: __DieGanzeWahrheit()
Die Ausgabe als #+RESULTS:
42
Und das ganze dann auch noch inline.
Die Wahrheit ist eine Zahl, und ihr Wert ist call___DieGanzeWahrheit().
Die Wahrheit ist eine Zahl, und ihr Wert ist 42
.
5.5 Code Block in Tabelle nutzen
Erzeugen wir erst einmal einen Source Code Block.
#+NAME: py4tblformula #+BEGIN_SRC python -n -r -k :var arg1=0 arg2=0 :exports none :eval no-export return (arg1 * (arg2**2))**(1/2) #+END_SRC | Wert 1 | Wert 2 | Ergebnis | |--------+--------+----------| | 1 | 2 | | | 2 | 4 | | | 3 | 6 | | | 4 | 8 | | | 5 | 10 | | #+TBLFM: $3='(org-sbe "py4tblformula" (arg1 $1) (arg2 $2));%.2f
Das Ergebnis sieht dann so aus.
Wert 1 | Wert 2 | Ergebnis |
---|---|---|
1 | 2 | 2.00 |
2 | 4 | 5.66 |
3 | 6 | 10.39 |
4 | 8 | 16.00 |
5 | 10 | 22.36 |
5.6 Exportieren in ein Dokument
Um das Dokument als PDF, ODT, HTML u.ä. zu exportieren, gibt man das
Kommando C-c C-e
ein, um im dann auftauchenden Menü das gewünschte
zu wählen.
5.7 Den Code als Python Datei exportieren
Mit dem Kommando org-babel-tangle
(C-c C-v t
) wird aus dem
Dokument der getanglete Code in eine Python-Datei kopiert. Dafür
werden nur die Code-Blöcke benutzt, bei denen tangle auf yes
oder
einen Dateinamen stehen.
5.8 org-confirm-babel-evaluate
Wenn ein Source Code Block evaluiert werden soll, muss das bestätigt
werden (default). Das ein- und ausschalten kann über die Funktion
erledigt werden. Mit M-x babel-confirm
wird der Status
zurückgegeben. Mit C-u M-x babel-confirm
die Einstellung getoggelt.
(defun babel-confirm (flag) "Report the setting of org-confirm-babel-evaluate. If invoked with C-u, toggle the setting" (interactive "P") (if (equal flag '(4)) (setq org-confirm-babel-evaluate (not org-confirm-babel-evaluate))) (message "Babel evaluation confirmation is %s" (if org-confirm-babel-evaluate "on" "off")))
6 Python Skripte
Hier einige Python-Skripte, die beim tanglen in verschiedene Code-Dateien exportiert werden.
6.1 klasse.py
Die Klasse wird mit
1: import klasse as mk
importiert.
6.1.1 Header
2: #!/usr/bin/env python 3: # coding: utf-8 4: # python-n-org-mode.org[*Org Src python-n-org-mode.org[ python ]*] 5: # 25.03.2016 Andreas Kruse
6.1.2 Imports
Es werden keine imports benötigt.
6:
6.1.3 class meineklasse
Hier wird die Klasse „meineklasse“ angelegt. Sie erbt nur von „object“, womit sie die grundlegenden Fähigkeiten einer Klasse besitzt.
7: class meineklasse(object): 8: """Documentation for meineklasse 9: 10: """
6.1.3.1 def __init__
Bei der Initialisierung werden die beiden privaten Variabeln
__meinpfad
(Zeile 12) und__meinedaten
(Zeile_13)
angelegt.
11: def __init__(self): 12: self.__meinpfad = "" 13: self.__meinedaten = ""
6.1.3.2 def set_args
Mit dieser Funktion werden die beiden Variabeln __meinpfad
und
__meinedaten
gesetzt.
14: def set_args(self, pfad, daten): 15: self.__meinpfad = pfad 16: self.__meinedaten = daten
6.1.3.3 def get_args
Diese Funktion gibt die beiden Variabeln __meinpfad
und
__meinedaten
zurück.
17: def get_args(self): 18: """Some not so useful comment to fill this space with words. 19: """ 20: print(self.__meinpfad, ":", self.__meinedaten) 21: return self.__meinedaten, self.__meinpfad
6.2 matplot-exercises.py
6.2.1 Header
1: #!/usr/bin/env python 2: # coding: utf-8 3: # matplot-exercises.py 4: # 24.03.2016 Andreas Kruse
6.2.2 Imports
1: import numpy as np 2: import matplotlib.pyplot as plt
6.2.3 Code
1: x = np.linspace(0, 10) 2: line,= plt.plot(x, np.sin(x), '--', linewidth=2) 3: 4: dashes = [10, 5, 100, 5] # 10 points on, 5 off, 100 on, 5 off 5: line.set_dashes(dashes) 6: 7: # plt.show() 8: plt.savefig("./matplot-exercises.png") 9: plt.savefig("./matplot-exercises.pdf") 10: print("matplot-exercises saved!")
6.2.4 Das Ergebnis
6.3 parsen.py
Hier geht es um Python-Funktionen zum Parsen von Dateien.
6.3.1 Header
1: #!/usr/bin/env python 2: # coding: utf-8 3: # parsen.py 4: # 04.03.2016 Andreas Kruse
6.3.2 Imports
5: import re
6.3.3 Code
Regular Expression (regexp) vorkompiliert, um die Zahlen aus folgendem String zu lesen.
6: # dashes = [10, 5, 100, 5] # 10 points on, 5 off, 100 on, 5 off 7: reg = re.compile(r'\d+\s+(.*?)[,$]')
Hier das Suchen mit search()
.
8: print("\n---- reg.search ----\n") 9: for line in open('matplot-exercises.py', 'r'): 10: mo = reg.search(line) 11: if mo is not None: 12: print(mo.group(1))
Als nächstes wird finditer()
probiert.
13: print("\n---- reg.finditer ----\n") 14: for line in open('matplot-exercises.py', 'r'): 15: moiter = reg.finditer(line) 16: for mo in moiter: 17: print(mo.group(0), mo.span())
Diesmal findall()
auf ein etwas komplizierteren String angesetzt.
18: print("\n---- Teststring ----\n") 19: teststring = "Irgendwas vorher[Plot Name&String&[123456:irgendwastolles];Was auch immer noch kommt.;" 20: teststring += "Irgendwas vorher[Plot Name&String&[123487:nochwastolles];Was auch immer noch kommt.;" 21: teststring += "Irgendwas vorher[Plot Name&String&[213487:onchwastolles];Was auch immer noch kommt.;" 22: teststring += "Irgendwas vorher[Plot Name&String&[132487:ncohwastolles];Was auch immer noch kommt.;" 23: print(teststring, "\n") 24: testreg = re.compile(r'Name&String&\[(.*?)\];') 25: moall = testreg.findall(teststring) 26: print("FINDALL = ", moall) 27: for found in moall: 28: print(" - ", found)
Das Ergebnis der Tests.
---- reg.search ---- points on ---- reg.finditer ---- 10 points on, (28, 41) 5 off, (42, 48) 100 on, (49, 56) ---- Teststring ---- Irgendwas vorher[Plot Name&String&[123456:irgendwastolles];Was auch immer noch kommt.;Irgendwas vorher[Plot Name&String&[123487:nochwastolles];Was auch immer noch kommt.;Irgendwas vorher[Plot Name&String&[213487:onchwastolles];Was auch immer noch kommt.;Irgendwas vorher[Plot Name&String&[132487:ncohwastolles];Was auch immer noch kommt.; FINDALL = ['123456:irgendwastolles', '123487:nochwastolles', '213487:onchwastolles', '132487:ncohwastolles'] - 123456:irgendwastolles - 123487:nochwastolles - 213487:onchwastolles - 132487:ncohwastolles
6.4 stringsearch.py
In Strings mit String-Methoden suchen.
6.4.1 Header
1: #!/usr/bin/env python 2: # stringsearch.py -- searching in strings with string methods 3: # 07.02.2016 Andreas Kruse
6.4.2 Imports
Keine Imports.
6.4.3 Code
Als erstes benötigen wir die Eingabe des Nutzers von dem zu durchsuchenden String und dem String, der dort gesucht werden soll.
4: s = raw_input('Enter source string: ') 5: sub = raw_input('Enter substring: ')
Schnell mal schauen, ob der Suchstring im Quellstring vorhanden ist.
6: # The operator returns TRUE or FALSE 7: if sub in s: 8: print "´%s´ is a substring of ´%s´" % (sub, s) 9: else: 10: print "´%s´ is NOT a substring of ´%s´" % (sub, s)
Die String-Funktion index
gibt schon mehr Information her.
11: # index, rindex return index (0-based), or raise ValueError: 12: try: 13: idx = s.index(sub) 14: ridx = s.rindex(sub) 15: print "´%s´.index(´%s´) == %d" % (s, sub, idx) 16: print "´%s´.rindex(´%s´) == %d" % (s, sub, ridx) 17: except ValueError: 18: print "´%s´ doesn´t occur in ´%s´" (sub, s)
Bei der String-Funktion find
gibt es kein ValueError
.
19: # find, rfind return index (0-based), or -1 if not found 20: pos = s.find(sub) 21: rpos = s.rfind(sub) 22: print "´%s´.find(´%s´) == %d" % (s, sub, pos) 23: print "´%s´.rfind(´%s´) == %d" % (s, sub, rpos)
Mit den String-Funktionen startswith
und endswith
testet man nur,
ob der Suchstring am Anfang oder am Ende des Quellstrings vorkommt.
24: # startswith, endswith return TRUE or FALSE 25: print "´%s.startswith(´%s´) == " % (s, sub), s.startswith(sub) 26: print "´%s.endswith(´%s´) == " % (s, sub), s.endswith(sub)
Die Funktion count
gibt aus, wie oft der Suchstring im Quellstring
vorkommt.
27: # count returns number of non-overlapping occurences: 28: print "´%s´ occurs %d times in ´%s´" % (sub, s.count(sub), s)
6.5 String split
Andere String-Methoden.
6.5.1 Header
1: #!/usr/bin/env python 2: # stringsplit.py -- searching in strings with string methods 3: # 27.02.2017 Andreas Kruse
6.5.2 Imports
Keine Imports.
6.5.3 Code
datei = './python-n-org-mode.tex' txt = "" with open(datei, 'r') as f: txt = f.read() start = r'\begin{lstlisting}' ende = r'\end{lstlisting}' neutxt = "" oben, delim, unten = txt.partition(start) while(unten): neutxt = neutxt + oben + delim oben, delim, unten = unten.partition(ende) # tu was mit oben oben = "\n---- SUBSTART ----\n" + oben neutxt = neutxt + oben + delim + "\n---- SUBEND ----\n" oben, delim, unten = unten.partition(start) print(neutxt + unten)
6.6 list of list durchlaufen
for arg1, arg2, arg3, arg4 in (("a", "b", "c", "d"),("aa", "ab", "ac", "ad")): print("arg1", arg1) print("arg2", arg2) print("arg3", arg3) print("arg4", arg4)
6.7 pandas
1: import pandas as pd 2: import numpy as np 3: import matplotlib.pyplot as plt 4: 5: rows = 9999 6: cols = ['a', 'b'] 7: timecol = pd.date_range('20170318110922', periods=rows) 8: numbers = range(1,rows+1) 9: gendata = pd.DataFrame(np.random.randn(rows, 1), index=timecol, columns=list(cols[1])) 10: gendata.loc[:,cols[0]] = numbers 11: gendata.to_csv(datafile, sep=';', index_label='time', columns=['a', 'b']) 12: 13: data = pd.read_csv(datafile, sep=';', header=0, infer_datetime_format=True, comment='#', memory_map=True, parse_dates=['time']) 14: datatb = data[['b']] 15: 16: data.loc[:,'Rolling Mean'] = data['b'].rolling(window=10).mean() 17: data.loc[:,'Rolling Sum'] = data['b'].rolling(window=10).sum() 18: 19: # data.plot(kind='line', grid=True, legend=True, use_index=False, y='time', x='b') # ['b', 'Rolling Mean', 'Rolling Sum'] 20: # plt.show() 21: 22: # datatb_sum = datatb.sum() 23: # print("\nsum:", datatb_sum, "\n") 24: # print(data['b'].describe()) 25: print(data.describe()) 26: 27: #print("\n", data.loc[1, 'a'], "\n") 28: 29: #print("\n", data['time'].head(4), "\n") 30: print("\n", data.head(), "\n") 31: print("\n", data.tail(5), "\n") 32:
>>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> ... ... >>> ... ... ... a b Rolling Mean Rolling Sum count 9999.000000 9999.000000 9990.000000 9990.000000 mean 5000.000000 -0.000063 -0.000247 -0.002467 std 2886.607005 0.988421 0.325378 3.253779 min 1.000000 -3.866026 -1.240299 -12.402993 25% 2500.500000 -0.664675 -0.223300 -2.233000 50% 5000.000000 0.015612 0.005847 0.058473 75% 7499.500000 0.665711 0.222070 2.220702 max 9999.000000 4.244649 1.130717 11.307172 >>> ... >>> ... time a b Rolling Mean Rolling Sum 0 2017-03-18 11:09:22 1 -1.019090 NaN NaN 1 2017-03-19 11:09:22 2 1.229911 NaN NaN 2 2017-03-20 11:09:22 3 -0.266117 NaN NaN 3 2017-03-21 11:09:22 4 1.884065 NaN NaN 4 2017-03-22 11:09:22 5 0.413736 NaN NaN time a b Rolling Mean Rolling Sum 9994 2044-07-28 11:09:22 9995 -0.451663 -0.065499 -0.654989 9995 2044-07-29 11:09:22 9996 -1.477035 -0.209918 -2.099183 9996 2044-07-30 11:09:22 9997 0.936827 -0.259702 -2.597021 9997 2044-07-31 11:09:22 9998 -0.444598 -0.149219 -1.492186 9998 2044-08-01 11:09:22 9999 1.196533 -0.103803 -1.038028
1: import pandas as pd 2: import numpy as np 3: import matplotlib.pyplot as plt 4: 5: s = pd.Series([2, 3.1415, 4, np.nan, 9, 4]) 6: print("\nSeries:\n", s) 7: 8: no_periods = 7 9: dates = pd.date_range('20170315', periods=no_periods) 10: print("\nDates:\n", dates) 11: 12: lcol = list('ABCD') 13: df = pd.DataFrame(np.random.randn(no_periods,len(lcol)), index=dates, columns=lcol) 14: print("\nDataFrame:\n", df) 15: 16: df2 = pd.DataFrame({ 17: 'A' : 1., 18: 'B' : pd.Timestamp('20170415'), 19: 'C' : pd.Series(1, index=list(range(4)), dtype='float32'), 20: 'D' : np.array([3] * 4, dtype='int32'), 21: 'E' : pd.Categorical(["test", "train", "test", "train"]), 22: 'F' : 'foo', 23: }) 24: print("\nDataframe 2:\n", df2) 25: 26: print("\nHead:\n", df.head()) 27: print("\nTail:\n", df.tail(3)) 28: print("\nIndex:\n", df.index) 29: print("\nColumns:\n", df.columns) 30: print("\nValues:\n", df.values) 31: print("\nDescribe:\n", df.describe()) 32: print("\nTranspose:\n", df.T) 33: print("\nSort axis:\n", df.sort_index(axis=1, ascending=False)) 34: print("\nSort values:\n", df.sort_values(by='B')) 35: print("\nGet a single column df['A'] :\n", df['A']) 36: print("\nGet a single column df.A :\n", df.A) 37: print("\nGet rows by slice row numbers :\n", df[0:3]) 38: print("\nGet rows by slice entry names:\n", df['2017-03-15':'2017-03-18']) 39: print("\nGet a single value :\n", df.loc[dates[1], 'C']) 40: print("\nIs in method :\n", df[dates.isin(['2017-03-16', '2017-03-20'])]) 41: print("\nMean :\n", df.mean())
>>> >>> >>> >>> Series: 0 2.0000 1 3.1415 2 4.0000 3 NaN 4 9.0000 5 4.0000 dtype: float64 >>> >>> >>> Dates: DatetimeIndex(['2017-03-15', '2017-03-16', '2017-03-17', '2017-03-18', '2017-03-19', '2017-03-20', '2017-03-21'], dtype='datetime64[ns]', freq='D') >>> >>> >>> DataFrame: A B C D 2017-03-15 -0.295786 0.418509 0.155799 -0.291698 2017-03-16 0.645025 -1.014092 0.588442 0.822387 2017-03-17 0.029185 -1.211002 0.209220 0.622748 2017-03-18 1.062711 0.131436 -0.177434 -2.425198 2017-03-19 -2.081938 0.506990 -0.822545 -1.660982 2017-03-20 -0.322644 -0.276965 1.366793 1.419028 2017-03-21 -1.188212 -0.076080 0.012820 -1.935340 >>> ... ... ... ... ... ... ... >>> Dataframe 2: A B C D E F 0 1.0 2017-04-15 1.0 3 test foo 1 1.0 2017-04-15 1.0 3 train foo 2 1.0 2017-04-15 1.0 3 test foo 3 1.0 2017-04-15 1.0 3 train foo >>> Head: A B C D 2017-03-15 -0.295786 0.418509 0.155799 -0.291698 2017-03-16 0.645025 -1.014092 0.588442 0.822387 2017-03-17 0.029185 -1.211002 0.209220 0.622748 2017-03-18 1.062711 0.131436 -0.177434 -2.425198 2017-03-19 -2.081938 0.506990 -0.822545 -1.660982 Tail: A B C D 2017-03-19 -2.081938 0.506990 -0.822545 -1.660982 2017-03-20 -0.322644 -0.276965 1.366793 1.419028 2017-03-21 -1.188212 -0.076080 0.012820 -1.935340 Index: DatetimeIndex(['2017-03-15', '2017-03-16', '2017-03-17', '2017-03-18', '2017-03-19', '2017-03-20', '2017-03-21'], dtype='datetime64[ns]', freq='D') Columns: Index(['A', 'B', 'C', 'D'], dtype='object') Values: [[-0.29578562 0.41850907 0.15579927 -0.2916977 ] [ 0.64502467 -1.01409192 0.58844178 0.82238725] [ 0.02918458 -1.21100156 0.20922037 0.62274796] [ 1.0627111 0.13143587 -0.17743363 -2.42519829] [-2.08193764 0.50699006 -0.8225454 -1.66098231] [-0.32264429 -0.27696498 1.36679264 1.41902815] [-1.18821231 -0.0760802 0.01281957 -1.93534007]] Describe: A B C D count 7.000000 7.000000 7.000000 7.000000 mean -0.307380 -0.217315 0.190442 -0.492722 std 1.066364 0.670359 0.675374 1.519289 min -2.081938 -1.211002 -0.822545 -2.425198 25% -0.755428 -0.645528 -0.082307 -1.798161 50% -0.295786 -0.076080 0.155799 -0.291698 75% 0.337105 0.274972 0.398831 0.722568 max 1.062711 0.506990 1.366793 1.419028 Transpose: 2017-03-15 2017-03-16 2017-03-17 2017-03-18 2017-03-19 2017-03-20 \ A -0.295786 0.645025 0.029185 1.062711 -2.081938 -0.322644 B 0.418509 -1.014092 -1.211002 0.131436 0.506990 -0.276965 C 0.155799 0.588442 0.209220 -0.177434 -0.822545 1.366793 D -0.291698 0.822387 0.622748 -2.425198 -1.660982 1.419028 2017-03-21 A -1.188212 B -0.076080 C 0.012820 D -1.935340 Sort axis: D C B A 2017-03-15 -0.291698 0.155799 0.418509 -0.295786 2017-03-16 0.822387 0.588442 -1.014092 0.645025 2017-03-17 0.622748 0.209220 -1.211002 0.029185 2017-03-18 -2.425198 -0.177434 0.131436 1.062711 2017-03-19 -1.660982 -0.822545 0.506990 -2.081938 2017-03-20 1.419028 1.366793 -0.276965 -0.322644 2017-03-21 -1.935340 0.012820 -0.076080 -1.188212 Sort values: A B C D 2017-03-17 0.029185 -1.211002 0.209220 0.622748 2017-03-16 0.645025 -1.014092 0.588442 0.822387 2017-03-20 -0.322644 -0.276965 1.366793 1.419028 2017-03-21 -1.188212 -0.076080 0.012820 -1.935340 2017-03-18 1.062711 0.131436 -0.177434 -2.425198 2017-03-15 -0.295786 0.418509 0.155799 -0.291698 2017-03-19 -2.081938 0.506990 -0.822545 -1.660982 Get a single column df['A'] : 2017-03-15 -0.295786 2017-03-16 0.645025 2017-03-17 0.029185 2017-03-18 1.062711 2017-03-19 -2.081938 2017-03-20 -0.322644 2017-03-21 -1.188212 Freq: D, Name: A, dtype: float64 Get a single column df.A : 2017-03-15 -0.295786 2017-03-16 0.645025 2017-03-17 0.029185 2017-03-18 1.062711 2017-03-19 -2.081938 2017-03-20 -0.322644 2017-03-21 -1.188212 Freq: D, Name: A, dtype: float64 Get rows by slice row numbers : A B C D 2017-03-15 -0.295786 0.418509 0.155799 -0.291698 2017-03-16 0.645025 -1.014092 0.588442 0.822387 2017-03-17 0.029185 -1.211002 0.209220 0.622748 Get rows by slice entry names: A B C D 2017-03-15 -0.295786 0.418509 0.155799 -0.291698 2017-03-16 0.645025 -1.014092 0.588442 0.822387 2017-03-17 0.029185 -1.211002 0.209220 0.622748 2017-03-18 1.062711 0.131436 -0.177434 -2.425198 Get a single value : 0.588441776539 Is in method : A B C D 2017-03-16 0.645025 -1.014092 0.588442 0.822387 2017-03-20 -0.322644 -0.276965 1.366793 1.419028 Mean : A -0.307380 B -0.217315 C 0.190442 D -0.492722 dtype: float64
6.8 Tkinter und Scrollbar
1: #!/usr/bin/python 2: 3: # Tkinter und Scrollbar 4: # Andreas Kruse 5: # 05.04.2018 6: 7: import tkinter as tk 8: from tkinter import IntVar, StringVar, ttk 9: 10: 11: # http://effbot.org/zone/tkinter-autoscrollbar.htm 12: class AutoScrollbar(tk.Scrollbar): 13: # a scrollbar that hides itself if it's not needed. only 14: # works if you use the grid geometry manager. 15: def set(self, lo, hi): 16: if float(lo) <= 0.0 and float(hi) >= 1.0: 17: # grid_remove is currently missing from Tkinter! 18: self.tk.call("grid", "remove", self) 19: else: 20: self.grid() 21: tk.Scrollbar.set(self, lo, hi) 22: 23: def pack(self, **kw): 24: raise Exception("cannot use pack with this widget") 25: 26: def place(self, **kw): 27: raise Exception("cannot use place with this widget") 28: 29: 30: root = tk.Tk() 31: root.title('--- Scrollbars ---') 32: root.geometry('600x300') 33: 34: mainlabeltext = StringVar() 35: mainlabel = tk.Label( 36: root, 37: textvariable=mainlabeltext, 38: ) 39: mainlabel.grid(row=0, column=0) 40: mainlabeltext.set("Nothing selected, so far...") 41: 42: vscrollbar = AutoScrollbar(root) 43: vscrollbar.grid( 44: row=1, 45: column=1, 46: sticky="ns" 47: ) 48: hscrollbar = AutoScrollbar( 49: root, 50: orient="horizontal" 51: ) 52: hscrollbar.grid( 53: row=2, 54: column=0, 55: sticky="ew", 56: ) 57: 58: canvas = tk.Canvas( 59: root, 60: yscrollcommand=vscrollbar.set, 61: xscrollcommand=hscrollbar.set, 62: ) 63: canvas.grid( 64: row=1, 65: column=0, 66: sticky="news", 67: ) 68: 69: vscrollbar.config(command=canvas.yview) 70: hscrollbar.config(command=canvas.xview) 71: 72: # make the canvas expandable 73: root.grid_rowconfigure(1, weight=1) 74: root.grid_columnconfigure(0, weight=1) 75: 76: # 77: # create canvas contents 78: 79: frame = tk.Frame(canvas) 80: frame.rowconfigure(1, weight=1) 81: frame.columnconfigure(1, weight=1) 82: 83: dcheckbuttonsstate = {} 84: dcheckbuttons = {} 85: dstatuslabel = {} 86: dstatuslabeltext = {} 87: dtexttemplates = { 88: 'selected' : "Selected.", 89: 'not selected' : "Not selected.", 90: 'marker label' : "You may choose {0}, or not ...", 91: 'result label' : "Well, the number is {0}.", 92: } 93: lcombobox = ['first', 'second', 'third'] 94: dcomboboxes = {} 95: dresultlabel = {} 96: dresultlabeltext = {} 97: no_of_rows = 22 98: 99: 100: def var_states(): 101: ''' 102: Called up by clicking on the selection checkbutton. 103: ''' 104: 105: summ = 0 106: for i in range(1, no_of_rows): 107: if 1 == dcheckbuttonsstate[i].get(): 108: dstatuslabeltext[i].set(dtexttemplates['selected']) 109: dcomboboxes[i].config(state='normal') 110: combo = dcomboboxes[i].get() 111: if combo == lcombobox[0]: 112: combo = 1 113: elif combo == lcombobox[1]: 114: combo = 2 115: elif combo == lcombobox[2]: 116: combo = 3 117: else: 118: combo = 1 119: dresultlabeltext[i].set( 120: dtexttemplates['result label'].format(i * combo) 121: ) 122: dresultlabel[i].config(state='normal') 123: summ += i * combo 124: else: 125: dstatuslabeltext[i].set(dtexttemplates['not selected']) 126: dcomboboxes[i].config(state='disabled') 127: dresultlabeltext[i].set(dtexttemplates['result label'].format(i)) 128: dresultlabel[i].config(state='disabled') 129: 130: if 0 < summ: 131: mainlabeltext.set( 132: "{0} is the summary of selected results".format(summ) 133: ) 134: else: 135: mainlabeltext.set("Nothing selected, so far...") 136: 137: 138: def combo_on_select(event=None): 139: # <-- this works only with bind because `command=` doesn't send event 140: if event: 141: print("event.widget:", event.widget.get()) 142: var_states() 143: 144: 145: def set_list_widgets(frame, rows): 146: # In this part the widgets will be placed 147: for i in range(1, rows): 148: mytext = dtexttemplates['marker label'].format(i) 149: mylabel = tk.Label( 150: frame, 151: text=mytext, 152: ) 153: mylabel.grid(row=i, column=0) 154: 155: # checkbuttons, command to var_states() 156: dcheckbuttonsstate[i] = IntVar() 157: dcheckbuttons[i] = tk.Checkbutton( 158: frame, 159: # text="selected", 160: variable=dcheckbuttonsstate[i], 161: activeforeground='blue', 162: selectcolor='red', 163: command=var_states, 164: ) 165: dcheckbuttons[i].grid(row=i, column=1) 166: 167: # label shows the status of the checkbutton 168: dstatuslabeltext[i] = StringVar() 169: dstatuslabeltext[i].set(dtexttemplates['not selected']) 170: dstatuslabel[i] = tk.Label( 171: frame, 172: textvariable=dstatuslabeltext[i], 173: ) 174: dstatuslabel[i].grid(row=i, column=2) 175: 176: # comboboxes, state disabled until checkbutton is set 177: dcomboboxes[i] = ttk.Combobox( 178: frame, 179: values=lcombobox, 180: width=10, 181: ) 182: dcomboboxes[i].set(lcombobox[0]) 183: dcomboboxes[i].grid(row=i, column=3) 184: dcomboboxes[i].config(state='disabled') 185: dcomboboxes[i].bind('<<ComboboxSelected>>', combo_on_select) 186: 187: dresultlabeltext[i] = StringVar() 188: dresultlabeltext[i].set(dtexttemplates['result label'].format(i)) 189: dresultlabel[i] = tk.Label( 190: frame, 191: textvariable=dresultlabeltext[i], 192: ) 193: dresultlabel[i].grid(row=i, column=4) 194: dresultlabel[i].config(state='disabled') 195: 196: # END OF DEF set_list_widget 197: 198: 199: set_list_widgets(frame, no_of_rows) 200: 201: canvas.create_window(0, 0, anchor="nw", window=frame) 202: frame.update_idletasks() 203: canvas.config(scrollregion=canvas.bbox("all")) 204: 205: root.mainloop()