Mit Numpy arrays rechnen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
zaxizax
User
Beiträge: 4
Registriert: Donnerstag 28. November 2019, 19:17

Hallo werte Community :)

Bin noch recht neu in der Python Welt, und verzweifle gerade an folgender Aufgabe.
Möchte mir gerne die Differenz von Werten in einer Spalte berechnen lassen.
Wenn diese "Soll-Differenz" im Beispiel genannt "neutral_loss" gefunden wurde, sollen beide Zeilen mit vollständigem Inhalt angezeigt werden.
Wie ihr im "Output" sehen könnt, funktioniert das, abgesehen von ein paar mir unklaren Fehlern auch halbwegs OK.

Warum ich aber um eure Hilfe bitte, ist folgendes:

Es soll jeder Spalteneintrag gegen jeden Spalteneintrag verglichen werden.
Hätte das mit "line1 += 1", aber ich glaube ich habe die falsche Position im Code gewählt.

Es funktioniert auch folgendes nicht: len(list) - > die Idee wäre dabei, die Gesamtanzahl der Spalteneinträge damit berechnen zu lassen.

Vielen Dank schon mal :)


Code:

import numpy as np
list = ([10,20,30,40,50],[12,13,22,32,42])
a = np.array(list)
row_1 = 0
line_1 = 0
line_2 = 0
neutral_loss = 20
deviation = 0.1
lower_bound = float(neutral_loss - deviation)
upper_bound = float(neutral_loss + deviation)
j = 1
k = 1
while k < 2:
while j < len(list):
b = float(a[row_1, line_1])
c = float(a[row_1, line_2])
#print(b)
#print(c)
if abs(b - c) >= lower_bound and abs(b - c) <= upper_bound:
print(a[row_1, :])
print(a[row_1+1, :])
line_2 = line_2 + 1
else:
print("No result!")
line_2 = line_2 + 1
j += 1
#line_1 += 1
k +=1


Output:

Traceback (most recent call last):
File "C:/.../PycharmProjects/neutral_loss/neutral_loss.py", line 16, in <module>
c = float(a[row_1, line_2])
IndexError: index 5 is out of bounds for axis 1 with size 5
No result!
No result!
[10 20 30 40 50]
[12 13 22 32 42]
No result!
No result!

Process finished with exit code 1
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@zaxizax: `list` ist der Name des eingebauten Datentyps `list`, den Namen sollte man nicht an etwas anderes binden.

Mal davon abgesehen das Grunddatentypen nichts in Namen verloren haben ist es extrem verwirrend wenn die dann nicht mal stimmen. Du bindest nämlich keine Liste an `list` sondern ein Tupel.

`list` wird auch gar nicht wirklich verwendet, denn aus dem Inhalt wird ein Numpy-Array erstellt und man kann dann auch einfach immer *das* statt dem Tupel verwenden.

Die ganzen `float()`-Aufrufe machen keinen Sinn, die kann man entfernen.

`j` und `k` werden nicht wirklich verwendet, denn innerhalb der Schleifen wo sie als Bedingung verwendet werden, ändert sich der Wert nicht, womit beide Schleifen *Endlosschleifen* sind. Und da in der äusseren Endlosschleife eine innere Endlosschleife steckt, kann man die äussere auch entfernen, weil vor der inneren nichts gemacht wird, und die innere ja nie verlassen wird, womit die äussere Schleife einmal ausgeführt wird, beziehungsweise nicht einmal das.

Mir ist nicht so ganz klar ob Du weisst das sowohl `row` als auch `line` auf Deutsch *Zeile* heisst‽ Bist Du sicher das `line` nicht eigentlich `column` (Spalte) heissen sollte‽

Die ``if``-Bedingung lässt sich als verkettete Bedingung einfacher und lesbarer ausdrücken. Da muss dann der Betrag von b-c auch nur *einmal* ausgerechnet werden.

Statt ``name = name + 1`` kann man auch ``name += 1`` schreiben.

Wenn etwas sowohl im ``if``- als auch im ``else``-Zweig am Ende steht, kann man das auch *einmal* und *hinter* die beiden Zweige schreiben, denn dann hängt es ja gar nicht von der Bedingung ab, sondern wird immer ausgeführt.

Dein Code macht letztlich das gleiche wie dieser hier:

Code: Alles auswählen

#!/usr/bin/env python3
import numpy as np


def main():
    a = np.array([[10, 20, 30, 40, 50], [12, 13, 22, 32, 42]])
    neutral_loss = 20
    deviation = 0.1
    lower_bound = neutral_loss - deviation
    upper_bound = neutral_loss + deviation
    column = 0
    b = a[0, 0]
    while True:
        c = a[0, column]
        if lower_bound <= abs(b - c) <= upper_bound:
            print(a[0])
            print(a[1])
        else:
            print("No result!")
        column += 1


if __name__ == "__main__":
    main()
Hoffentlich siehst Du jetzt warum es zu dem `IndexError` kommt. Da ist nichts was den verhindern würde.

Mir ist nicht klar was Du tatsächlich machen wolltest.

Edit: `row` wird ja auch nicht wirklich sinnvoll verwendet und ”kopieren” muss man die Zeilen für die Ausgabe auch nicht wirklich.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
zaxizax
User
Beiträge: 4
Registriert: Donnerstag 28. November 2019, 19:17

wow. vielen dank für diese rasche und hilfreiche antwort :)

da ich als chemiker mit programmieren bisher gar nichts am hut hatte, war dieser erstellte code, einfach learning by doing mit Hilfe simpler Youtube Tutorials. Da ich als völliger Laie, keine Ahnung vom Aufbau von Loops bzw. generell vom programmieren habe, bin ich wie du gesehen hast, sehr sehr seeeehr schnell an die Grenzen gestossen.

mein eigentliches ziel ist es, eine .csv einlesen zu lassen, die folgendes enthält:

CompoundNr, Masse, Retentionszeit, Spezies
1, 200, 4.5, H+
2, 300, 6.2, H+
3, 400, 5.5, H+
4, 900, 3.2, H+
5, 1000, 4.8, H+

Mein Code soll nun jede Masse miteinander vergleichen, und wenn nun eine Massendifferenz = 100 ist, sollen beide Zeilen vollständig ausgegeben werden, die die Massen mit der neutral_loss oder Massendifferenz = 100 ergeben

ergebnis:

1, 200, 4.5, H+
2, 300, 6.2, H+

und

2, 300, 6.2, H+
3, 400, 5.5, H+

und

4, 900, 3.2, H+
5, 1000, 4.8, H+
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@zaxizax: Ich sehe hier gerade nicht wirklich wozu das Numpy gut sein soll. Pandas kann helfen um das einfacher einzulesen als mit dem `csv`-Modul, und damit hätte man dann indirekt Numpy an Bord. Aber dieser Algorithmus ist wohl eher nicht so gut parallelisierbar.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
zaxizax
User
Beiträge: 4
Registriert: Donnerstag 28. November 2019, 19:17

danke. werde mich da weiter einlesen
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Die Bedingung ist nicht wie von Dir gewünscht, aber das ist ja eher der unwichtige Teil:

Code: Alles auswählen

#!/usr/bin/env python3
import io
from itertools import combinations

import pandas as pd

SOURCE = """\
CompoundNr, Masse, Retentionszeit, Spezies
1, 200, 4.5, H+
2, 300, 6.2, H+
3, 400, 5.5, H+
4, 900, 3.2, H+
5, 1000, 4.8, H+
"""


def main():
    data = pd.read_csv(io.StringIO(SOURCE), index_col=0, skipinitialspace=True)
    mass = data["Masse"]
    for row_index_a, row_index_b in combinations(range(len(mass)), 2):
        if abs(mass.iloc[row_index_a] - mass.iloc[row_index_b]) <= 100.1:
            print(data.iloc[[row_index_a, row_index_b]])
            print()


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
zaxizax
User
Beiträge: 4
Registriert: Donnerstag 28. November 2019, 19:17

wow. kann dir gar nicht sagen, wie begeistert ich von deinem programm bin :)

vielen vielen lieben dank schon mal werter Herr _blackjack_


habe dein programm nun an meine bedingungen angepasst:

import io
from itertools import combinations

import pandas as pd

def main():
neutral_loss = 20
deviation = 0.1
lower_bound = neutral_loss - deviation
upper_bound = neutral_loss + deviation
data = pd.read_csv('mass.csv', index_col=0, skipinitialspace=True)
mass = data["Mass"]
for row_index_a, row_index_b in combinations(range(len(mass)), 2):
if lower_bound <= abs(mass.iloc[row_index_a] - mass.iloc[row_index_b]) <= upper_bound:
print(data.iloc[[row_index_a, row_index_b]])
print()
a = data.iloc[[row_index_a, row_index_b]]

a.to_csv('mass_modified.csv')

if __name__ == "__main__":
main()


jez scheiterts nur mehr daran, dass "a" mit jeder if bedingung überspeichert wird, und in meiner ausgegebenen .csv nur der letzte data.iloc eintrag steht :(

sollte dies aber nicht möglich sein, auch kein problem. dein programm ist so oder so schon eine riiiiiiiesen hilfe :)
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Du kannst ja jedes "a" was erzeugt wird in einer Liste speichern.(Wobei "a" kein guter Variablenname ist) Dann beim schreiben in die .csv einfach über diese Liste iterieren.
Antworten