Seite 1 von 1

Messwert in Array finden

Verfasst: Montag 5. Juni 2017, 18:13
von sanjo386
Hallo zusammen,

ich möchte gerne einen Messwert in einem Array finden. Die Herausforderung daran ist, dass es Messwerte sind inkl. der natürlichen Streuung und es soll der nächste Wert gefunden werden. Angenommen ich suche den Messwert 12 und das Array sieht [1.5, 2.8, 5.0, 11.9, 12.2, 14.9] aus, dann soll das Ergebnis 11.9 sein. Man könnte abfragen, ob der Messwert kleiner oder größer als der gesuchte Wert ist und sich so herantasten (Newton), aber das erscheint mir etwas aufwendig, zumal hier mehrdimensionale Arrays Messwerte unterschiedlicher Einheiten und Streuungen enthalten. Man müsste also zusätzlich noch die Genauigkeit in Bezug zur Standardabweichung berücksichtigen. Alternativ könnte man von jedem Messwert die Differenz zum gesuchten Wert bilden und die betragsmäßig kleinste Differenz entspricht dem nächsten Messwert, was mir als sehr rechenlastig erscheint.

Was denkt ihr, gibt es vielleicht weitere Möglichkeiten?

Vielen Dank vorab und Gruß
Sanjo386

Re: Messwert in Array finden

Verfasst: Montag 5. Juni 2017, 18:35
von __deets__
Wenn die Sortierung immer gegeben ist, kannst du auch mit dem bisect-Modul arbeiten.

Re: Messwert in Array finden

Verfasst: Montag 5. Juni 2017, 19:19
von Siegfried
Alternativ mit numpy

[codebox=pys60 file=Unbenannt.txt]
import numpy as np
werte = [1.5, 2.8, 5.0, 11.9, 12.2, 14.9]
suchwert = 12
index=abs(np.array(werte)-suchwert).argmin()
print("Das Listenelement mit der geringsten Abweichung ist:",werte[index],"Listenindex:",index)

[/code]

Funktioniert auch mit mehrdimensionalen Arrays; Voraussetzung ist, daß alle Subarrays einer Dimension gleich groß sind. Beispiel:
[codebox=pys60 file=Unbenannt.txt]
werte = [[1.5, 2.8, 5.0, 11.9, 12.2, 14.9],[8, 9, 10, 11, 12.02, 13]]
[/code]

Re: Messwert in Array finden

Verfasst: Dienstag 6. Juni 2017, 05:17
von Siegfried
@Siegfried:
index ist zwar ein sprechender Name, kann aber zu Konflikten nit der eingebauten index Methode führen. Besser wäre ein Name wir 'ind','idx', 'suchindex' , 'indexx',...
Für mehrdimensionale Arrays funktioniert es so nicht. So kann nur der Listenindex ausgegeben werden. Wenn man auch den Wert haben will, sollte man das Array von vornherein als 'np.'array' definieren

korrigierte Version
[codebox=pys60 file=Unbenannt.txt]
import numpy as np
werte = np.array([[1.5, 2.8, 5.0, 11.9, 12.2, 14.9],[8, 9, 10, 11, 12.02, 13]])
suchwert=12
indexx=abs(werte-suchwert).argmin()
print("Das Listenelement mit der geringsten Abweichung ist:",werte.flatten()[indexx],"Listenindex:",indexx)
[/code]

Re: Messwert in Array finden

Verfasst: Dienstag 6. Juni 2017, 05:40
von Sirius3
Die Methode `list.index` ist in einem anderen Namensraum, so dass eine lokale Variable `index` überhaupt kein Problem darstellt. Was dagegen ein Problem ist, sind Namen, die aus kryptischen Abkürzungen bestehen, wie `ind`, `idx`, oder sinnlose postfixe enthalten, wie z.B. `indexx`, wo niemand weiß, wofür das `x` steht, oder etwas suggerieren, was gar nicht der Fall ist, wie z.B. `suchindex`, der gar nicht zum Suchen da ist, sondern schon ein `gefundenindex` ist. Am besten nennt man den Index nach dem Messwert, den man gesucht hat, als `index_druck`, `index_temperatur`, ...

Wenn man ein 2d-Array nur dazu hat, um es dann flachzuklopfen, hat man nicht wirklich ein 2d-Array.

Re: Messwert in Array finden

Verfasst: Dienstag 6. Juni 2017, 08:03
von snafu
sanjo386 hat geschrieben:Angenommen ich suche den Messwert 12 und das Array sieht [1.5, 2.8, 5.0, 11.9, 12.2, 14.9] aus, dann soll das Ergebnis 11.9 sein.
Und dann soll anschließend nicht mehr die 12 verwendet werden, sondern die 11.9, habe ich das richtig verstanden? Man kann also nicht in einem Rutsch mit der 12 das 2d-Array durchlaufen, sondern muss fortwährend den Näherungswert anpassen?

Re: Messwert in Array finden

Verfasst: Dienstag 6. Juni 2017, 17:45
von Siegfried
Über sinnvolle Namensgebung kann man lange streiten. Ich halte `ind` oder `idx` nicht für besonders kryptische Abkürzungen, meine aber, daß `gefundenindex` etwas suggeriert, was gar nicht der Fall ist, da ein Wert gesucht wird, der bei den Meßwerten gar vorhanden ist, ergo auch nicht gefunden werden kann. Ähnlich gering scheint mir der Zusatznutzen von `index_druck` oder `index_temperatur`, da sich die Meßwerte wahrscheinlich alle auf Temperatur, Druck o.ä. beziehen, d.h. der eine gesuchte Meßwert hat genauso einen `index_druck` wie alle anderen Meßwerte auch.

Gemäß Fragestellung sind mehrdimensionale Arrays gegeben. Es kann also keine Rede davon sein, daß sie nur erzeugt werden, um sie anschließend flach zu klopfen.

Re: Messwert in Array finden

Verfasst: Dienstag 6. Juni 2017, 22:59
von snafu
Hier mal der gezeigte Ansatz angewendet auf dem 2d-Array:

Code: Alles auswählen

import numpy as np

def find_nearest_2d(values, needle):
    indices = abs(values - needle).argmin(axis=1)
    return np.array(
        [values[i, j] for i, j in enumerate(indices)]
    )

def main():
    values = [[1.5, 2.8, 5.0, 11.9, 12.2, 14.9],[8, 9, 10, 11, 12.02, 13]]
    print(find_nearest_2d(np.array(values), 12))

if __name__ == '__main__':
    main()
Vielleicht kann man sich den Umweg über die LC sparen, aber dazu fällt mir kein Numpy-Boardmittel ein...

Re: Messwert in Array finden

Verfasst: Mittwoch 7. Juni 2017, 06:09
von Siegfried
@snafu: Vielleicht habe ich die Frage falsch verstanden.Ich dachte, es ginge um ein Array (ein- oder mehrdimensional), aus dem ein Wert extrahiert werden soll, der einem Suchwert am nächsten ist. Egal; sollte irgend jemand (wenn auch vielleicht der Fragesteller nicht) dieses Problem haben, könnte man analog zum Tutorial (https://docs.scipy.org/doc/numpy-dev/us ... ssing.html) auch eine `index`-Methode einbauen. Das Problem bei `argmin` ist, das es einen "flach geklopften" Index zurück gibt. Die `index` Methode paßt ihn an die Anzahl der Dimensionen an, d.h. sie funktioniert bei 1,2, ... dimensionalen Arrays.

[codebox=pys60 file=Unbenannt.txt]
import numpy as np

class ndarray_mit_index_funktion(np.ndarray):
def __new__(self, input_array, dtype=float, buffer=None, offset=0, strides=None, order=None):
return np.asarray(input_array, dtype, order).view(self)

def index(self, suchwert):
"""Sucht das erste Vorkommen eines Suchwertes und gibt den Index zurueck
Sollte der Wert nicht im Array vorhanden sein, wird der Index des Wertes
zurueckgegeben, der dem Suchwert am naechsten ist. Funktioniert nicht
fuer Zeichenketten"""
idx=abs(self-suchwert).argmin()
ergebnis=[]
for i in reversed(self.shape):
ergebnis.append(idx % i)
idx = idx // i
return tuple(reversed(ergebnis))

def main():
werte = ndarray_mit_index_funktion\
([[1.5, 2.8, 5.0, 11.9, 12.2, 14.9],[8, 9, 10, 11, 12.02, 13]])
suchindex = werte.index(12)
print("Das Listenelement mit der geringsten Abweichung ist:",werte[suchindex],"Listenindex:",suchindex)

if __name__ == '__main__':
main()

[/code]

Das Problem ist, daß wir nunmehr Funktionen `find_nearest_2D` bzw Methoden `index` haben, unsere Programme immer mehr Zeilen umfassen und dadurch für den Fragesteller der eigentliche Kern (hier Zeile 12) verloren gehen könnte.

Re: Messwert in Array finden

Verfasst: Mittwoch 7. Juni 2017, 08:50
von BlackJack
@Siegfried: Eine Klasse abzuleiten macht hier nicht wirklich Sinn. Eine Funktion ist *wesentlich* einfacher und ich sehe keinen Vorteil von einer Klasse.

Für die Umrechnung des flachen Index gibt es schon eine fertige Funktion in Numpy.

Den '\' am Zeilenende hättest Du Dir sparen können wenn Du die Klammer nicht auf die nächste Zeile verschoben hättest. Solange es noch ”offene” Klammern gibt, weiss der Compiler auch so dass der Ausdruck noch nicht zuende ist.

Als Funktion ist das ein Einzeiler:

Code: Alles auswählen

import numpy as np

 
def find_nearest_index(values, needle):
    """Sucht das erste Vorkommen eines Suchwertes und gibt den Index zurueck.

    Sollte der Wert nicht im Array vorhanden sein, wird der Index des Wertes
    zurueckgegeben, der dem Suchwert am naechsten ist. Funktioniert nicht
    fuer Zeichenketten.
    """
    return np.unravel_index(abs(values - needle).argmin(), values.shape)

 
def main():
    werte = np.array(
        [[1.5, 2.8, 5.0, 11.9, 12.2, 14.9], [8, 9, 10, 11, 12.02, 13]]
    )
    index = find_nearest_index(werte, 12)
    print(
        'Das Listenelement mit der geringsten Abweichung ist:',
        werte[index],
        'Listenindex:',
        index,
    )


if __name__ == '__main__':
    main()

Re: Messwert in Array finden

Verfasst: Mittwoch 7. Juni 2017, 08:57
von Sirius3
@snafu: das Zeilenweise finden des nächsten Wertes geht auch kurz:

Code: Alles auswählen

indices = abs(values - needle).argmin(axis=1)
nearest = values[range(values.shape[0]), indices]

Re: Messwert in Array finden

Verfasst: Mittwoch 7. Juni 2017, 18:52
von Siegfried
@BlackJack: Sehr kompakte und elegante Lösung. Und schon wieder habe ich etwas dazu gelernt. `unravel_index` wird nicht mehr vergessen. Zum Glück hat meine mühsame manuelle Lösung wenigstens die gleichen Ergebnisse gebracht.

Re: Messwert in Array finden

Verfasst: Donnerstag 8. Juni 2017, 11:25
von Siegfried
@snafu: Die zeilenweise Suche wird auch im NumPy Tutorial behandelt (https://docs.scipy.org/doc/numpy-dev/us ... of-indices). In diesem offiziellen Tutorial wird übrigens problematischer Weise ein Index in einer Variablen mit der krytischen Abkürzung `ind` abgespeichert.

Re: Messwert in Array finden

Verfasst: Donnerstag 8. Juni 2017, 11:34
von BlackJack
@Siegfried: Für Quelltexte gelten andere Richtlinien als für interaktive Python-Shell-Sitzungen die dazu auch noch innerhalb eines Tutorials stehen, wo alles ausführlich erklärt wird und kaum ein Name/Wert ausserhalb des jeweiligen, kleinen Ausschnitts der Python-Shell-Sitzung hinaus weiterverwendet wird. Zudem ist das eine Bibliothek für ein Spezialgebiet in dem die Leute an schlechte Namen gewöhnt sind. Was die Namen nicht besser macht. :-)

Re: Messwert in Array finden

Verfasst: Sonntag 11. Juni 2017, 17:12
von sanjo386
Diese Zeile

Code: Alles auswählen

4.index=abs(np.array(werte)-suchwert).argmin()
hat mir bereits geholfen. Darüber hinaus waren die weiteren Antworten auch hilfreich!

Gruß
Sanjo