Seite 1 von 1

Anzahl gleicher Worte in einem Text

Verfasst: Mittwoch 12. November 2008, 12:16
von Python-Anfängerin
Ich habe einen Text eingelesen und diesen nun als Liste aus Strings vorliegen. Jetzt hätte ich gerne die Verteilung der Wörter, also: "und" kommt viermal vor usw. Ich habe ein Beispielprogramm, wo sowas ähnliches mit einem Dictionary gemacht wird, kann das aber nicht übertragen, weil da die Länge des Strings, der gezählt werden soll vorgegeben ist (string=[i:i+2]). Gibt es vielleicht eine Schreibweise, dass der String bis zum nächsten Leerzeichen gehen soll? Das Ganze geht dann über eine for-Schleife mit if/else, aber ich häng jetzt echt an diesem (vlt. regulären?) Ausdruck.

Verfasst: Mittwoch 12. November 2008, 12:19
von Fabian Kochem
Benutz doch einfach .split():

Code: Alles auswählen

kw = {}
arr = text.split(" ")
for item in arr:
    # dem dictionary hinzufügen bzw. hochzählen

Verfasst: Mittwoch 12. November 2008, 12:32
von Python-Anfängerin
Oh Mann... Manchmal steht man echt auf dem Schlauch... Danke für die schnelle - und hilfreiche - Antwort!

Verfasst: Mittwoch 12. November 2008, 14:19
von derdon
Und warum nicht einfach die count-Methode von Strings? (Text aus dem Vim-Artikel aus dem Python-Wiki)

Code: Alles auswählen

In [21]: text = u"""Vim ist der bekannteste Klon des eines der ältesten Editoren für Unices, vi.
Von elvis, nvi, WinVi und seinem Urvater vi unterscheidet er sich dadurch, dass er viele Verbesserungen
aufweist. Durch seinen Umfang und seine etwas andere Art ist er für den Anfänger oft sehr verwirrend,
da seine Bedienung sich stark von normalen Editoren wie etwa SciTE unterscheidet. Diese Seite will
jedoch nicht die Bediehnung von Vim lehren, denn dazu gibt es genügend andere Informationen im Internet,
wie auch den bei Vim mitgelieferten vimtutor. Vielmehr möchte diese Kurzanleitung aufzeigen, wie man Vim
dazu einsetzen kann effizienter in Python zu programmieren."""

In [22]: text.count("vi")
Out[22]: 6

In [23]: text.split(" ").count("vi")
Out[23]: 1

Verfasst: Mittwoch 12. November 2008, 14:22
von cofi
derdon hat geschrieben: (Text aus dem Vim-Artikel aus dem Python-Wiki)
Uhh sublime Propaganda :) Wobei sie natürlich durchaus gerechtfertigt ist :)

Verfasst: Mittwoch 12. November 2008, 14:56
von BlackJack
@derdon: "Einfach" die `count()`-Methode ist eine schlechte Idee weil ja nicht nur ein Wort gesucht werden soll, sondern ein Histogramm aller im Text vorkommenden Worte erstellt werden soll.

Ausserdem zählt Dein Ansatz auch alle Worte mit, in denen die Buchstabenfolge 'vi' vorkommt, und nicht nur 'vi' als eigenes Wort.

@Python-Anfängerin: Ich würde als Vorverarbeitung den Text in Kleinbuchstaben umwandeln und dann mit der `translate()`-Methode alles ausser Buchstaben durch Leerzeichen ersetzen.

Verfasst: Mittwoch 12. November 2008, 15:19
von derdon
BlackJack hat geschrieben:@derdon: "Einfach" die `count()`-Methode ist eine schlechte Idee weil ja nicht nur ein Wort gesucht werden soll, sondern ein Histogramm aller im Text vorkommenden Worte erstellt werden soll.

Ausserdem zählt Dein Ansatz auch alle Worte mit, in denen die Buchstabenfolge 'vi' vorkommt, und nicht nur 'vi' als eigenes Wort.
Ich hab doch extra zwei verschiedene Aufrufe gezeigt, damit man sehen kann, dass einmal nach "vi" irgendwo im Text gesucht wird und einmal nach "vi" als Wort.

Code: Alles auswählen

In [61]: text.split(" ").index("vi")
Out[61]: 20

In [62]: text.split(" ")[20]
Out[62]: u'vi'
Edit: Typo

Verfasst: Mittwoch 12. November 2008, 15:37
von DasIch
@derdon Wie willst du damit sowas nachbauen?

Code: Alles auswählen

def count(s):
    counted = {}
    for word in s.split(' '):
        if word in counted:
            counted[word] += 1
        else:
            counted[word] = 1
    return counted
Verstanden wieso count keine gute Idee ist? ;)

Verfasst: Mittwoch 12. November 2008, 15:54
von helduel
Moin,

[mod]collections#collections.defaultdict[/mod] ist hier hilfreich, wenn man als Factory int nimmt.

Gruß,
Manuel

Verfasst: Mittwoch 12. November 2008, 15:59
von derdon
@DasIch: sehr cooler Schnipsel! 8)

Verfasst: Donnerstag 13. November 2008, 00:09
von ichbinsisyphos
set() ist praktisch für histogramme. Damit kommen alle Einträge nur einmal vor.

* Eingelesen wird wahrscheinlich zeilenweise.
* Die Zeilen an Leerzeichen splitten und an neue Liste anhängen mit extend().
* Bereinigen, Satzzeichen raus, vielleicht Groß- in Kleinbuchstaben umwandeln, etc.
* Neue Liste ohne mehrfache Einträge mit list(set())
* Zählen wie oft jeder Eintrag im set in der Wörterliste vorkommt mit count().


Ich hab da noch eine blöde Frage: Wie liest man unicode-Text richtig ein?

p.s.: Das Wiki enthält eine Rechtschreibfehler: "Bediehnung".

Verfasst: Donnerstag 13. November 2008, 09:11
von mkesper
ichbinsisyphos hat geschrieben:Ich hab da noch eine blöde Frage: Wie liest man unicode-Text richtig ein?
Schau mal ob dich [wiki]Von Umlauten, Unicode und Encodings[/wiki] weiterbringt.
ichbinsisyphos hat geschrieben:p.s.: Das Wiki enthält eine Rechtschreibfehler: "Bediehnung".
Dann melde dich doch einfach an und verbessere ihn. 8)

Verfasst: Donnerstag 13. November 2008, 09:25
von Leonidas
mkallas hat geschrieben:
ichbinsisyphos hat geschrieben:p.s.: Das Wiki enthält eine Rechtschreibfehler: "Bediehnung".
Dann melde dich doch einfach an und verbessere ihn. 8)
Man braucht sich nichtmal anzumelden.

Verfasst: Donnerstag 13. November 2008, 09:34
von BlackJack
@ichbinsisyphos: `set()` ist total unpraktisch für Histogramme eben gerade weil jedes Wort nur einmal drin vorkommen kann, ohne die Information *wie oft*. Ausserdem haben `set()`\s keine `count()`-Methode. Macht ja auch keinen Sinn, die könnte ja eh' nur 0 oder 1 liefern, und dafür kann man schon ``in`` verwenden.

Falls Du `str.count()` meintest: Überleg Dir doch mal was für besch*** Laufzeit der Algorithmus dadurch bekommt. Und da hat man wieder das bereits demonstrierte Problem, dass auch Treffer gezählt werden, die gar keine eigenständigen Worte sind.

Verfasst: Donnerstag 13. November 2008, 12:07
von ichbinsisyphos
BlackJack hat geschrieben:@ichbinsisyphos: `set()` ist total unpraktisch für Histogramme eben gerade weil jedes Wort nur einmal drin vorkommen kann, ohne die Information *wie oft*. Ausserdem haben `set()`\s keine `count()`-Methode. Macht ja auch keinen Sinn, die könnte ja eh' nur 0 oder 1 liefern, und dafür kann man schon ``in`` verwenden.

Falls Du `str.count()` meintest: Überleg Dir doch mal was für besch*** Laufzeit der Algorithmus dadurch bekommt. Und da hat man wieder das bereits demonstrierte Problem, dass auch Treffer gezählt werden, die gar keine eigenständigen Worte sind.
Aus dem set wird wieder eine Liste gemacht, die dann die Suchbegriffe enthält, gesucht selbst wird in der alten Liste.

Angenommen die Wörter sind mal bereinigt in einer Liste "woerter":

Code: Alles auswählen

woerterset = list(set(woerter))

histogram=[]
for i in woerterset:
    histogram.append([woerter.count(i), i])
Ich mach das inzwischen immer wenn ich keine mehrfachen Einträge will.

Die list(set())-Umwandlung wird die Laufzeit kaum beeinflussen, aber das Suchen in sehr langen Listen wird ineffizient, vielleicht sollt man gleich mit dicts arbeiten.

Verfasst: Donnerstag 13. November 2008, 13:53
von helduel
ichbinsisyphos hat geschrieben:Die list(set())-Umwandlung wird die Laufzeit kaum beeinflussen, aber das Suchen in sehr langen Listen wird ineffizient, vielleicht sollt man gleich mit dicts arbeiten.
Mein Vorschlag:

Code: Alles auswählen

from collections import defaultdict

histogram = defaultdict(int)
for word in words:
    histogram[word] += 1

print histogram
Gruß,
Manuel