Hi,
folgendes Problem:
Ich möchte ein Diagramm plotten.
Dazu fordere ich den Benutzer auf die Limits für die X-Achse einzugeben (xmin, xmax).
Nun sollen aber xmin und xmax nicht nur Zahlen, also floats, sein, sondern auch Prozent zahlen (60%).
Erstmal, gibt es einen schönen Weg eine Prozentzahl zu erkennen (mache bisher etwas String Gymnastik aber hüpsch ist anders)
Zweitens, wie speichere ich es am besten?
Sollte ich mir einen eigenen Datentyp schreiben oder was wie ne Klasse?
Oder gibt es da auch eine schönere Lösung?
MfG
p90
Prozentangaben verarbeiten?
Dem Problem fehlt Kontext, um es wirklich gut beurteilen zu koennen. Aber versuchen wir's mal:
- das einlesen von den Werten musst du schon mit String-Gymnastik machen, und ich halte das auch fuer das beste. Ob die "huebsch" ist oder nicht haengt von deiner Implementierung ab, ich finde das hier eingentlich ok:
Mehr geht natuerlich immer, du kannst validieren (Prozentangaben nur positive, nur 0 <= v <= 100 usw)
- ein neuer Datentyp Prozent lohnt sich IMHO nicht. Du verraetst nicht, was die Prozent denn sind (vieviel Prozent von was denn genau?), aber ich wuerde die Eingabe einfach in ein Dictionary oder kleines Objekt packen, dass eben die Grenzen + die Flagge enthaelt. Wer auch immer damit weiterrechnet, muss dann zB darauf ruecksicht nehmen.
- das einlesen von den Werten musst du schon mit String-Gymnastik machen, und ich halte das auch fuer das beste. Ob die "huebsch" ist oder nicht haengt von deiner Implementierung ab, ich finde das hier eingentlich ok:
Code: Alles auswählen
def read_input(msg=""):
is_percent = False
inp = raw_input(msg).strip()
if inp[-1] == "%":
is_percent = True
inp = inp[:-1]
return float(inp), is_percent
- ein neuer Datentyp Prozent lohnt sich IMHO nicht. Du verraetst nicht, was die Prozent denn sind (vieviel Prozent von was denn genau?), aber ich wuerde die Eingabe einfach in ein Dictionary oder kleines Objekt packen, dass eben die Grenzen + die Flagge enthaelt. Wer auch immer damit weiterrechnet, muss dann zB darauf ruecksicht nehmen.
@gkuhl
Wo ist das so definiert? Und wie unterscheidet der OP dann von der Eingabe 0.6? Das ist doch schlicht nicht dasselbe, und demnach falsch was du da vorschlaegst.
Wo ist das so definiert? Und wie unterscheidet der OP dann von der Eingabe 0.6? Das ist doch schlicht nicht dasselbe, und demnach falsch was du da vorschlaegst.
@deets: Prozent kommt aus dem lateinischen oder italienischen und bedeutet vom Hundert [1]. Definiert ist es u.a. in irgendeiner DIN. Danach sind x Prozent = x% = x/100 = 0.01x. Und genau so würde ich das im Programm speichern.
Ob die Benutzereingabe in Prozent ist oder nicht, und wie man diesen dann erkennt, hängt davon ab, wie das Benutzerinterface gestaltet wird. Mir ging es in meiner Antwort um die Speicherung.
Ob die Benutzereingabe in Prozent ist oder nicht, und wie man diesen dann erkennt, hängt davon ab, wie das Benutzerinterface gestaltet wird. Mir ging es in meiner Antwort um die Speicherung.
Nochmal: wie unterscheidest du bei deiner Speicherung zwischen der Eingabe "60%" die laut dir ja einfach nur nach 0.6 gewandelt werden muss, und der Eingabe 0.6, die semantisch etwas komplett anderes bedeutet? *Das* ist hier das Problem, nicht eine triviale Division.gkuhl hat geschrieben:@deets: Prozent kommt aus dem lateinischen oder italienischen und bedeutet vom Hundert [1]. Definiert ist es u.a. in irgendeiner DIN. Danach sind x Prozent = x% = x/100 = 0.01x. Und genau so würde ich das im Programm speichern.
Ob die Benutzereingabe in Prozent ist oder nicht, und wie man diesen dann erkennt, hängt davon ab, wie das Benutzerinterface gestaltet wird. Mir ging es in meiner Antwort um die Speicherung.
Für mich gibt es keinen Grund zwischen "60%" und "0.6" zu unterscheiden, weil es als Zahl in beiden Fällen 0.6 bedeutet. Ersteres benötigt nur etwas Handarbeit beim Umwandeln. Gleiches gilt übrigens auch für die Strings "600‰", "60c" oder "6e-2", als Zahl ebenfalls 0.6. Genauso würde ich Prozentzahlen im Computer speichern und das war schließlich die Teil der Frage des OP.
Wenn man für die Ausgabe ein bestimmtes Format wünscht, kann man eine beim Erkennen des %-Zeichens eine Flag setzen. Hier ein einfaches Beispiel:
Genauso würde ich auch die Frage des OP angehen. Intern mit Floats rechnen und bei der Ausgabe (z.B. Beschriftung der Achsen) eventuelle Benutzereingaben berücksichtigen. Meiner Meinung eine saubere Trennung von Benutzerinterface und Programmlogik.
Ich sehe hier wirklich nicht, wo hier ein großes Problem sein soll. Reden wir eventuell total aneinander vorbei?
Grüße
Gerrit
Wenn man für die Ausgabe ein bestimmtes Format wünscht, kann man eine beim Erkennen des %-Zeichens eine Flag setzen. Hier ein einfaches Beispiel:
Code: Alles auswählen
zahl, flag = bearbeite_eingabe("60%") # Rückgabe: (0.60, '%')
print "{0:.1f}%".format(100*zahl) if flag == "%" else "{0:.2f}".format(zahl)
Ich sehe hier wirklich nicht, wo hier ein großes Problem sein soll. Reden wir eventuell total aneinander vorbei?
Grüße
Gerrit
@gkuhl: 0.6 != 0.6% denn 0.6 ist eine *absolute* Angabe und 0.6% ist eine *relative* Angabe. Wenn ich sage ich möchte auf der X-Achse den Wertebereich 0.2 bis 0.8 angezeigt bekommen, ist das etwas anderes als wenn ich sage 20%-80% vom Wertebereich. Das wäre nur gleich wenn der Wertebereich zufällig auf 0-1 beschränkt ist.
Jetzt verstehe ich endlich was ihr meint. Ich hatte den OP so verstanden, dass auf der x-Achse Werte in Prozent (z.B. 0% bis 200%) dargestellt werden und per Benutzereingabe, ein absolute Bereich ausgewählt werden soll. Also z.B. 20% bis 120%. In dem Zusammenhang sind die Prozentzahlen absolute Werte und es macht wenig Sinn, das Prozent im Programm herumzuschleppen.
Sollte es sich um relative Angaben handeln, wäre mir noch nicht klar auf welchen Wertebereich sich diese beziehen sollen. Möglich wären u.a.:
- die Länge der dargestellten x-Achse,
- Minimum und Maximum der Daten,
- oder irgendwelche anderen obskuren Vorgaben.
Hier wäre Aufklärung notwendig. Relative Zahlen teile ich übrigens auch durch 100. Damit rechnet es sich einfacher.
Sollte es sich um relative Angaben handeln, wäre mir noch nicht klar auf welchen Wertebereich sich diese beziehen sollen. Möglich wären u.a.:
- die Länge der dargestellten x-Achse,
- Minimum und Maximum der Daten,
- oder irgendwelche anderen obskuren Vorgaben.
Hier wäre Aufklärung notwendig. Relative Zahlen teile ich übrigens auch durch 100. Damit rechnet es sich einfacher.
Hi,
also erst mal Danke für die vielen Antworten.
Erstmal etwa mehr Kontext.
Ich plotte wie gesagt Daten in ein Histogramm.
Dabei möchte ich die Möglichkeit haben den absoluten x-Abschnitt einzutragen als auch zu sagen "Plotte mir alle Daten bis auf die obersten 5%" (es handelt sich um Daten aus einem Osziloskop das die einkommenden Signale ab einer bestimmten Höhe abschneidet und ich dadurch immer am rechten Rand einen fetten Peak habe der da nicht sein sollte sondern eigentlich unter "overflow"(das ist die Anzahl der Ereignisse über halb des betrachteten Bereichs) angezeigt werden soll)
Ich muss also irgendwie bei der Eingabe verstehen "Aha, das ist ein Float, das ist dann wohl Absolut" und "Aha, das ist ein Prozentwert, da muss ich erst mal nachsehen in welchen Datenbereich meine Daten sind und dann dies relativ darauf anwenden"
Machen wir mal ein Beispiel:
gemessene Werte: (0, 2,10,2,3,5) = a
Ohne irgendeien Angabe verwende ich standardmäßig min(a) als minimum, max(a) als maximum für den plot.
Nun kann ich angeben: min=3
Dann würden die Werte (0,2,2) nicht im Histogramm erscheinen.
Gebe ich den Wert: max=10% an mache ich folgendes:
(max(a)-min(a))*(1-10%)+min(a) = maximum = (10-0)*90%+0=9
Das ist auch alles an sich kein Problem, nur das ich halt die beiden Möglichkeiten irgendwie durch schleppen muss und da wird es etwas schwierig. Ich dachte mir ich schreibe vlt ne neue Klasse "limits" und die bekommt das dann gesagt was es ist, baue da die Funktionen
"maximum" und "minimum" ein und diese geben mir dann später das was ich brauche.
Denke das geht auch nicht anders. Aber bei so was frage ich doch lieber nach weil bestimmt schon jemand der wesentlich besser in python ist vor was ähnlichem gesessen hat.
also erst mal Danke für die vielen Antworten.
Erstmal etwa mehr Kontext.
Ich plotte wie gesagt Daten in ein Histogramm.
Dabei möchte ich die Möglichkeit haben den absoluten x-Abschnitt einzutragen als auch zu sagen "Plotte mir alle Daten bis auf die obersten 5%" (es handelt sich um Daten aus einem Osziloskop das die einkommenden Signale ab einer bestimmten Höhe abschneidet und ich dadurch immer am rechten Rand einen fetten Peak habe der da nicht sein sollte sondern eigentlich unter "overflow"(das ist die Anzahl der Ereignisse über halb des betrachteten Bereichs) angezeigt werden soll)
Ich muss also irgendwie bei der Eingabe verstehen "Aha, das ist ein Float, das ist dann wohl Absolut" und "Aha, das ist ein Prozentwert, da muss ich erst mal nachsehen in welchen Datenbereich meine Daten sind und dann dies relativ darauf anwenden"
Machen wir mal ein Beispiel:
gemessene Werte: (0, 2,10,2,3,5) = a
Ohne irgendeien Angabe verwende ich standardmäßig min(a) als minimum, max(a) als maximum für den plot.
Nun kann ich angeben: min=3
Dann würden die Werte (0,2,2) nicht im Histogramm erscheinen.
Gebe ich den Wert: max=10% an mache ich folgendes:
(max(a)-min(a))*(1-10%)+min(a) = maximum = (10-0)*90%+0=9
Das ist auch alles an sich kein Problem, nur das ich halt die beiden Möglichkeiten irgendwie durch schleppen muss und da wird es etwas schwierig. Ich dachte mir ich schreibe vlt ne neue Klasse "limits" und die bekommt das dann gesagt was es ist, baue da die Funktionen
"maximum" und "minimum" ein und diese geben mir dann später das was ich brauche.
Denke das geht auch nicht anders. Aber bei so was frage ich doch lieber nach weil bestimmt schon jemand der wesentlich besser in python ist vor was ähnlichem gesessen hat.
@p90
Das ist schon beim ersten mal so verstanden worden. Es aendert also nicht wirklich viel an den Antworten.
Man kann das Ganze - abhaengig von deinem restlichen Programm - ein bisschen mehr in was OO-iges packen. Also zB sowas hier:
Zusammen mit meiner oben vorgestellten Funktion kannst du dann eben eine der beiden Limits-Implementationen erzeugen und weiterreichen.
Das ist schon beim ersten mal so verstanden worden. Es aendert also nicht wirklich viel an den Antworten.
Man kann das Ganze - abhaengig von deinem restlichen Programm - ein bisschen mehr in was OO-iges packen. Also zB sowas hier:
Code: Alles auswählen
class Limits(object):
def __init__(self, min, max):
self.min, self.max = min, max
def min_max_for_data(self, datapoints):
return self.min, self.max
def filter_data(self, datapoints):
minp, maxp = self.min_max_for_data(datapoints):
return [p for p in datapoints if minp <= p <= maxp]
class PercentageLimits(Limits):
def __init__(self, minp, maxp):
self.minp, self.maxp = minp, max
def min_max_for_data(self, datapoints):
min_ = min(datapoints)
max_ = max(datapoints)
d = max_ - min_
return min_ + self.minp * d, min_ + self.maxp * d
@p90: Mir war der Kontext nicht wirklich klar. Daher vielen Dank für die längere Beschreibung.
Die Verarbeitung und Speicherung der Eingabe würde ich wie deets machen. Die Benutzereingabe also nach dem Parsen in einem Dictionary speichern:
Um die Daten zu filtern, würde ich eine Funktion einer Lösung mit Klassen vorziehen. Hier mal ein Beispiel mit NumPy:
Die Verarbeitung und Speicherung der Eingabe würde ich wie deets machen. Die Benutzereingabe also nach dem Parsen in einem Dictionary speichern:
Code: Alles auswählen
limits = {'limits': (0.0, 0.6), 'relative': True}
Code: Alles auswählen
import numpy as np
def filter_data(data, limits, relative=False):
vmin, vmax = limits
data = np.asarray(data)
if relative:
distance = data.max() - data.min()
vmin = data.min() + vmin * distance
vmax = data.min() + vmax * distance
return data[(data >= vmin) & (data <= vmax)] # & soll ein kaufmänisches Und sein.