KI150 Übung J.Busse#

unsystematische Notizen zur Übung J.Busse zur Veranstaltung KI150 “Programmieren”

Mikro-Aufgaben dicts#

Quelle: 3_Dictionaries und Mengen.ipynb

shopping_dict = {"apple": 5, "banana": 4, "milk": 2}
print(shopping_dict) 
{'apple': 5, 'banana': 4, 'milk': 2}

Anzahl der Keys

...
Ellipsis

Ist der key “ham” enthalten? Verschiedene Lösungen, incl. get()

...
Ellipsis

Liste aller keys; Liste alle Values

...
Ellipsis

Erhöhe die Anzahl der “apple” um 2

...
Ellipsis

Füge hinzu:

  • “ham”

  • “apple” (gibt es schon: Was passiert?)

...
Ellipsis

Lösche

  • “milk”

  • “steak” (gibt es nicht: wsa tun?)

...
Ellipsis

Warum funktioniert das folgende? Erklären Sie:

for k, v in shopping_dict.items():
    print(k,v)
apple 5
banana 4
milk 2

Wörter und Zeichen#

wort_laenge = { "hallo": 5, "Welt": 4, "Grüß": 4, "Gott": 4, "Tschau": 5}

Erzeuge ein “umgedrehtes” Dictionary, bei dem man für jede Wortlänge die entsprechenden Wörter nachschlagen kann!

laenge_wort = {}
...
# assert laenge_wort == {5: {'Tschau', 'hallo'}, 4: {'Gott', 'Grüß', 'Welt'}}

Die ähnliche Aufgabe, aber mit Zusatzelement: Füge eine Funktion hinzu, die die Geburtstage “normalisiert”, d.h. vergleichbar macht.

  • mit einer Bibliothek?

  • mit regex?

Geburtstage = { 'Anna': "01.05.2005", 'Ben': '1.5.2005', 'Charlie': "5.1.2005", 'Delta': "2005/01/05"}

Verschachtelte dictionaries (nested dictionaries)#

shopping_monday = {"apple": 3, "juice": 2}
shopping_friday = {"juice": 2, "candy": 25}
shopping = {"monday": shopping_monday, "friday": shopping_friday}
shopping
{'monday': {'apple': 3, 'juice': 2}, 'friday': {'juice': 2, 'candy': 25}}

Erstellen Sie eine Liste, in der alle Waren enthalten sind, die in shopping enthalten sind. Vorgehen: Schleife in der Schleife.

...
Ellipsis

zip()#

https://docs.python.org/3/library/functions.html#zip

item_names = ["apple", "banana", "candy", "ice cream"]
nums = [3, 5, 5, 7]

erzeuge obiges shopping-dict!

dict(zip(item_names, nums))
{'apple': 3, 'banana': 5, 'candy': 5, 'ice cream': 7}

2. Praktikum (Ausgabedatum: 25.10.2022)#

Herumspielen mit den Aufgaben des 2. Übungsblattes

char_count#

Gegeben ist ein String:

string = "Hallo Welt!"

gesucht: Ein dict char_count, das zu jedem Zeichen im String angibt, wie oft es vorkommt.

...
char_count = ...

Erzeugen Sie ein dict, das zu jedem Buchstaben seine prozentuale Häufigkeit unter allen Buchstaben angibt!

...
Ellipsis

Würfeln#

Konsultieren Sie https://python.readthedocs.io/en/stable/library/random.html. Versuchen Sie auf möglichst viele verschiedene Weisen eine Liste der Länge max_len von ganzzahligen Zufallszahlen zwischen 0 und 1 zu erzeugen:

  • Urnen-Modell ohne zurücklegen

  • Urnen-Modell mit zurücklegen

    • gleichverteilt

    • nominalverteilt

Dafür gibt es in der Bibliothek random natürlich schon fertige Funktionen:

  • Recherchieren und verwenden Sie diese!

  • spielen: Welche lassen sich leicht durch Selbermachen simulieren?

max_len = 10
...

Standard-Mikro-Aufgaben#

Insbesondere für Übungsblatt 5, Aufgabe 2: “Die Null-Chiffre” ist es gut, schon ein paar Lösungen aus den vergangenen Wochen zur Hand zu haben.

def sliceable_get()#

Ein Sliceable ist in Python alles, auf das mit variable[pos_1 : pos_2] zugegriffen werden kann, insbesondere Strings und Listen.

Schreiben Sie eine Funktion string_get(string, pos), die aus dem String string

  • das Zeichen an den Position pos zurückgibt, falls definiert

  • ein leerer String sonst.

Lösen Sie die Aufgabe mehrfach:

  • indem Sie die Länge von string mit pos vergleichen

  • indem Sie mit try - except einen IndexError abfangen

def string_get(string, pos):
    ...
# assert string_get("abc", 0) == "a"
# assert string_get("abc", 4) == ""

Verallgemeinern Sie die Funktion string_get(string, pos) so zu sliceable_get(sliceable, pos), dass sie mit Strings und Listen funktioniert. Falls das Sliceable zu kurz ist, soll entsprechend ein leerer String oder eine leere Liste zurückgegeben werden.

Leerzeichen enfernen: Verschiedene Lösungen!#

Aus einem String sollen alle Leerzeichen entfernt werden. Lösen Sie die Aufgabe mehrfach:

  • konventionell (und suboptimal) mit einer Schleife

  • mit split

  • mit re.split

  • mit einer List-Comprehension

(Unnötig zu sagen: Bei Ansätzen die zunächst eine Liste zurückgeben, muss man diese dann wieder zu einem String joinen.)

Satzzeichen entfernen mit re.split()#

In einem String sollen alle Satzzeichen (,;.:!?) entfernt werden. Lösen Sie die Aufgabe mit re.split.

String an Satzzeichen splitten#

Ein String soll nicht an Leerzeichen, sondern an Satzzeichen gesplittet werden. Lösen Sie die Aufgabe mit re.split.

zip()#

Mit Hilfe von zip soll eine Menge von Textzeilen (bis zur Länge der kürzesten Zeile) spaltenweise ausgegeben werden, Beispiel:

text_zeilen = [ "ABCD", "abcd", "12345678"]

text_spalten_kurz = [ ... ]
text_spalten_kurz
    
[Ellipsis]
# assert text_spalten_kurz == ['Aa1', 'Bb2', 'Cc3', 'Dd4']

Gleiche Aufgabe, aber jetzt bis zur Länge der längsten Zeile, z.B. mit der Funktion zip_longest().

import itertools

text_spalten_lang = [ ... ]
text_spalten_lang
[Ellipsis]
# assert text_spalten_lang == ['Aa1', 'Bb2', 'Cc3', 'Dd4', '__5', '__6', '__7', '__8']

Tabellen#

Tabellen werden in Python z.B. mit DataFrames aus der Bibliothek pandas vorgehalten.

Pandas selbst ist nicht Gegenstand einer allgemeinen Python-Einführung. Wir zeigen hier aber, wie man mit Pandas eine Excel- oder CSV-Datei einlesen und in Datenstrukturen transformieren kann, die wir bereits gut kennen und auch auswerten können.

Minimaler Beispiel-Datensatz: Tabelle, wer zuletzt mit auf der Familienfeier dabei war. Hobby ist ein Schlüssel für:

  • 1: an der frischen Luft

  • 2: drinnen

  • 3: im Auto

Download: party.csv

import pandas as pd
filename = "party.csv"
party_df = pd.read_csv(filename, 
                       delimiter=";", 
                       encoding="utf-8",
                       dtype= {'Hobby': str }
                      )
party_df
Nickname Party Körpergröße Gender Hobby
0 Jo 2022-05-30 175 m 2
1 Mary 2022-05-30 166 f 1

Die erste Zeile der CSV-Datei wird defaultmäßig als Spaltenkopf interpretiert. Natürlich kann man die Spaltennamen abfragen:

party_df.columns
Index(['Nickname', 'Party', 'Körpergröße', 'Gender', 'Hobby'], dtype='object')

Umwandeln in Python-native Datenstrukturen mit der Funktion

spaltenweise

# spaltenweise, dict of dicts
party_dict = pd.DataFrame.to_dict(party_df) # orient='dict'
party_dict
{'Nickname': {0: 'Jo', 1: 'Mary'},
 'Party': {0: '2022-05-30', 1: '2022-05-30'},
 'Körpergröße': {0: 175, 1: 166},
 'Gender': {0: 'm', 1: 'f'},
 'Hobby': {0: '2', 1: '1'}}
# spaltenweise, dict of lists
party_list = pd.DataFrame.to_dict(party_df, orient='list')
party_list
{'Nickname': ['Jo', 'Mary'],
 'Party': ['2022-05-30', '2022-05-30'],
 'Körpergröße': [175, 166],
 'Gender': ['m', 'f'],
 'Hobby': ['2', '1']}

zeilenweise

# zeilenweise, dict of dicts
party_index = pd.DataFrame.to_dict(party_df, orient='index')
party_index
{0: {'Nickname': 'Jo',
  'Party': '2022-05-30',
  'Körpergröße': 175,
  'Gender': 'm',
  'Hobby': '2'},
 1: {'Nickname': 'Mary',
  'Party': '2022-05-30',
  'Körpergröße': 166,
  'Gender': 'f',
  'Hobby': '1'}}
# zeilenweise, list of dichts
party_records = pd.DataFrame.to_dict(party_df, 'records')
party_records
[{'Nickname': 'Jo',
  'Party': '2022-05-30',
  'Körpergröße': 175,
  'Gender': 'm',
  'Hobby': '2'},
 {'Nickname': 'Mary',
  'Party': '2022-05-30',
  'Körpergröße': 166,
  'Gender': 'f',
  'Hobby': '1'}]

Aufgaben#

Für alle 4 Darstellungen zu lösen:

  • Liste aller Körpergrößen?

    • (und klar: Wenn man die Liste aller Körpergrößen hat: durchschnittliche Größe?)

  • Anzahl von Männern und Frauen?

  • Wie groß ist der größte Mann?

  • gruppieren nach Hobby-Kennziffer

Rekursion#

Berechnen Sie die Summe alle Würfe (rekursive Lösung).

wuerfel = [ 1,3,3,5,1,3,1,6,5,4]
def wuerfel_summe(w):
    if len(w) == 0:
        # Sonderfall, eigentlich undefiniert: Wir geben 0 zurück
        return 0 
    # w hat eine Länge von mindestens 1
    ergebnis = w[0]
    
    if len(w) == 1:
        # Rekursions-Abbruch
        return ergebnis
    else:
        # weiterer Aufruf erforderlich
        return ergebnis + wuerfel_summe(w[1:])

Aufgabe: Die Lösung haben Sie ja eben gelesen. Schließen Sie dieses Fenster, und codieren Sie diese (oder eine ähnliche) Lösung aus dem Kopf nach!

wuerfel_summe(wuerfel)
32

Häufigkeit jedes wurfes

Erstellen sie ein dict, in dem für jede gewüfelte Zahl angegeben ist, wie häufig sie vorkommt (rekursive Lösung).

Technik hier: Wir haben ein dict wd, das Stück für stück angefüllt wird.

def wuerfel_haeufigkeit(w, *, wd = {}): # wd ... wuerfel dictionary, w ... wuerfel-liste
    if len(w) == 0:
        return
    else:
        zahl = w[0]
        if zahl not in wd:
            wd[zahl] = 0
        wd[zahl] += 1
        if len(w) >= 2:
            wuerfel_haeufigkeit(w[1:], wd = wd)
    return wd
wuerfel_haeufigkeit(wuerfel)
{1: 3, 3: 3, 5: 2, 6: 1, 4: 1}

Aufgabe: Die Lösung haben Sie ja eben gelesen. Schließen Sie dieses Fenster, und codieren Sie diese (oder eine ähnliche) Lösung aus dem Kopf nach!

ng20_korpus_texte = [': \n: >> Please enlighten me.  How is omnipotence contradictory?\n: \n: >By definition, all that can occur in the universe is governed by the rules\n: >of nature. Thus god cannot break them. Anything that god does must be allowed\n: >in the rules somewhere. Therefore, omnipotence CANNOT exist! It contradicts\n: >the rules of nature.\n: \n: Obviously, an omnipotent god can change the rules.\n\nWhen you say, "By definition", what exactly is being defined;\ncertainly not omnipotence. You seem to be saying that the "rules of\nnature" are pre-existant somehow, that they not only define nature but\nactually cause it. If that\'s what you mean I\'d like to hear your\nfurther thoughts on the question.',
 "In <19APR199320262420@kelvin.jpl.nasa.gov> baalke@kelvin.jpl.nasa.gov \n\nSorry I think I missed a bit of info on this Transition Experiment. What is it?\n\nWill this mean a loss of data or will the Magellan transmit data later on ??\n\nBTW: When will NASA cut off the connection with Magellan?? Not that I am\nlooking forward to that day but I am just curious. I believe it had something\nto do with the funding from the goverment (or rather _NO_ funding :-)\n\nok that's it for now. See you guys around,\nJurriaan.\n "] 
ng20_korpus_texte
[': \n: >> Please enlighten me.  How is omnipotence contradictory?\n: \n: >By definition, all that can occur in the universe is governed by the rules\n: >of nature. Thus god cannot break them. Anything that god does must be allowed\n: >in the rules somewhere. Therefore, omnipotence CANNOT exist! It contradicts\n: >the rules of nature.\n: \n: Obviously, an omnipotent god can change the rules.\n\nWhen you say, "By definition", what exactly is being defined;\ncertainly not omnipotence. You seem to be saying that the "rules of\nnature" are pre-existant somehow, that they not only define nature but\nactually cause it. If that\'s what you mean I\'d like to hear your\nfurther thoughts on the question.',
 "In <19APR199320262420@kelvin.jpl.nasa.gov> baalke@kelvin.jpl.nasa.gov \n\nSorry I think I missed a bit of info on this Transition Experiment. What is it?\n\nWill this mean a loss of data or will the Magellan transmit data later on ??\n\nBTW: When will NASA cut off the connection with Magellan?? Not that I am\nlooking forward to that day but I am just curious. I believe it had something\nto do with the funding from the goverment (or rather _NO_ funding :-)\n\nok that's it for now. See you guys around,\nJurriaan.\n "]

Aufgabe: Wie kann man so etwas “cleanen”? Was will man cleanen?

  • alle Sonderzeichen, Interpunktionen etc. entfernen

  • auch Links wie z.B. <19APR199320262420@kelvin.jpl.nasa.gov> oder emails etc. entfernen?

Aufgaben (und später auch Lösungen) dazu: http://www.jbusse.de/dsci-txt/dsci-txt_2022-05-14.html#clean-string-string