Python Grundlagen#

Ziel dieser Übung ist es die folgenden Grundlagen zu Python und Jupyter zu vermitteln:

Dieses Material wird im Rahmen der Lehrveranstaltung Informationssysteme und Datenanalyse von der Forschungsgruppe Datenbanken und Informationssysteme (DIMA) der TU Berlin zur Verfügung gestellt.

Code kommentieren#

# Dies ist ein einzeiliger Kommentar
print("hello world")  # Zeichen nach dem "#" Symbol werden vom Python Interpreter ignoriert
hello world
"""
Ein Kommentar 
über
mehrere 
Zeilen.
"""

print("hello world")
hello world

Deklaration von Variablen#

Variablen können beliebige Werte annehmen. Typ oder Größe müssen nicht vorher definiert werden. Python differenziert zwischen Groß- und Kleinschreibung und benötigt, anders als bei Java oder C, kein Semikolon am Ende eines Befehls.

Die Variable, die den Wert annehmen soll, steht auf der linken Seite. Der neue Wert der Variable steht auf der rechten Seite.

x = 3  # integer
y = 3.0  # floating point number
z = "Hello"  # ein string definiert mit ""
# ein string, in der Variablen Z definiert mit ""
Z = "World!"

print(x, type(x))
print(y, type(y))
print(z, type(z))
print(Z, type(Z))

# der Type einer Variablen kann auch nachträglich geändert werden
Z = 23.5
print(Z, type(Z))
3 <class 'int'>
3.0 <class 'float'>
Hello <class 'str'>
World! <class 'str'>
23.5 <class 'float'>
# bool Werte werden mit False oder True deklariert
f = False
t = True

print(f, type(f))
print(t, type(t))
False <class 'bool'>
True <class 'bool'>

Arithmetische Operationen#

i = 5
j = 3
print("Summe : ", i + j)
print("Differenz : ", i - j)
print("Produkt : ", i * j)
print("Potenz : ", i**j)
print("Modulo : ", i % j)
print("Floor Division : ", i // j)
print("Float Division : ", i / j)
result = i / j
type(result)
Summe :  8
Differenz :  2
Produkt :  15
Potenz :  125
Modulo :  2
Floor Division :  1
Float Division :  1.6666666666666667
float

Namenskonventionen#

Ein gängiger Guide zu korrektem Code Style sind die Vorgaben von PEP8: https://www.python.org/dev/peps/pep-0008/

Variablen und Funktionen sollten folgende Konvention beachten:
snake_case
lower_case_with_underscore

Allerdings wird auch camelCase häufiger gesehen.

# snake_case
mein_string = "hallo123"
mein_zweiter_string = "hallo345"
# camelCase
meinDritterString = "hallo567"

print(mein_string)
print(mein_zweiter_string)
print(meinDritterString)
hallo123
hallo345
hallo567

Listen, Sets, Tuple, Dictionaries#

Listen
sind Sammlungen von Elementen und behalten die Reihenfolge bei. Listen haben eine variable Größe.

meine_liste = [87, 43, 1, 4, 321, 5, 2, 21, 1, 32, 1, 43]
print(meine_liste, type(meine_liste))

# Einfügen von einem Element in eine Liste
meine_liste.append(43)
print(meine_liste, type(meine_liste))

# Zusammenführen von zwei Listen
meine_liste.extend([34, 21, 74, 146])
print(meine_liste, type(meine_liste))
[87, 43, 1, 4, 321, 5, 2, 21, 1, 32, 1, 43] <class 'list'>
[87, 43, 1, 4, 321, 5, 2, 21, 1, 32, 1, 43, 43] <class 'list'>
[87, 43, 1, 4, 321, 5, 2, 21, 1, 32, 1, 43, 43, 34, 21, 74, 146] <class 'list'>

Sets
sind unsortiere, duplikat-freie Sammlungen von Elementen.

mein_set = {87, 43, 1, 4, 321, 5, 2, 21, 1, 32, 1, 43}
print(mein_set, type(mein_set))

# hinzüfügen eines Elementes
mein_set.add(56)
print(mein_set, type(mein_set))

# entfernen
mein_set.remove(321)
print(mein_set, type(mein_set))

# zusammenführen von zwei Sets
mein_set.update({32, 653, 12, 723, 145})
print(mein_set, type(mein_set))
{32, 321, 2, 1, 4, 5, 43, 21, 87} <class 'set'>
{32, 321, 2, 1, 4, 5, 43, 21, 87, 56} <class 'set'>
{32, 2, 1, 4, 5, 43, 21, 87, 56} <class 'set'>
{32, 2, 1, 4, 5, 43, 12, 653, 145, 723, 21, 87, 56} <class 'set'>

Tuple
sind wie Listen, die nicht verändert werden können

mein_tuple = (1, 5, 1, 4)
print(mein_tuple, type(mein_tuple))
# erstes Element
print(mein_tuple[0])
# letztes Element
print(mein_tuple[len(mein_tuple) - 1])
(1, 5, 1, 4) <class 'tuple'>
1
4

Dictionaries (aka Maps)
sind Key/Value Paare. Keys sind einzigartig in einem dict. Values können mehrmals vorkommen.

woerter = {"house": "Haus", "cat": "Katze", "black": "schwarz"}

print(woerter["house"])

woerter["river"] = "Fluss"
woerter["cat"] = "Veraenderte Katze"
# es können auch Keys verändert werden
woerter["new_house"] = woerter.pop("house")

print(woerter)
Haus
{'cat': 'Veraenderte Katze', 'black': 'schwarz', 'river': 'Fluss', 'new_house': 'Haus'}

If-Else Abfragen#

In Python werden Blöcke mit Einrückungen definiert. Eine Einrückung besteht aus 4 Leerzeichen. In C oder Java werden Blöcke in { } gekennzeichnet. Hinweis: Python IDEs lösen in der Regel Tab automatisch in 4 Leerzeichen auf.

a = 3 + 18
b = 4**2

if a > b:
    print("a groesser b")
    print("a > b")
elif a < b:
    print("a kleiner b")
    print("a < b")
else:
    print("a gleich b")
    print("a == b")
a groesser b
a > b
elemente = [1, 34, 442, 6, 12]

if 1 in elemente:
    print(str(1) + " ist in der Liste")
    if 34 in elemente:
        print(str(34) + " ist auch in der Liste")
else:
    print("Element nicht gefunden")
1 ist in der Liste
34 ist auch in der Liste

While Schleife#

i = 0
words = ["katze", "fenster", "haus"]

while i < len(words):
    print(words[i])
    i = i + 1
katze
fenster
haus

For Schleife#

words = ["katze", "fenster", "haus"]
for w in words:
    print(w, len(w))
katze 5
fenster 7
haus 4

Range Operator#

for i in range(15):
    print(i)
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
for i in range(2, 8):
    print(i)
2
3
4
5
6
7
for i in range(100, 20, -5):
    print(i)
100
95
90
85
80
75
70
65
60
55
50
45
40
35
30
25

Definition eigener Funktionen#

# Iterative Methode ohne Ausgabe
def fib(n):
    n1, n2 = 0, 1
    count = 0

    # Validiere die Eingaben
    if n <= 0:
        print("Falsche Eingabe!")
    elif n == 1:
        print("Fibonacci bis", n, ":")
        print(n1)
    else:
        print("Fibonacci:")
        while count < n:
            print(n1)
            nth = n1 + n2
            # update Werte
            n1 = n2
            n2 = nth
            count += 1


print(fib(14))
Fibonacci:
0
1
1
2
3
5
8
13
21
34
55
89
144
233
None
# Rekursive Methode mit Ausgabe
def fib(n):
    if n < 0:
        print("Falsche Eingabe!")
    # Erste Zahl ist 0
    elif n == 1:
        return 0
    # Zweite Zahl ist 1
    elif n == 2:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)


print(fib(14))
233
# Methode mit mehreren Eingabeparametern
def summe(a, b, c, d):
    return a + b + c + d


summe(2, 2, 15, 10)
29
# Der Typ von Funktionsparameters und Rückgabewerten kann über Type Annotations definiert werden
# Diese werden jedoch nicht vom Python Interpreter überprüft und dienen nur der Lesbarkeit
def summe_typed(a: int, b: float) -> float:
    return a + b


summe_typed(2, 2.0)
4.0

Lambdas#

Lambdas sind kleine anonyme Funktionen mit nur einem Ausdruck

# Lambda mit einem Parameter
l1 = lambda a: a + 10
print(l1(23))
33
# Lambda mit mehreren Parametern
l2 = lambda a, b: a * b
print(l2(15, 6))
90

Grundlagen in Pandas#

Hier ist eine kurze Einführung in Pandas: https://pandas.pydata.org/pandas-docs/stable/index.html

# dependencies importieren
import pandas as pd
import numpy as np

pd.__version__
'2.2.3'
# dataframe erzeugen mit numpy array
dates = pd.date_range("20130101", periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list("ABCD"))
print(df)
                   A         B         C         D
2013-01-01  1.291130 -1.723635 -0.315192  0.087506
2013-01-02 -0.285936  0.998324  0.143208 -0.260650
2013-01-03  0.294595 -0.635373  0.020600  1.771532
2013-01-04  0.689754  1.397468  1.184369 -1.712967
2013-01-05 -0.317074  0.456625 -0.706009 -0.223711
2013-01-06 -1.251361  0.701159  0.980643 -1.041790
# dataframe mit einem dict erzeugen
df = pd.DataFrame(
    {
        "A": 1.0,
        "B": pd.Timestamp("20130102"),
        "C": pd.Series(1, index=list(range(4)), dtype="float32"),
        "D": np.array([3] * 4, dtype="int32"),
        "E": pd.Categorical(["test", "train", "test", "train"]),
        "F": "foo",
    }
)
print(df)
     A          B    C  D      E    F
0  1.0 2013-01-02  1.0  3   test  foo
1  1.0 2013-01-02  1.0  3  train  foo
2  1.0 2013-01-02  1.0  3   test  foo
3  1.0 2013-01-02  1.0  3  train  foo
# ersten drei Zeilen anzeigen
print(df.head(3))
     A          B    C  D      E    F
0  1.0 2013-01-02  1.0  3   test  foo
1  1.0 2013-01-02  1.0  3  train  foo
2  1.0 2013-01-02  1.0  3   test  foo
# letzten zwei Zeilen anzeigen
print(df.tail(2))
     A          B    C  D      E    F
2  1.0 2013-01-02  1.0  3   test  foo
3  1.0 2013-01-02  1.0  3  train  foo
# Statistiken numerischer Felder
df.describe()
A B C D
count 4.0 4 4.0 4.0
mean 1.0 2013-01-02 00:00:00 1.0 3.0
min 1.0 2013-01-02 00:00:00 1.0 3.0
25% 1.0 2013-01-02 00:00:00 1.0 3.0
50% 1.0 2013-01-02 00:00:00 1.0 3.0
75% 1.0 2013-01-02 00:00:00 1.0 3.0
max 1.0 2013-01-02 00:00:00 1.0 3.0
std 0.0 NaN 0.0 0.0
# Projektion auf den Statistiken
df.describe()["A"]
count    4.0
mean     1.0
min      1.0
25%      1.0
50%      1.0
75%      1.0
max      1.0
std      0.0
Name: A, dtype: float64
# Selektion
df[df["A"] > 0]
A B C D E F
0 1.0 2013-01-02 1.0 3 test foo
1 1.0 2013-01-02 1.0 3 train foo
2 1.0 2013-01-02 1.0 3 test foo
3 1.0 2013-01-02 1.0 3 train foo
# Selektion nach Index und Update der Spalte
df.loc[:, "D"] = np.array([5] * len(df), dtype=np.int32)
print(df)
     A          B    C  D      E    F
0  1.0 2013-01-02  1.0  5   test  foo
1  1.0 2013-01-02  1.0  5  train  foo
2  1.0 2013-01-02  1.0  5   test  foo
3  1.0 2013-01-02  1.0  5  train  foo
# Funktionen anwenden

# Liste von Tuplen
matrix = [
    (22, 34, 23),
    (33, 31, 11),
    (44, 16, 21),
    (55, 32, 22),
    (66, 33, 27),
    (77, 35, 11),
]

# DataFrame object erzeugen
df = pd.DataFrame(matrix, columns=list("xyz"), index=list("abcdef"))
print(df)

# jetzt quadrieren wir alle elemente in z
df["z"] = df["z"].apply(lambda x: x * 2)
print(df)
    x   y   z
a  22  34  23
b  33  31  11
c  44  16  21
d  55  32  22
e  66  33  27
f  77  35  11
    x   y   z
a  22  34  46
b  33  31  22
c  44  16  42
d  55  32  44
e  66  33  54
f  77  35  22
# nur Zeile b und c quadrieren
# Liste von Tuplen
matrix = [
    (22, 34, 23),
    (33, 31, 11),
    (44, 16, 21),
    (55, 32, 22),
    (66, 33, 27),
    (77, 35, 11),
]

# DataFrame object erzeugen
df = pd.DataFrame(matrix, columns=list("xyz"), index=list("abcdef"))
df = df.apply(lambda x: x**2 if x.name in ["b", "c"] else x, axis=1)
print(df)
      x    y    z
a    22   34   23
b  1089  961  121
c  1936  256  441
d    55   32   22
e    66   33   27
f    77   35   11