Seite 2 von 2

Verfasst: Montag 9. April 2007, 00:45
von Leonidas
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 :)
Einige ersetzen ja ``ß`` mit ``sz``.

Verfasst: Montag 9. April 2007, 00:47
von EnTeQuAk
Einige ersetzen ja ``ß`` mit ``sz``.
Wie dem auch sei ;) Ich würde zu den Deutschen Umlauten stehen. Wir haben die und können sie auch verwenden :)

MfG EnTeQuAk

Verfasst: Montag 9. April 2007, 01:29
von M***
Wobei, was mir auffällt. Warum `ß` in `ss` umwandeln?
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.
(btw: was bezweckst du mit dem ersetzen?)
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.
Vigenère-Verschlüsselung

Verfasst: Montag 9. April 2007, 09:42
von rayo
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

Verfasst: Montag 9. April 2007, 09:56
von mitsuhiko
Marc hat geschrieben:
Wobei, was mir auffällt. Warum `ß` in `ss` umwandeln?
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.
1.) tauch im deutsch alpabeth auf
2.) sollte das so normalisiert werden, wie das auch der sender macht. sonst machst du die statistiken kaputt.

Verfasst: Montag 9. April 2007, 10:19
von birkenfeld
blackbird hat geschrieben: 1.) tauch im deutsch alpabeth auf
Heute ist Nonkonformistentag, hm? :twisted:

Verfasst: Montag 9. April 2007, 10:38
von BlackJack
@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:

Code: Alles auswählen

numchar=[]
numchartotal=0
for char in char2count:
    tmp = text.count(char)
    numchar.append(tmp)
    numchartotal += tmp
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.

Code: Alles auswählen

numchar = [text.count(char) for char in char2count]
numchar = map(text.count, char2count)
numchartotal = sum(numchar)
Für den Vergleich der Längen der beiden Listen `numchar` und `char2count` böte sich ein ``assert`` anstelle des ``if``/``else`` an.

Verfasst: Montag 9. April 2007, 11:17
von DaSch
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,"%"

Verfasst: Montag 9. April 2007, 12:41
von EnTeQuAk
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

Verfasst: Montag 9. April 2007, 12:47
von DaSch
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

Verfasst: Montag 9. April 2007, 13:36
von M***
@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.
Das "_dt" kann ich weglassen, stimmt wohl.

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}
Sieht bei der Ausgabe verwirrend und nicht schön aus. Im Python-Wiki habe ich mir die Lösung angeguckt, da wird empfohlen, mit Strings zu arbeiten.

Verfasst: Montag 9. April 2007, 13:42
von DaSch
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

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()

Verfasst: Montag 9. April 2007, 14:32
von M***
benutz doch einfach Sttringformatierung für die Ausgabe
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.

Verfasst: Montag 9. April 2007, 16:36
von BlackJack
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:

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'
Man kann also beides haben: Fliesskommazahlen mit denen sich rechnen lässt und eine Darstellung als Zeichenkette, die die Unvollkommenheit von Fliesskommazahlen versteckt.

Verfasst: Montag 9. April 2007, 17:16
von M***
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:

Code: Alles auswählen

>>> f = {'a': '%s' % 6.51}
>>> f
{'a': '6.51'}
>>> f['a']
'6.51'
Was ist mein Denkfehler?

Verfasst: Montag 9. April 2007, 18:28
von BlackJack
Wenn Du die Zahl schon im Dictionary als Zeichenkette formatierst, kannst Du natürlich gleich Zeichenketten schreiben.

Verfasst: Montag 9. April 2007, 18:36
von EyDu
Marc hat geschrieben:Was ist mein Denkfehler?
Am sinnvollsten ist, wenn du das Dictionary mit den Häufigkeiten mit konkreten Zahlen füllst, da du wahrscheinlich irgendwann mal mit diesen etwas berechnen musst und dir das Konvertieren von einem String in eine Fließkommazahl sprarst:

Code: Alles auswählen

f = {"a":6.51}
Wenn du den Wert als String haben möchtest, verwendetst du dann einfach immer den %-Operator mit entsprechenden Formatierungsangeben (wie ja schon von BlackJack angegeben):

Code: Alles auswählen

in_string = "Hier noch ein wenig Text: %5.2f. Und hier auch noch ein wenig" % f["a"]

Verfasst: Montag 9. April 2007, 21:05
von M***
Das hatte ich missverstanden. Es hat jetzt funktioniert. Danke.