dataframe - Sätze wortweise verändern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Taburkel
User
Beiträge: 5
Registriert: Montag 6. April 2020, 12:31

Moin,

ich bin Programmier- und Pythonanfänger und habe eine triviale Frage, auf die ich dennoch im www keine Antwort gefunden habe.
Ich muss Sätze vervielfältigen und dann wortweise verändern, etwa so:

Vorlage:
Der Junge ging in die Küche.
Die Frau löschte das Feuer.

Format nach Bearbeitung:
Der ----- ---- -- --- -----.
Der Junge ---- -- --- -----.
Der Junge ging -- --- -----.
etc.
Die ---- ------- --- -----.
Die Frau ------- --- -----.

(in der Sprachwissenschaft ein gebräuchliches experimentelles Set-Up, um zu untersuchen, wie Menschen Sätze verarbeiten.)

Ich habe das mal in Excel mit Macros gemacht. Erstmal: kopiere Satz 1 so oft, wie es Wörter gibt, danach in Zeile 1, ersetze alle Zellen ab Zelle 2 [bzw. bei Beginn mit 0 Zelle 1]. Bei Excel konnte ich die Zellen komfortabel ansteuern.

Wie mache ich das bei Python? Mit pandas? Oder welche Libraries/packages brauche ich?

(Ich arbeite auch einige Einsteigerbücher durch, aber wir müssen das möglichst schnell aufsetzen, und da wäre ein Hinweis hilfreich, wo ich anfangen muss zu suchen.)

Danke! Gruß Taburkel
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

So trivial ist die Aufgabe gar nicht, weil man ja noch Satzzeichen und andere Sonderzeichen beachten muß.
Die Frage ist, was der Input und was der gewünschte Output ist.

Immer wenn man vor so einer Aufgabe steht, muß man das Problem in kleinere Teilprobleme aufteilen, so lange bis man für das Subsubsubproblem weiß, wie man es lösen kann.
Unabhängig davon brauchst Du eine Funktion, die einen Satz bekommt und eine Liste mit verdeckten Sätzen zurück gibt.
Erster Schritt wäre, den Satz in Wörter zu unterteilen.
Dann brauchst Du eine weitere Funktion die in einem Wort Buchstaben in - umwandelt.
Wenn Du diese Teile hast, mußt Du nur noch mit einer Schleife von 1 bis Anzahl der Wörter durchgeben, und jeweils so viele Wörter im Klartext und den Rest versteckt ausgeben.
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Auf jeden Fall hat das nichts mit Pandas-DataFrames zu tun.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Taburkel
User
Beiträge: 5
Registriert: Montag 6. April 2020, 12:31

Danke für die Antworten! Bin fast am Ziel, aber nun habe ich doch noch ein kleines (?) Problem:

mein Code

Code: Alles auswählen

import re

f = open("Saetze.txt", "r")

saetze = f.readlines()

print(saetze, "\n\n")

for satz in saetze:
    satz_list = satz.split(" ")
    word_id = len(satz_list) - 1
            
    for i in range(len(satz_list)):
        satz_list[word_id] = re.sub(".", "-", satz_list[word_id])
        print(satz_list)
        word_id = word_id - 1
liest mir zeilenweise die Sätze aus dem File ein, macht die einzelnen Sätze zu Listen. Innerhalb einer Liste/eines Satzes wird nun zunächst das letzte Wort durch "----" ersetzt, der Satz dann ausgegeben, danach das vorletzte Wort etc.

Ich brauche es aber andersrum: Beim Umwandeln in "-" soll zunächst jedes Wort ersetzt werden, dann ausgeben/drucken, danach alles ab dem 2. Wort (Element 1), wieder ausgeben, dann alles ab dem 3. Wort, so dass über die Zeilen von oben nach unten letztlich wortweise der gesamte Satz erscheint.

--- ---- -----.
Der ---- -----.
Der Hund -----.

Ich brauche also den ursprünglichen Satz, den ich bei jedem Durchgang durch die Schleife etwas mehr ersetze, und war immer von der nächsten Zelle bis zum Ende. Etwa so:

Code: Alles auswählen

word_id = 0
satz_repl = []

for i in range(len(satz_list)):
        satz_repl[word_id:] = re.sub(".", "-", satz_list[word_id:])
        print(satz_repl)
        word_id = word_id + 1
Ich kriege aber eine Fehlermeldung, weil re.sub(".", "-", satz_list[word_id:]) einen String erwartet. Ich kann offenbar in einzelnem Element in der Liste alle Zeichen durch "-" ersetzen, aber nicht in allen Elementen von word_id bis zum Ende?

Sorry für die lange, letztlich vermutlich triviale Frage. Danke für einen Tipp!

Gruß Taburkel
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Dateien öffnet man mit dem with-Statement, dann werden sie auch wieder ordentlich geschlossen. Dann muß man noch das passende Encoding angeben, in dem die Textdatei gespeichert wurde, z.B. utf8:

Code: Alles auswählen

with open("Saetze.txt", "r", encoding='utf8') as file:
    sentences = file.readlines()
Um Dein Problem noch zu lösen, ist es am einfachsten, wenn Du eine Funktion definierst, die einen Satz bekommt und eine Anzahl an verdeckten Wörtern und den Ergebnissatz zurückliefert:

Code: Alles auswählen

def hide_words(words, number_of_hidden_words):
    # TODO: write the function
dann bräuchtest Du nur diese Funktion aufrufen entsprechend oft aufrufen:

Code: Alles auswählen

words = sentence.split()
for number_of_hidden_words in reversed(range(len(words)+1)):
    print(hide_words(words, number_of_hidden_words)
Wenn man jedes Zeichen (re: .) ersetzt, geht das einfacher ohne regulären Ausdruck, Du willst aber nur Buchstaben \w ersetzen.
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Habe das mal spasseshalber im Scheme-Dialekt Racket gelöst:

Code: Alles auswählen

#!/usr/bin/env racket
#lang racket

(call-with-input-file "test.txt"
  (lambda (port)
    (for ([sentence (in-lines port)])
      (let* ([words (string-split sentence)]
             [hidden-words (for/vector ([word words])
                             (regexp-replace* #px"\\p{L}" word "-"))])
        (for ([(word index) (in-indexed words)])
          (vector-set! hidden-words index word)
          (displayln (string-join (vector->list hidden-words))))))))
Ausgabe:

Code: Alles auswählen

Der ----- ---- -- --- -----.
Der Junge ---- -- --- -----.
Der Junge ging -- --- -----.
Der Junge ging in --- -----.
Der Junge ging in die -----.
Der Junge ging in die Küche.
Die ---- ------- --- -----.
Die Frau ------- --- -----.
Die Frau löschte --- -----.
Die Frau löschte das -----.
Die Frau löschte das Feuer.
Im Grund kann man in Python genau so vorgehen. Mit dem zusätzlichen Vorteil, dass man keine zwei Datentypen (Vektor, Liste in Racket) braucht, weil in Python die Liste alle benötigten Eigenschaften abdeckt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
nezzcarth
User
Beiträge: 1635
Registriert: Samstag 16. April 2011, 12:47

Taburkel hat geschrieben: Montag 6. April 2020, 14:43 (in der Sprachwissenschaft ein gebräuchliches experimentelles Set-Up, um zu untersuchen, wie Menschen Sätze verarbeiten.)
Weshalb möchtest du das denn in Python programmieren? Das klingt so, als würdest du die Sätze vorverarbeiten wollen, was eher ungewöhnlich wäre. Eigentlich führt man solche Experimente ja in spezieller Software aus, in deren Programmiersprache man das dann programmieren muss und wo das live abläuft. Oder soll das ein Skript für so ein Programm werden und das Programm versteht Python (z. B. OpenSesame oder Psychopy)?
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das ganze in Python:

Code: Alles auswählen

#!/usr/bin/env python3
import re


def main():
    with open("test.txt", encoding="utf-8") as sentences:
        for sentence in sentences:
            words = sentence.split()
            hidden_words = [re.sub(r"\w", "-", word) for word in words]
            for index, word in enumerate(words):
                hidden_words[index] = word
                print(" ".join(hidden_words))


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Taburkel
User
Beiträge: 5
Registriert: Montag 6. April 2020, 12:31

Moin moin,

ich war einige Zeit offline, hab gerade erst gesehen, dass __blackjack__ eine Lösung gepostet hat. Werd ich zeitnah ausprobieren, wenn die Kinder im Bett sind (oder aus dem Haus, also für die Ausbildung, haha).

Hatte mir trocken/theoretisch auch noch eine Lösung überlegt, bin nun ganz motiviert zu schauen, ob die in die richtige Richtung ging.

Vielen Dank!

@nezzcarth: Das ist ein cooler, weiterdenkender Kommentar gewesen (ich will nicht gönnerhaft klingen!). Danke! Wir benutzen dmdx, weil das für unsere Zwecke flexibler ist. Das braucht halt ein vorverarbeitetes rtf-file.

Grüße
Taburkel
Antworten