Erstellen einer Statistik

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.
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

Ich möchte ein Programm schreiben, dass mir eine Statistik ueber die Häufigkeit des Auftretens von bestimmten Einzelfällen aus ziemlich vielen Fällen gibt. Ich habe erst einmal über die Version nachgedacht, für jeden möglichen Fall, den ich einfach mal mit i bezeichne, eine oder zwei eigene Variable einzuführen. Dann kann ich mein Programm einfach alle möglichen Fälle durchprobieren lassen und jeweils mit einer Reihe von if / elif / else durchprobieren lassen, welcher Fall nun eingetreten ist. Dann setze ich einfach den entsprechenden Wert der Variablen eins hoch, und zum Schluss addiere ich alle Variablen, um auf die gesamte Fallzahl zu kommen, und setze jeweils eine zweite Variable auf den Quotienten von erster Variablen und Fallzahl, und dann gebe ich alle diese jeweils zweite Variable als Tabelle aus. Also so ähnlich wie:

Code: Alles auswählen

for i in range(1,151);
  if i == 1:
    q1 = p1+1
  elif i == 2:
    q2 = p2+1
  ...
  else 
    q150 = q150+1
Nur: Das macht 300 Variablen, die ich vorher definieren muss, und 148 "elif"s. Bezüglich des zweiteren vertraue ich in die Geduld von Python :) , aber zum Erstellen der Variablen hätte ich gerne eine Abkürzung.
Nun habe ich beim Stoebern in den Tutorien die Befehle "str" und "concat" gefunden und mir gedacht, das koennte eine Lösung sein. Ich erzeuge für jeden Fall fortlaufend einen Wert für die Variable "i", dann packe ich diesen Wert mit einem festen Buchstaben (q für das Hochzählen der Fälle und w für die Wahrscheinlichkeiten) zusammen und habe meine Variable; immer genauso viele, wie ich gerade brauche. Ich habe also ausprobiert, was passiert, wenn ich folgendes mache:

Code: Alles auswählen

for i in range(1,5):
  str(i)
  __concat__('q',i)
  __concat__('w',i)
Das gibt im Moment nur eine Fehlermeldung bezueglich concat...
Aber es würde auch sonst nicht funktionieren, glaube ich? Erstens kann ich der Variablen so noch keinen Wert zuweisen (moeglicherweise darf sie dafür kein String sein, sondern muss schon den passenden Typ (int, float) haben?), und zweitens kann ich später auch nicht gezielt auf die einzelnen Variablen zurückgreifen. Was ich bräuchte, wäre eine Möglichkeit, Python zu sagen:

Für den Fall i verwende die Variable 'q'i oder 'w'i.

(Dann könnte ich vielleicht auch die ganzen "elif"s durch eine Schleife ersetzen...)
Wenn es eine solche Funktion schon gibt, erkenne ich sie nicht (was leider auch das Suchen mit der Suchfunktion oder in den Referenzlisten eher schwierig macht).
Wenn nicht - gibt es sinnvolle alternative Herangehensweisen?
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Ja, ein Hash. Das verbindet einen Schlüssel (in Deinem Fall den Wert von dem die Häufigkeit bestimmt werden soll) mit einem Wert (die Häufigkeit).

Das ganze sieht so aus:

Code: Alles auswählen

x = {} # Ein hash bauen.
x[0] = 1 # Häufigkeit von 0 ist 1
x[1] = 15 # Häufigkeit von 1 ist 15
for wert in [1,2,3,4,5,6,7]: # Das [] ist eine Liste mit den Werten von denen ich
                             # die Häufigkeit bestimmen will.
    x[wert] = x.get(wert,0)+1 # Hole die momentane Häufigkeit von wert (get(...)), und
                              # addiere 1 hinzu, und speichere das wieder in unserem hash.
print x
Hoffe das hilft!

PS: Ich kann Dir nur empfehlen ein gutes Python-Buch zu kaufen/auszuleihen, denn gerade Fragen über Datentypen und Ihre Anwendung (wie zum Beispiel ein hash) lassen sich in einem Forum relativ schlecht beantworten; dafür sind eigentlich Bücher da.
--- Heiko.
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

modelnine hat geschrieben:Ja, ein Hash. Das verbindet einen Schlüssel (in Deinem Fall den Wert von dem die Häufigkeit bestimmt werden soll) mit einem Wert (die Häufigkeit).
Wenn ich ehrlich sein darf... das ist mir noch zu hoch :( . (Ich weiss, das soll man nicht schreiben, aber ich bin Anfänger und verstehe auch die Tutorials in diesem Punkt noch nicht...)
Ich müsste also zuerst alle meine "möglichen Fälle" erzeugen und die Ergebnisse zu einem Hash bündeln (hoffentlich ohne eigene Variablen). Dann könnte ich 150 Abfragen machen, um für jeden meiner 150 Fälle die Häufigkeit herauszufinden. Dann muesste ich die Größe des Hash bestimmen, um die Gesamtzahl der Fälle zu bekommen, und könnte meine Wahrscheinlichkeiten berechnen?

Aber für diese Berechnung brauche ich ja auch wieder eine definierte Variable (die ich vermutlich in Zeile 6 erzeugen könnte)?

Und was ist mit den Zeilen 2 und 3 gemeint? Zu dem Zeitpunkt weiss ich ja noch nichts über die möglichen Häufigkeiten?
modelnine hat geschrieben:PS: Ich kann Dir nur empfehlen ein gutes Python-Buch zu kaufen/auszuleihen, denn gerade Fragen über Datentypen und Ihre Anwendung (wie zum Beispiel ein hash) lassen sich in einem Forum relativ schlecht beantworten; dafür sind eigentlich Bücher da.
Nicht so trivial, wenn die nächste deutsche Buchhandlung rund 9000 km entfernt ist... Und es ist in Deutsch schon kompliziert genug, ein englisches Buch könnte ich vielleicht bekommen, aber ob ich es verstehen würde?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich muß sagen, das ich dein Problem bzw. das was du machen willst, auch nicht nicht so richtig verstehe.

Zu den Grundlagen, schau die mal die Unterseiten auf http://wiki.python.de/Tutorial an... Es sind zumindest die Grundlagen um mit Zahlen, String, Listen und Dicts zu arbeiten...

Zu deinem Anliegen... Es ist sicherlich nicht so toll, wenn man eine riesige IF-Abfrage aufbaut... Viel mehr müßte man IMHO eine Datenstruktur ausdenken, die für dein Regelwerk steht. Dann braucht man ein Programm, welches automatisch Daten durch dieses Regelwerk auswertet und die Ergebnisse liefert...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
r2d2
User
Beiträge: 43
Registriert: Donnerstag 2. März 2006, 23:05
Wohnort: Bielefeld

wenn du nur integer (ganze zahlen) von 1 bis 150 protokollieren willst, dann versuch es so:

Code: Alles auswählen

# erstellt eine liste mit 150 elementen, alle mit 0 initialisiert
mylist = [0 for i in range(1,151)]

# setzt bei den aufruf die stelle mylist[1] um eins hoch
def logevent(i):
    mylist[i] += 1
am ende hst du die anzahlt der aufrufe für jeden fall von 1 bis 150

kannst mit

Code: Alles auswählen

print mylist[i]
abfragen

r2d2
äh, nimm diese schlange von meinem hals.
querdenker
User
Beiträge: 424
Registriert: Montag 28. Juli 2003, 16:19
Wohnort: /dev/reality

Versuchen wir es mal mit einem anderen Ansatz:

In welcher Form hast du deine Daten vorliegen?

Kannst du eventuell mal ein Beispiel posten?

mfg, querdenker
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

jens hat geschrieben:Ich muß sagen, das ich dein Problem bzw. das was du machen willst, auch nicht nicht so richtig verstehe.
Offenbar erkläre ich schlecht... :(

Ich gebe ein paar Anfangsdaten in mein hypothetisches Programm ein und führe damit ein paar (tausend) Berechnungen durch, und zwar größtenteils in Form von for- und if-Konstrukten.
Diese Rechnungen führen immer zu integer-Ergebnissen, die je nach Eingabe mal zwischen 1 und 4, mal zwischen 1 und 36 oder eben auch mal zwischen 1 und 150 liegen können - oder theoretisch auch in einem noch größeren Raum, aber für die Praxis genügen vielleicht erst einmal 150 Fälle.
Weil ich nicht alle diese Ergebnisse in einzelnen Variablen speichern möchte, wollte ich nach der Berechnung jeweils nur abfragen, was das Ergebnis i ist, und für diesen Wert einen Zähler (mein 'q'i) um eins hochsetzen. Wenn nur Ergebnisse von 1 bis 4 möglich sind, würden mir also 4 Variable genügen, wenn Ergebnisse bis 150 möglich sind, brauche ich eben auch 150 Variable.
Von diesen 4 bis 150 Variablen bilde ich anschliessend eine Summe ('Fallzahl') und teile jede durch diese 'Fallzahl', um an meine relative Wahrscheinlichkeit zu kommen. Wieder brauche ich manchmal eigentlich nur 4 Variable, manchmal 150.

@ r2d2:
Das sieht schon interessant aus, aber ich komme mit dem Begriff "Aufruf" nicht klar. Was versteht man in diesem Zusammenhang darunter? Kann ich das siebzehnte Listenelement irgendwie gezielt "aufrufen", wenn das Rechenergebnis i 17 beträgt? (Bzw., wenn ich es richtig verstehe: wie mache ich aus meinem 17 = i ein "logevent"?)
Und kann ich "mylist" in eine Form bringen, die es mir erlaubt, alle Werte aufzuaddieren (d.h. meine 'Fallzahl' zu bestimmen) und anschliessend jeden einzelnen Wert durch eben diese Fallzahl zu teilen?

Edit: @ querdenker
Ups, crossposting...
Ist es so konkret genug, oder soll ich versuchen, ein Zahlenbeispiel zu konstruieren?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hm. Du brauchst die Ergebnisse nicht in jeweils einer seperaten Variable zu speichern, sondern an einer bestehenden Liste dran hängen...

Zum Thema Listen, schau dir erstmal das an: http://wiki.python.de/Tutorial/Listen

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

jens hat geschrieben:Hm. Du brauchst die Ergebnisse nicht in jeweils einer seperaten Variable zu speichern, sondern an einer bestehenden Liste dran hängen...
Hm... ja, ich glaube, das könnte klappen.

Damit komme ich auf folgendes:

Code: Alles auswählen

l = []
for i in range (20):
	x = i+1                                                   # Platzhalter für beliebig komplizierte Rechnungen
	l.append(x)
Fallzahl = len(l)
Ergebnisse = [ l.count(%)/Fallzahl % i for i in l]   # Erzeugt eine zweite Liste mit den Wahrscheinlichkeiten
Das ergibt derzeit nur eine Fehlermeldung, weil irgendwas nach dem count(%) fehlt... aber im Prinzip sollte es funktionieren? Ich probiere es morgen nochmal weiter. Vielen Dank erst mal! :)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi merlin_emrys!

Wenn du nur etwas zählen möchtest, dann könnte es evt. so funktionieren:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

# Liste mit Vergleichswerten und einer Zahl, die bei jedem
# Auftreten des Vergleichswerts um eins erhöht wird.
ergebnisliste = [
    [0, 0],
    [1, 0],
    [2, 0],
    [3, 0],
]

# Liste mit den zu prüfenden Werten
pruefliste = [0, 1, 2, 0, 3, 3, 0, 1, 2, 0, 3, 3,]

# Damit die Länge nicht so oft neu ermittelt werden muss,
# wird diese einmal berechnet und daraus eine Liste gemacht,
# welche später mehrmals verwendet werden kann..
rangelist = range(len(ergebnisliste))

# Jeden Wert aus der Prüfliste durchlaufen
for wert in pruefliste:
    # In einer Schleife den Wert mit den ersten Werten der
    # Ergebnisliste vergleichen.
    for i in rangelist:
        if wert == ergebnisliste[i][0]:
            # Gefunden --> Zähler um eins erhöhen
            ergebnisliste[i][1] += 1

print ergebnisliste
mfg
Gerold
:-)

PS: Je nach Anwendung, geht das Zählen von Werten auch einfacher. Aber ich dachte mir, dass du evt. besondere Filterregeln haben könntest und das ist eine Lösung, die nur mit Listen arbeitet. Man kann z.B. auch mit "count()" arbeiten, mit "List Comprehensions", mit "filter()", usw...

Um ein präziseres Beispiel zu liefern. So kann man auch zählen. Vorausgesetzt, man weiß vorher schon, was man zählen möchte.

Code: Alles auswählen

pruefliste = ["a", "aa", "aa", "bb"]
suchliste = ["aa", "bb"]
for sucheintrag in suchliste:
    print "%s: %s" % (sucheintrag, pruefliste.count(sucheintrag))
Zuletzt geändert von gerold am Freitag 3. März 2006, 17:02, insgesamt 2-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Python ist nicht SQL ;)
Mach es doch so, wie von r2d2 vorgeschlagen:

Code: Alles auswählen

haeufigkeit = {} # Hash/Dict anlegen
Fallzahl = 0
for i in range(20):
  x = i+1
  if x not in haeufigkeit:
    haeufigkeit[x] = 1
  else:
    haeufigkeit[x] += 1
  Fallzahl += 1

for x in haeufigkeit:
  print "Wahrscheinlichkeit für",x,"ist %2.3f%%" % (haeufigkeit[x]*100./Fallzahl)
r2d2
User
Beiträge: 43
Registriert: Donnerstag 2. März 2006, 23:05
Wohnort: Bielefeld

@merlin_emrys

ich versuche mal sich dem problem zu nähern.

1. du hast eine funktion, die bestimmte berechnungen anstellt.
2. bei jedem durchlauf liefert diese funktion als ergebnis einen integer-wert.
3. die häufigkeit der einzelnen ergebnisse willst du protokollieren.
4. die ergebnismenge (die anzahl der möglichen integer-werte) steht fest

Code: Alles auswählen

# erstellt eine liste mit 150 variablen, alle mit 0 initialisiert
# diese liste entspricht 150 variablen
# die variablen werden mit mylist[i] angesprochen
# mit mylist[i] gelesen, mit mylist[i]=x gesetzt
mylist = [0 for i in range(1, 151)]

# setzt bei den aufruf die variable mylist[i] um eins hoch
# beispiel: i==1, dann wird die variable an der position 1 um eins erhöht.
def logevent(i):
    mylist[i] = mylist[i] + 1 # oder mylist[i] += 1

# du protokollierst die ergebnisse der funktion "deinefunktion()" mit
logevent(deinefunktion(blablabla))

#oder mit
x = deinefunktion(blablabla)
logevent(x)
wenn meine annahmen bezüglich deines problems falsch sind, berichtige mich.

r2d2
äh, nimm diese schlange von meinem hals.
r2d2
User
Beiträge: 43
Registriert: Donnerstag 2. März 2006, 23:05
Wohnort: Bielefeld

@merlin_emrys

> Nicht so trivial, wenn die nächste deutsche Buchhandlung rund 9000 km entfernt ist...

wo bist du denn gerade? würde mich interessieren.

ansonsten habe ich dein posting im offtopic-forum gelesen.
1. du musst nicht verzweifeln
2. es gibt keine dummen fragen - nur dumme antworten
3. wer nicht fragt bleibt dumm
4. die python-gemeinde freut sich über jeden neuen bürger

in desem sinne: her mit den fragen - ich hab einen großen sack an antworten zu verschenken

r2d2
äh, nimm diese schlange von meinem hals.
querdenker
User
Beiträge: 424
Registriert: Montag 28. Juli 2003, 16:19
Wohnort: /dev/reality

@merlin_emrys:

Ich meinte schon so ein Beispiel wo richtig Zahlen stehen. Muß ja nicht gerade das längste sein.

mfg, querdenker
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

Danke für die vielen neuen Ratschläge! :-)
Etwas ausgeschlafener mache ich mich mal an einen neuen Versuch.

Erste Runde: r2d2s Vorschlag könnte ich verstanden haben, und wenn es funktioniert, müsste es ziemlich praktisch sein.

Code: Alles auswählen

# Programmentwurf
#
# Eingabe der Anfangswerte
#
anz = input("Anzahl Rechenwerte eingeben, Maximum 5: ")
# 
# damit brauche ich maximal die Variablen ber1 bis ber5
#
ber1 = ber2 = ber3 = ber4 = ber5 = 0                      
# 
# Weiter mit der Eingabe
#   
berabfr = input("Bereich für alle Werte gleich? 1=ja, 2=nein: ")
if berabfr == 1: 
   bereich = input("Gib den Bereich an, Maximum 30: ")
elif berabfr == 2:
   for i in range(anz):
       if i == 1:
          ber1 = input("Gib den Bereich an, Maximum 30: ") 
       elif i == 2:
          ber2 = input("Gib den Bereich an, Maximum 30: ") 
       elif i == 3:
          ber3 = input("Gib den Bereich an, Maximum 30: ") 
       elif i == 4:
          ber4 = input("Gib den Bereich an, Maximum 30: ") 
       else:     
          ber5 = input("Gib den Bereich an, Maximum 30: ")
else:
   print "Keine gültige Eingabe"
#
# Eingabe ist damit vorläufig beendet
# Weitere Modifikationen müssen noch implementiert werden
#
#
# erstellt eine liste mit 150 variablen, alle mit 0 initialisiert 
werteliste = [0 for i in range(1, 151)]
#
#
# Rechenoperationen ausführen, in diesem Fall zu Testzwecken eine einfache Addition
#
Fallzahl = 0
for a in range(ber1):
   if ber2 > 0:
       for b in range(ber2):
           if ber3 > 0:
               for c in range(ber3):
                   if ber4 > 0:
                       for d in range(ber4):
                           if ber5 > 0:
                               for e in range(ber5):
                                   i = a + b + c + d + e
                                   def logevent(i):
                                   werteliste[i] = werteliste[i] + 1
                                   Fallzahl = Fallzahl + 1
                           else:
                                   i = a + b + c + d
                                   def logevent(i):
                                   werteliste[i] = werteliste[i] + 1
                                   Fallzahl = Fallzahl + 1
                   else:
                                   i = a + b + c
                                   def logevent(i):
                                   werteliste[i] = werteliste[i] + 1
                                   Fallzahl = Fallzahl + 1
           else:
                                   i = a + b
                                   def logevent(i):
                                   werteliste[i] = werteliste[i] + 1
                                   Fallzahl = Fallzahl + 1
   else:
                                   i = a
                                   def logevent(i):
                                   werteliste[i] = werteliste[i] + 1
                                   Fallzahl = Fallzahl + 1
#
# damit müsste die Werteliste jetzt je nach Eingabe mehr oder weniger viele Daten enthalten
#
print werteliste
Für den Fall 2 (Werte), 1 (gleicher Bereich) und 4 (ber1 und ber2) kann man das Ergebnis relativ leicht mit Hand erstellen:
- Die äusserste Schleife (ber1) sollte mit a = 1 beginnen;
- die zweite Schleife (ber2) sollte mit b = 1 beginnen;
- die inneren 3 Schleifen (ber3, ber4, ber5) sollten nicht ausgeführt werden;
- die zweite Schleife (ber2) sollte a und b addieren, also i = 2;
- dann sollte sie mit b = 2 weitermachen, also i = 3
- und so weiter für b = 3 und 4, dann für a = 2 bis 4 dasselbe
- und damit würde ich in meiner Liste erwarten
(0, 1, 2, 3, 4, 3, 2, 1, 0, 0, usw 0)

Problem:
Wenn ich das Programm testen lasse, moniert Python für Zeile 53:
. There's an error in your program:
. expected an intended block

Was auch immer Python hier erwartet - ich weiss es nicht. "intended block" taucht auf, wenn die Einrückung nicht stimmt? Aber nicht weiter eingerückt gibt den gleichen Fehler.

Also eine zweite Runde, zurück zum Anhängen von Werten an eine Liste.
Eine ganze Menge Fehlerkorrekturen später sieht das Ganze dann so aus:

Code: Alles auswählen

# Programmentwurf
#
# Eingabe der Anfangswerte
#
anz = input("Anzahl Rechenwerte eingeben, Maximum 5: ")
# 
# damit brauche ich maximal die Variablen ber1 bis ber5
#
ber1 = ber2 = ber3 = ber4 = ber5 = 0                      
# 
# Weiter mit der Eingabe
#   
berabfr = input("Bereich für alle Werte gleich? 1=ja, 2=nein: ")
if berabfr == 1: 
       if anz == 1:
          ber1 = input("Gib den Bereich an, Maximum 30: ") 
       elif anz == 2:
          ber1 = ber2 = input("Gib den Bereich an, Maximum 30: ") 
       elif anz == 3:
          ber1 = ber2 = ber3 = input("Gib den Bereich an, Maximum 30: ") 
       elif anz == 4:
          ber1 = ber2 = ber3 = ber4 = input("Gib den Bereich an, Maximum 30: ") 
       else:     
          ber1 = ber2 = ber3 = ber4 = ber5 = input("Gib den Bereich an, Maximum 30: ")
elif berabfr == 2:
   for i in range(anz):
       if i == 1:
          ber1 = input("Gib den Bereich an, Maximum 30: ") 
       elif i == 2:
          ber2 = input("Gib den Bereich an, Maximum 30: ") 
       elif i == 3:
          ber3 = input("Gib den Bereich an, Maximum 30: ") 
       elif i == 4:
          ber4 = input("Gib den Bereich an, Maximum 30: ") 
       else:     
          ber5 = input("Gib den Bereich an, Maximum 30: ")
else:
   print "Keine gültige Eingabe"
#
# Eingabe ist damit vorläufig beendet
# Weitere Modifikationen müssen noch implementiert werden
#
#
# erstellt eine liste mit 150 variablen, alle mit 0 initialisiert 
ergebnisliste = []
#
#
# Rechenoperationen ausführen, in diesem Fall zu Testzwecken eine einfache Addition
#
Fallzahl = 0
for a in range(1,ber1+1):
   if ber2 > 0:
       # print "Start Loop 2"
       for b in range(1,ber1+1):
           if ber3 > 0:
               # print "Start Loop 3"
               for c in range(1,ber1+1):
                   if ber4 > 0:
                       # print "Start Loop 4"
                       for d in range(1,ber1+1):
                           if ber5 > 0:
                               # print "Start Loop 5"
                               for e in range(1,ber1+1):
                                   i = a + b + c + d + e
                                   ergebnisliste.append(i)
                                   Fallzahl = Fallzahl + 1
                                   # print i
                           else:
                                   i = a + b + c + d
                                   ergebnisliste.append(i)
                                   Fallzahl = Fallzahl + 1
                                   # print i
                   else:
                                   i = a + b + c
                                   ergebnisliste.append(i)
                                   Fallzahl = Fallzahl + 1
                                   # print i
           else:
                                   i = a + b
                                   ergebnisliste.append(i)
                                   Fallzahl = Fallzahl + 1
                                   # print i
   else:
                                   i = a
                                   ergebnisliste.append(i)
                                   Fallzahl = Fallzahl + 1
                                   # print i
#
# damit müsste die Werteliste jetzt je nach Eingabe mehr oder weniger viele Daten enthalten
#
print ergebnisliste
ergebnisliste.sort()
print ergebnisliste
Was ich dann bekomme, ist:
>>>
Anzahl Rechenwerte eingeben, Maximum 5: 2
Bereich für alle Werte gleich? 1=ja, 2=nein: 1
Gib den Bereich an, Maximum 30: 4
[2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 5, 6, 7, 8]
[2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 8]
>>>
Jetzt müsste ich diese Liste "durchzählen".
Dafür habe ich den Befehl "count" entdeckt. Das Problem ist: Entweder ich versuche es mit einem if / elif / else-Berg von ergebnisliste.count(1), ergebnisliste.count(2) usw. bis ergebnisliste.count(150), oder ich versuche es mit einer Iteration, wie ihn das Wiki-Tutorium benutzt:

Code: Alles auswählen

neueListe = [ "X%sX" % i for i in l]
Nur: In keinem Anfänger-Tutorial wird mir verraten, wie man mit diesem % umgeht. Und aus den Beispielen, die ich finde, werde ich nur begrenzt schlau: % ist ein Platzhalter für etwas, was danach noch genauer definiert wird. Die Library Reference verrät mir, daß das kleine "s" für String-Variable steht und bietet mir für Integer zwei Möglichkeiten an: d und i.
Aber ich komme nicht dahinter, wie die Formulierung aussehen muß.

Code: Alles auswählen

werteliste = [ergebnisliste.count(%d) % i for i in ergebnisliste]

ist es jedenfalls nicht; ich bekomme einen Syntax error für das % in ergebnisliste.count(%d).

Nach etwa 7 Stunden Programmierung mache ich für heute erstmal Schluss, schaue aber nachher nochmal ins Forum.
Nur noch kurz @ r2d2: Auf die Frage nach meinem Aufenthaltsort antworte ich im Off-Topic.


Danke nochmal für alle Hilfe, gerade auch an Gerold und Jogurth. Ich habe Eure Vorschläge nicht übersehen, nur aus Zeitmangel noch nicht ausprobieren können...
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

merlin_emrys hat geschrieben: Problem:
Wenn ich das Programm testen lasse, moniert Python für Zeile 53:
. There's an error in your program:
. expected an intended block

Was auch immer Python hier erwartet - ich weiss es nicht. "intended block" taucht auf, wenn die Einrückung nicht stimmt? Aber nicht weiter eingerückt gibt den gleichen Fehler.
In deinem ersten Programm stimmen die Eintrueckungen nicht.
Erstens sollten die else immer die gleiche Einrueckung haben wie das if, zu dem sie gehoeren. Ausserdem muss in der Zeile nach einem def auch eine Einrueckung sein (was in Zeile 53 nicht der Fall ist --> Fehlermeldung!)

Merke: In Zeilen nach ":" kommt immer eine Einrueckung. Die Editoren, die Python koennen, machen das meist auch von alleine.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Zu deinem Zaehlproblem: Eine Loesung ist:

Code: Alles auswählen

werteliste = []
for i in ergebnisliste:
     werteliste.append(ergebnisliste.count(i))
Dein Fehler: %s, %i etc. sind in strings einzusetzen, und koennen nicht fuer sich stehen. Z.B. (der einfachheit halber ohne for-Schleife):

Code: Alles auswählen

meine_liste.count("%d" % 4)

Das ist das gleiche wie

Code: Alles auswählen

meine_liste.count("4")

Es wird also das Auftreten des STRINGS "4" gezaehlt, du willst aber das Auftreten der ZAHL 4 zaehlen:

Code: Alles auswählen

meine_liste.count(4)
Mann muesste also den String "4" noch in einen Integer konvertieren. Ueblicherweise macht man das mit int("4").

Ich muss gestehen, dass ich den eleganten Einzeiler, den du versucht hast, gerade auch nicht richtig hinbekomme, aber obiger Dreizeiler geht ja auch. :)
BlackJack

merlin_emrys hat geschrieben:

Code: Alles auswählen

# Programmentwurf
#
# Eingabe der Anfangswerte
#
anz = input("Anzahl Rechenwerte eingeben, Maximum 5: ")
# 
# damit brauche ich maximal die Variablen ber1 bis ber5
#
ber1 = ber2 = ber3 = ber4 = ber5 = 0
`input()` kann gefährlich sein, weil man dort gültiges Python eingeben kann, was dann ausgeführt wird. In Deinem Fall nicht so schlimm wenn Du der einzige bist, der das Programm benutzt, aber wenn das auch mal "Endbenutzer" in die Hände bekommen, sollte man `raw_input()` nehmen und die Zeichenkette die dort zurückgeliefert wird, explizit in eine Zahl (`int()` oder `float()`) umwandeln.

Für Deine Bereiche kannst Du eine Liste nehmen:

Code: Alles auswählen

In [2]:ber = [0] * 5

In [3]:ber
Out[3]:[0, 0, 0, 0, 0]

In [4]:ber[0]
Out[4]:0

In [5]:ber[2]
Out[5]:0
Dann fängt die Numerierung zwar bei 0 an, aber man kann sie auch "programmatisch", also zum Beispiel in einer Schleife vornehmen.

Code: Alles auswählen

# 
# Weiter mit der Eingabe
#   
berabfr = input("Bereich für alle Werte gleich? 1=ja, 2=nein: ")
if berabfr == 1: 
       if anz == 1:
          ber1 = input("Gib den Bereich an, Maximum 30: ") 
       elif anz == 2:
          ber1 = ber2 = input("Gib den Bereich an, Maximum 30: ") 
       elif anz == 3:
          ber1 = ber2 = ber3 = input("Gib den Bereich an, Maximum 30: ") 
       elif anz == 4:
          ber1 = ber2 = ber3 = ber4 = input("Gib den Bereich an, Maximum 30: ") 
       else:     
          ber1 = ber2 = ber3 = ber4 = ber5 = input("Gib den Bereich an, Maximum 30: ")
Hier würde ich nicht zwischen der Anzahl der Bereiche unterscheiden. Warum nicht einfach alle auf den eingegebenen Wert setzen?

Code: Alles auswählen

In [7]:ber = [int(raw_input('Bereich:'))] * 5
Bereich:10

In [8]:ber
Out[8]:[10, 10, 10, 10, 10]

Code: Alles auswählen

elif berabfr == 2:
   for i in range(anz):
       if i == 1:
          ber1 = input("Gib den Bereich an, Maximum 30: ") 
       elif i == 2:
          ber2 = input("Gib den Bereich an, Maximum 30: ") 
       elif i == 3:
          ber3 = input("Gib den Bereich an, Maximum 30: ") 
       elif i == 4:
          ber4 = input("Gib den Bereich an, Maximum 30: ") 
       else:     
          ber5 = input("Gib den Bereich an, Maximum 30: ")
Hier hätte man jetzt einen Vorteil davon, das die Bereiche in einer Liste stehen: Man kann sie in einer Schleife abfragen.

Code: Alles auswählen

elif berabfr == 2:
   for i in xrange(anz):
       ber[i] = int(raw_input('Gib den Bereich an, Maximum 30: '))
Immer wenn Du fast identischen Quelltext öfter wiederholst, ist das ein Warnsignal dafür, dass *Du* etwas tust, was Du auch dem Rechner übertragen kannst.

Die Schleife und die Liste machen nicht nur weniger Tipparbeit, sondern erhöhen auch die Wartbarkeit des Programms. Stell Dir in beiden Varianten mal vor an wievielen Stellen Du etwas ändern müsstest, wenn Du Beispielsweise 10 Bereiche oder ein anderes Maximum haben möchtest.

Code: Alles auswählen

# erstellt eine liste mit 150 variablen, alle mit 0 initialisiert 
ergebnisliste = []
Der Kommetar ist so nicht richtig. Da oben wird nur eine leere Liste, d.h. eine mit 0 Einträgen angelegt. Analog zur Bereichsliste kann man so 150 Nullen in eine Liste packen:

Code: Alles auswählen

ergebnisliste = [0] * 150
Was ich dann bekomme, ist:
>>>
Anzahl Rechenwerte eingeben, Maximum 5: 2
Bereich für alle Werte gleich? 1=ja, 2=nein: 1
Gib den Bereich an, Maximum 30: 4
[2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 5, 6, 7, 8]
[2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 8]
>>>
Jetzt müsste ich diese Liste "durchzählen".
Dafür habe ich den Befehl "count" entdeckt. Das Problem ist: Entweder ich versuche es mit einem if / elif / else-Berg von ergebnisliste.count(1), ergebnisliste.count(2) usw. bis ergebnisliste.count(150), oder ich versuche es mit einer Iteration, wie ihn das Wiki-Tutorium benutzt:

Code: Alles auswählen

neueListe = [ "X%sX" % i for i in l]
Nur: In keinem Anfänger-Tutorial wird mir verraten, wie man mit diesem % umgeht. Und aus den Beispielen, die ich finde, werde ich nur begrenzt schlau: % ist ein Platzhalter für etwas, was danach noch genauer definiert wird. Die Library Reference verrät mir, daß das kleine "s" für String-Variable steht und bietet mir für Integer zwei Möglichkeiten an: d und i.
Aber ich komme nicht dahinter, wie die Formulierung aussehen muß.
Die Platzhalter für Zeichenkettenformatierung brauchst Du bei Deinem Problem erstmal gar nicht. Du möchtest ja Zahlen zählen und nichts mit Zeichenketten anstellen.

Code: Alles auswählen

werteliste = [ergebnisliste.count(%d) % i for i in ergebnisliste]

ist es jedenfalls nicht; ich bekomme einen Syntax error für das % in ergebnisliste.count(%d).
Den hat Dir Rebecca ja schon erklärt. Aber letztendlich ist das nicht das was Du möchtest. Das Ergebnis hat nämlich genau so viele Einträge wie `ergebnisliste` und ausserdem ist das mit dem `count()` nicht so effizient weil für jeden Eintrag die gesamte Liste durchlaufen werden muss. Der Zeitaufwand dafür wächst quadratisch mit der Länge der Liste.

Mit Deiner sortierten Beispielliste von oben sähe das so aus:

Code: Alles auswählen

In [11]:ergebnisliste = [2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 8]

In [12]:[ergebnisliste.count(i) for i in ergebnisliste]
Out[12]:[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 2, 2, 1]
Du brauchst zum Zählen eher eine Abbildung, also ein Dictionary wo ein Wert auf die Häufigkeit seines Auftretens abgebildet wird.

Code: Alles auswählen

In [13]:histogramm = dict()

In [14]:for wert in ergebnisliste:
   .14.:    histogramm[wert] = histogramm.get(wert, 0) + 1
   .14.:

In [15]:histogramm
Out[15]:{2: 1, 3: 2, 4: 3, 5: 4, 6: 3, 7: 2, 8: 1}

In [16]:histogramm[5]
Out[16]:4
Ansonsten würde ich Dir raten die einzelnen Teile Deines Programms in Funktionen zu verpacken. Dann kannst Du das Programm im interaktiven Interpreter importieren und die Funktionen sozusagen "live" und einzeln ausprobieren.

Und Du kannst auch mit den eingebauten Datentypen rumspielen um ein Gefühl dafür zu bekommen wie die funktionieren.

Code: Alles auswählen

In [22]:d = dict()

In [23]:help(d)
Help on dict object:

class dict(object)
 |  dict() -> new empty dictionary.
 |  dict(mapping) -> new dictionary initialized from a mapping objects
 |      (key, value) pairs.
 |  dict(seq) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in seq:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized with the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)
...

In [24]:d['hallo'] = 10

In [25]:d
Out[25]:{'hallo': 10}

In [26]:d['hallo']
Out[26]:10

In [27]:d['blah']
---------------------------------------------------------------------------
exceptions.KeyError                 Traceback (most recent call last)

/home/bj/<ipython console>

KeyError: 'blah'

In [28]:help(d.get)
Help on built-in function get:

get(...)
    D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.

In [29]:d.get('hallo', 0)
Out[29]:10

In [30]:d.get('blah', 0)
Out[30]:0
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

Rebecca hat geschrieben:Zu deinem Zaehlproblem: Eine Loesung ist:

Code: Alles auswählen

werteliste = []
for i in ergebnisliste:
     werteliste.append(ergebnisliste.count(i))
Ich glaube, i muss im "range(1,150)" sein, aber damit haut es dann hin. Vielen Dank! :-)
Rebecca hat geschrieben:Dein Fehler: %s, %i etc. sind in strings einzusetzen, und koennen nicht fuer sich stehen.
Ups... danke für den Tip, das hatte ich bisher nicht begriffen. Und danke für den Hinweis betr. der Einrückung nach einem Doppelpunkt. Ich hatte sowas vermutet, war mir aber keineswegs sicher. Nur in dem speziellen Fall von Zeile 53 hat Python zu meiner Verwirrung beide Versionen nicht akzeptiert... Die zitierte Version war die geänderte, ursprünglich hatte ich die Einrückung aus r2d2s Vorschlag schon mit übernommen.
BlackJack hat geschrieben:`input()` kann gefährlich sein, weil man dort gültiges Python eingeben kann, was dann ausgeführt wird. In Deinem Fall nicht so schlimm wenn Du der einzige bist, der das Programm benutzt, aber wenn das auch mal "Endbenutzer" in die Hände bekommen, sollte man `raw_input()` nehmen und die Zeichenkette die dort zurückgeliefert wird, explizit in eine Zahl (`int()` oder `float()`) umwandeln.
Ich bezweifele, dass irgendjemand dies Programm interessant finden wird... aber Hinweise auf gute Programmierpraxis kann ich auch noch sehr gut gebrauchen. Danke! Ich werde die entsprechenden Befehle noch einfügen.
BlackJack hat geschrieben:Hier würde ich nicht zwischen der Anzahl der Bereiche unterscheiden. Warum nicht einfach alle auf den eingegebenen Wert setzen?
Wenn ich Deine Frage richtig verstehe, müsste die Antwort mit genau dieser Überlegung zusammenhängen:
BlackJack hat geschrieben:Immer wenn Du fast identischen Quelltext öfter wiederholst, ist das ein Warnsignal dafür, dass *Du* etwas tust, was Du auch dem Rechner übertragen kannst.
Das ist mir bewußt. In ScionImage würde ich dann einfach hingehen, beispielsweise eine sogenannte "procedure" mit dem Namen "Ergebnisermittlung" oder so erstellen und an den entsprechenden Stellen einfach nur "Ergebnisermittlung" durchführen lassen. Aber in Python heisst das wohl nicht "procedure"... Ich vermute, es ist der "def"-Befehl? An dem lerne ich noch...
Aber kurz zurück: Wenn ich die "Ergebnisermittlung" verallgemeinere, müssen (glaube ich, aber ich bin Anfänger) die "nicht benötigten" Bereiche auf Null gesetzt bleiben, damit nur so viele Schleifen abgearbeitet werden, wie auch in der Anzahl zu Anfang eingegeben wurden. Alternativ fiele mir ein, innerhalb der "Auswerte-Schleifen" statt über

Code: Alles auswählen

if ber4 > 0:
die Abfrage über anz gehen zu lassen:

Code: Alles auswählen

if anz>= 4
BlackJack hat geschrieben:Der Kommetar ist so nicht richtig.
Ups, stimmt. Den hatte ich beim Umschreiben des Programms übersehen... Ist geändert.
BlackJack hat geschrieben:Du brauchst zum Zählen eher eine Abbildung, also ein Dictionary wo ein Wert auf die Häufigkeit seines Auftretens abgebildet wird.
Wie erwähnt, wenn ich es mit range(1,150) versuche, bekomme ich das von mir erwartete Ergebnis. Die Sache mit dem dictionary gefällt mir aber noch besser, weil sie vor jeder Angabe mitteilt, um welchen Wert es geht. Sonst macht es doch viel Arbeit, wenn ich nachzählen muss, wie der Wert für 123 nun ist! :-)

Danke nochmal für die Hilfe!
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

Ich hab' leider immer noch nicht alles ausprobieren können, aber derzeit hänge ich an einem Problem, das ich nicht verstehe. Offenbar mache ich einen Fehler in der Abfrage von Werten, die ich per raw_input zugewiesen habe.

Code: Alles auswählen

#
# Poolabfrage
#
poolabfr = raw_input("Gibt es einen Pool? j_a,n_ein: ")

if poolabfr == 'n' or 'nein': 
          pool = 0          
elif poolabfr == 'j' or 'ja': 
          pool_e = raw_input("Gib die Poolgröße an, Maximum 20: ")
          pool = int(pool_e)
else: 
     print "Keine gültige Eingabe"
     pool = 20

print 'pool = ', pool
print poolabfr
Beim Programmdurchlauf wird immer die erste Bedingung als "wahr" festgestellt, egal was ich eingebe; ich bekomme z.B.

Code: Alles auswählen

>>> 
Gibt es einen Pool? j_a,n_ein: j
pool =  0
j
>>> 
Laut Tutorial müsste es aber so gehen...?
Antworten