UP | HOME

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

  1. Im Dokument einzelne Code-Stücke unabhängig ausführen, und eventuell das Ergebnis unter dem Code-Stück einfügen.
  2. Einzelne Code-Stücke vom Ausführen beim Exportieren ausschließen.
  3. Exportieren des Dokuments in verschiedene Formate.
  4. Beim Exportieren
    1. mit Code und Ergebnissen
    2. mit Code ohne Ergebnisse
    3. ohne Code mit Ergebnissen
    4. ohne Code und ohne Ergebnissen
  5. Exportieren und Ausführen als Code-Datei.

3 Links

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 oder no für nie, query für eine Abfrage, never-export oder no-export falls die Evaluierung mit C-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 auf t (default) gesetzt ist, wird beim Exportieren abgefragt. Mit nil 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 und both.
:tangle
Für das exportieren des Code-Blocks in die Code-Datei. Möglich sind no, yes und filename. Der Default-Wert ist no.
: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

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

Hier das Ergebnis als Bild. Einmal als PNG, und einmal als PDF.

matplot-exercises.png

./code/matplot-exercises.pdf

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()

Autor: Andreas Kruse

Created: 2018-04-06 Fr 22:57

Validate