Programm für Textanalyse
Also ich hab jetzt einfach mal so weil ich nix besseres zu tun hatte auch mal ein Prog geschrieben.
Wie findet ihr das?
Ich hab noch die Möglichkeit eingebaut einen eigenen String anzugeben nach dem Gezählt wird und dann noch die Datei nicht vorher in kleinbuchstaben zu konvertieren.
Wie findet ihr das?
Ich hab noch die Möglichkeit eingebaut einen eigenen String anzugeben nach dem Gezählt wird und dann noch die Datei nicht vorher in kleinbuchstaben zu konvertieren.
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: utf-8 -*-
import string
import sys
lower=True
if len(sys.argv) == 1:
print "Bitte eine Datei zum einlesen angeben"
if len(sys.argv) >= 2:
path = sys.argv[1]
charpath=-1
try:
daten = file (path,'r')
except:
print "Fehler beim Daten einlesen #000"
text = daten.read()
daten.close()
if len(sys.argv) >= 3:
charpath = sys.argv[1]
try:
chardaten = file (charpath,'r')
except:
print "Fehler beim Daten einlesen #001"
chartext = chardaten.read()
chardaten.close()
if len(sys.argv) >= 4:
if sys.argv[3]=="-l":
lower=False
else:
print "Falsches Argument angegeben"
if lower:
text = string.lower(text)
numworte=len(text.split())
if charpath!=-1:
char2count=list(chartext)
else:
char2count=list("abcdefghijklmnopqrstuvwxyz")
numchar=[]
numchartota=0
for i in range(len(char2count)):
char_tmp=char2count[i]
num_tmp=text.count(char_tmp)
numchartota+=num_tmp
numchar.append(num_tmp)
if len(numchar)!=len(char2count):
print "Fehler beim Zeichenzählen #002"
else:
print "Anzahl der Worte:",numworte
print "Anzahl der Buchstaben:",numchartota
print "Durchschnittliche Anzahl der Buchstaben pro Wort:",numchartota/numworte
print "Anteile der Zeichen"
for i in range(len(char2count)):
char_tmp=char2count[i]
num_tmp=float(numchar[i])
numchartota=float(numchartota)
proz=(num_tmp/numchartota)*100
print "Der Anteil von",char_tmp,"ist","%.2f" % proz,"%"
Beim groben drüber schauen, sind mir ein paar Dinge schonmal aufgefallen.
Einmal: schaue dir mal bitte das Python-Modul optparse an. Das vereinfacht das parsen von Komandozeilen-Argumenten.
Weiterhin:
Ist nicht schön. Es ist nicht gut, gleich sämtliche Exceptions abzufangen. Fange nur die Exception ab, die du erwartest. So bleiben andere Bugs/Fehler nicht unbemerkt.
Die Fehlermeldung z.B. bringt nichts, sagt absolut gar nichts aus. Python hat schon so nen schönes Traceback-System
Ist ebenso wenig schön, wie auch veraltert.
MfG EnTeQuAk
Einmal: schaue dir mal bitte das Python-Modul optparse an. Das vereinfacht das parsen von Komandozeilen-Argumenten.
Weiterhin:
Code: Alles auswählen
try:
daten = file(path,'r')
except:
print "Fehler beim Daten einlesen #000"
Die Fehlermeldung z.B. bringt nichts, sagt absolut gar nichts aus. Python hat schon so nen schönes Traceback-System
Code: Alles auswählen
try:
daten = file(path,'r')
except IOError, err:
print 'Fehler beim einlesen von "%s":\n%s' % (err.filename, err)
Code: Alles auswählen
text = string.lower(text)
Code: Alles auswählen
text = text.lower()
Ich würde gerne direkt nachdem ich die text.txt eingelesen habe die Umlaute umwandeln (ä -> ae, ö -> oe, ü -> ue, ß -> ss).
Kann ich da mit chr() und ord() arbeiten? Warscheinlich nicht.^^ Wie wäre eine einfache Lösung?
Danke.
Kann ich da mit chr() und ord() arbeiten? Warscheinlich nicht.^^ Wie wäre eine einfache Lösung?
Danke.
Bin mir nicht so sicher. Also entweder, du nutzt stures 'text.replace()' oder machst das so:
Einfach jeden Buchstaben, den du ersetzt haben magst eintragen
Wobei, was mir auffällt. Warum `ß` in `ss` umwandeln? Das macht den ganzen Text nicht mehr so gaaanz Rechtschreibtechnisch richtig. Aber na ja wollts nur sagen
(btw: was bezweckst du mit dem ersetzen?)
MfG EnTeQuAk
Code: Alles auswählen
def replace_chars(text):
chars = {
'ä': 'ae', 'Ä': 'Ae',
'ü': 'ue', 'Ü': 'Ue',
'ö': 'oe', 'Ö': 'Oe',
'ß': 'ss',
}
for char in chars:
if char in text:
text = text.replace(char, chars[char])
return text
Wobei, was mir auffällt. Warum `ß` in `ss` umwandeln? Das macht den ganzen Text nicht mehr so gaaanz Rechtschreibtechnisch richtig. Aber na ja wollts nur sagen
(btw: was bezweckst du mit dem ersetzen?)
MfG EnTeQuAk
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Einige ersetzen ja ``ß`` mit ``sz``.EnTeQuAk hat geschrieben:Wobei, was mir auffällt. Warum `ß` in `ss` umwandeln? Das macht den ganzen Text nicht mehr so gaaanz Rechtschreibtechnisch richtig. Aber na ja wollts nur sagen
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Wie dem auch sei Ich würde zu den Deutschen Umlauten stehen. Wir haben die und können sie auch verwendenEinige ersetzen ja ``ß`` mit ``sz``.
MfG EnTeQuAk
Bei einer Häufigkeitsanalyse kann ich keine Umlaute gebrauchen, weil diese nicht direkt im Alphabet auftauchen. Ob ich "ß" ignoriere oder in "ss" umwandle muss ich noch sehen.Wobei, was mir auffällt. Warum `ß` in `ss` umwandeln?
Falls du die Verschlüsselung Vigenère kennst und weißt, wie man diese bricht, dann kannst du nachvollziehen, warum ich "ä", "ö", "ü" und "ß" umwandeln möchte.(btw: was bezweckst du mit dem ersetzen?)
Vigenère-Verschlüsselung
-
- User
- Beiträge: 773
- Registriert: Mittwoch 5. November 2003, 18:06
- Wohnort: Schweiz
- Kontaktdaten:
Da müsstest du zuerst wissen ob er wirklich in Deutschland die Analyse macht. Bei uns in der Schweiz gibts dieses komische ß gar nicht (musste es vom vorherigen Post kopieren, gibt keine Taste dafür ) bei uns wird nur ss geschrieben.
Gruss
Gruss
-
- User
- Beiträge: 1790
- Registriert: Donnerstag 28. Oktober 2004, 16:33
- Wohnort: Graz, Steiermark - Österreich
- Kontaktdaten:
1.) tauch im deutsch alpabeth aufMarc hat geschrieben:Bei einer Häufigkeitsanalyse kann ich keine Umlaute gebrauchen, weil diese nicht direkt im Alphabet auftauchen. Ob ich "ß" ignoriere oder in "ss" umwandle muss ich noch sehen.Wobei, was mir auffällt. Warum `ß` in `ss` umwandeln?
2.) sollte das so normalisiert werden, wie das auch der sender macht. sonst machst du die statistiken kaputt.
TUFKAB – the user formerly known as blackbird
- birkenfeld
- Python-Forum Veteran
- Beiträge: 1603
- Registriert: Montag 20. März 2006, 15:29
- Wohnort: Die aufstrebende Universitätsstadt bei München
Heute ist Nonkonformistentag, hm?blackbird hat geschrieben: 1.) tauch im deutsch alpabeth auf
@Marc: Lass doch bei den Schlüsseln in dem Dictionary mit der Häufigkeitsverteilung einfach den Postfix '_dt' weg. Und auch wenn das Dictionary nur zur Anzeige dient, hätte ich die Werte als Fliesskommazahlen eingetragen. Falls man doch mal irgendwann damit rechnen will. Zum Beispiel wenn man die Abweichung eines analysierten Textes von der typischen Häufigkeit ausrechnen möchte oder so.
@DaSch: Stilistisch sind in dem Quelltext für meinen Geschmack zu wenige Leerzeichen und -zeilen enthalten. Es "klebt" alles so zusammen. Nicht nur Leerzeilen könnten ein wenig Struktur in das Programm bringen, es ist auch so linear runtergeschrieben. Man könnte es in Funktionen aufteilen.
Die Kommandozeilenschnittstelle sollte dokumentiert werden. Wenn ich das richtig sehe ist die nicht konsistent. Das das erste Argument je nach Anzahl der übergebenen Argumente etwas anderes bedeutet, ist nicht so schön.
Einem Namen eine -1 zuzuweisen, wenn er als "unbekannt" oder "nicht gesetzt" gelten soll, wie bei `charpath`, ist ziemlich C-like. In Python nimmt man dafür normalerweise `None`.
Über ``except`` wurde ja schon etwas gesagt. In dieser Form gibt's im Fehlerfall gleich danach eine Ausnahme: Wenn die Datei nicht geöffnet werden konnte, dann schlägt natürlich der Aufruf von `read()` fehl.
Bei `numchartota` fehlt irgendwie ein 'l'.
Die ``for``-Schleifen sind umständlich und nicht "pythonisch". Wenn man ``for i in range(len(something)):`` schreibt, kann man in 99,9% der Fälle gleich über `something` iterieren ohne den Umweg über einen Index.
Die erste Schleife sähe dann so aus:
Python bietet aber viel ausdruckstärkere Konstrukte und Funktionen an, die oft "detaillierte" Schleifen überflüssig machen. Die Liste könnte man zum Beispiel mit einer "list comprehension" oder `map()` erstellen und die Gesamtsumme dann einfach mit `sum()` ermitteln.
Für den Vergleich der Längen der beiden Listen `numchar` und `char2count` böte sich ein ``assert`` anstelle des ``if``/``else`` an.
@DaSch: Stilistisch sind in dem Quelltext für meinen Geschmack zu wenige Leerzeichen und -zeilen enthalten. Es "klebt" alles so zusammen. Nicht nur Leerzeilen könnten ein wenig Struktur in das Programm bringen, es ist auch so linear runtergeschrieben. Man könnte es in Funktionen aufteilen.
Die Kommandozeilenschnittstelle sollte dokumentiert werden. Wenn ich das richtig sehe ist die nicht konsistent. Das das erste Argument je nach Anzahl der übergebenen Argumente etwas anderes bedeutet, ist nicht so schön.
Einem Namen eine -1 zuzuweisen, wenn er als "unbekannt" oder "nicht gesetzt" gelten soll, wie bei `charpath`, ist ziemlich C-like. In Python nimmt man dafür normalerweise `None`.
Über ``except`` wurde ja schon etwas gesagt. In dieser Form gibt's im Fehlerfall gleich danach eine Ausnahme: Wenn die Datei nicht geöffnet werden konnte, dann schlägt natürlich der Aufruf von `read()` fehl.
Bei `numchartota` fehlt irgendwie ein 'l'.
Die ``for``-Schleifen sind umständlich und nicht "pythonisch". Wenn man ``for i in range(len(something)):`` schreibt, kann man in 99,9% der Fälle gleich über `something` iterieren ohne den Umweg über einen Index.
Die erste Schleife sähe dann so aus:
Code: Alles auswählen
numchar=[]
numchartotal=0
for char in char2count:
tmp = text.count(char)
numchar.append(tmp)
numchartotal += tmp
Code: Alles auswählen
numchar = [text.count(char) for char in char2count]
numchar = map(text.count, char2count)
numchartotal = sum(numchar)
Also erstmal danke für eure Tips ich habs jetzt ein wenig umgebaut und noch ein paar Fetures hinzugefügt
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: utf-8 -*-
import optparse
parser = optparse.OptionParser()
parser.set_usage("%prog [options] File")
parser._add_version_option()
parser.version="%prog 0.1"
parser.add_option("-c","--case-sensitive",action="store_false", dest="lower",default=True,help="don't convert Letters to lowercase")
parser.add_option("-p","--percentage",action="store_true", dest="percentage",default=False,help="Show Percentage of default Characters")
parser.add_option("-P","--Percentage",action="store", type="string", dest="charcount",help="Show Percentage of charactres spezified in File",metavar="charfile")
(options, args) = parser.parse_args()
lower = options.lower
percentage = options.percentage
if len(args)>0:
try:
daten = file (args[0],'r')
text = daten.read()
daten.close()
except IOError, err:
print 'Error when reading File "%s":\n\t%s' % (err.filename, err)
parser.exit()
else:
parser.print_help()
parser.exit()
if options.charcount is not None:
try:
chardaten = file (options.charcount,'r')
chartext = chardaten.read()
chardaten.close()
char2count=list(chartext)
except IOError, err:
print 'Error when reading File "%s":\n\t%s' % (err.filename, err)
parser.exit()
elif lower:
char2count=list("abcdefghijklmnopqrstuvwxyz")
else:
char2count=list("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz")
if lower:
text = text.lower()
numworte=len(text.split())
numchar = [text.count(char) for char in char2count]
numchar = map(text.count, char2count)
numchartotal = sum(numchar)
if len(numchar)!=len(char2count):
print "Error in CharCount"
else:
print "Anzahl der Worte:",numworte
print "Anzahl der Buchstaben:",numchartotal
print "Durchschnittliche Anzahl der Buchstaben pro Wort:",numchartotal/numworte
if percentage:
print "Anteile der Zeichen"
for i in range(len(char2count)):
char_tmp=char2count[i]
num_tmp=float(numchar[i])
numchartotal=float(numchartotal)
proz=(num_tmp/numchartotal)*100
print "Der Anteil von",char_tmp,"ist","%5.2f" % proz,"%"
So. Ich habe mich einfach mal rangemacht, um dir zu zeigen, wie es mit Funktionen ausschauen könnte.
Ich habe einige Sachen entfernt, da ich sie für unnötig hielt /sie sich überschnitten haben. Das Script ist jetzt ein wenig läger, lässt sich nun aber, finde ich besser überblicken.
Hier ist es: http://paste.pocoo.org/show/1361/
Ich hoffe, alles umgesetzt zu haben
MfG EnTeQuAk
Ich habe einige Sachen entfernt, da ich sie für unnötig hielt /sie sich überschnitten haben. Das Script ist jetzt ein wenig läger, lässt sich nun aber, finde ich besser überblicken.
Hier ist es: http://paste.pocoo.org/show/1361/
Ich hoffe, alles umgesetzt zu haben
MfG EnTeQuAk
also das mit der Option -c funktioniert irgendwie net
ich wollte des jetzt auch mal mit funktionen machen, dein Ansatz ist schon ganz gut denk ich
danke schonmal dafür
ich wollte des jetzt auch mal mit funktionen machen, dein Ansatz ist schon ganz gut denk ich
danke schonmal dafür
Das "_dt" kann ich weglassen, stimmt wohl.@Marc: Lass doch bei den Schlüsseln in dem Dictionary mit der Häufigkeitsverteilung einfach den Postfix '_dt' weg. Und auch wenn das Dictionary nur zur Anzeige dient, hätte ich die Werte als Fliesskommazahlen eingetragen. Falls man doch mal irgendwann damit rechnen will. Zum Beispiel wenn man die Abweichung eines analysierten Textes von der typischen Häufigkeit ausrechnen möchte oder so.
Ich wollte die Zahlen als Fließkommazahl schreiben, aber dann passiert folgendes bekanntes Problem:
Code: Alles auswählen
>>> f = {'a': 6.51}
>>> f
{'a': 6.5099999999999998}
benutz doch einfach Sttringformatierung für die Ausgabe
Ich hab jetzt meine Version auch nochmal ein wenig überarbeitet und das alles mit funktionen etwas übersichtlicher gemacht
Ich hab jetzt meine Version auch nochmal ein wenig überarbeitet und das alles mit funktionen etwas übersichtlicher gemacht
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: utf-8 -*-
import optparse
import time
def main():
start=time.time()
options,args,parser=parsing()
text,char2count=fileopen(options,args,parser)
if options.lower:
text = text.lower()
numworte,numchar,numchartotal=count(text,char2count)
output(numworte,numchar,numchartotal,char2count,options)
if options.test:
test(start)
def parsing():
parser = optparse.OptionParser()
parser.set_usage("%prog [options] File")
parser._add_version_option()
parser.version="%prog 0.1"
parser.add_option("-c","--case-sensitive",action="store_false", dest="lower",default=True,help="don't convert Letters to lowercase")
parser.add_option("-p","--percentage",action="store_true", dest="percentage",default=False,help="Show Percentage of default Characters")
parser.add_option("-P","--Percentage",action="store", type="string", dest="charcount",help="Show Percentage of charactres spezified in File",metavar="charfile")
parser.add_option("-s","--special",action="store_true", dest="special",default=False,help="Analyse special charactres")
parser.add_option("-t","--test",action="store_true", dest="test",default=False,help="Make a Speedtest")
(options, args) = parser.parse_args()
return options,args,parser
def fileopen(options,args,parser):
if len(args)>0:
try:
daten = file (args[0],'r')
text = daten.read()
daten.close()
except IOError, err:
print 'Error when reading File "%s":\n\t%s' % (err.filename, err)
parser.exit()
else:
parser.print_help()
parser.exit()
if options.charcount is not None:
try:
chardaten = file (options.charcount,'r')
chartext = chardaten.read()
chardaten.close()
char2count=list(chartext)
except IOError, err:
print 'Error when reading File "%s":\n\t%s' % (err.filename, err)
parser.exit()
else:
char2count=set(options)
return text,char2count
def set(options):
if options.lower:
char2count=list("abcdefghijklmnopqrstuvwxyz")
else:
char2count=list("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz")
if options.special:
char2count.append("--")
char2count.extend(" ")
spezial_char=".,;.´:-_#'+*~!?§$€%&()[]{}=\/|<>"
char2count.extend(spezial_char)
return char2count
def count (text,char2count):
numworte=len(text.split())
numchar = [text.count(char) for char in char2count]
numchar = map(text.count, char2count)
numchartotal = sum(numchar)
return numworte,numchar,numchartotal
def output(numworte,numchar,numchartotal,char2count,options):
percentage = options.percentage
print "Anzahl der Worte:",numworte
print "Anzahl der Buchstaben:",numchartotal
print "Durchschnittliche Anzahl der Buchstaben pro Wort:",numchartotal/numworte
if percentage:
print "Anteile der Zeichen"
for i in range(len(char2count)):
char_tmp=char2count[i]
if char_tmp != "--":
num_tmp=float(numchar[i])
numchartotal=float(numchartotal)
proz=(num_tmp/numchartotal)*100
print "Der Anteil von",char_tmp,"ist","%5.2f" % proz,"% Absolut:",numchar[i]
else:
print "------------------------------------------------------"
def test(start):
print "Runtime: %.4f"%(time.time()-start),"Sekunden"
print "Cputime: %.4f"%(time.clock()),"Sekunden"
if __name__ == '__main__':
main()
Habe ich in meinem Programm ja benutzt. BlackJack meinte dann, ich solle Fließkommazahlen verwenden, um mit damit ggf. noch rechnen zu können. Darauf habe ich dann im Beitrag über deinem geantwortet.benutz doch einfach Sttringformatierung für die Ausgabe
Mit Stringformatierung war der ``%`` Operator gemeint und wenn man eine Fliesskommazahl als Zeichenkette oder als Fliesskommazahl formatiert, dann taucht das Problem nicht auf weil entsprechend gerundet wird:
Man kann also beides haben: Fliesskommazahlen mit denen sich rechnen lässt und eine Darstellung als Zeichenkette, die die Unvollkommenheit von Fliesskommazahlen versteckt.
Code: Alles auswählen
In [42]: 6.51
Out[42]: 6.5099999999999998
In [43]: '%s' % 6.51
Out[43]: '6.51'
In [44]: '%f' % 6.51
Out[44]: '6.510000'
In [45]: '%5.2f' % 6.51
Out[45]: ' 6.51'
Ich verstehe nicht, wieso ich dann beides habe. Die Ausgabe ist doch ein String und keine Fließkommazahl. Wenn ich den Eintrag aus dem Dictionary aufrufe, dann wird doch der String benutzt:
Was ist mein Denkfehler?
Code: Alles auswählen
>>> f = {'a': '%s' % 6.51}
>>> f
{'a': '6.51'}
>>> f['a']
'6.51'