String in ndarray für numpy wandeln

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Benutzeravatar
nieselfriem
User
Beiträge: 135
Registriert: Sonntag 13. Januar 2013, 16:00

Hallo,

ich möchte ein wenig in QT und numpy was ausprobieren. Dabei habe ich ein QLineEdit in dem eine Funktion stehen soll, z.B. "x**2" und diese soll dann mit matplotlib und numpy als Graph ausgegeben werden. Doch leider scheitert das Thema an dem datentypen für numpy

ich kann für numpy eine Funktion ja wie folgt angeben

Code: Alles auswählen

y = 0.5*x*2-9  
Nun liefert aber QLineEdit diese Funktion als String. Wie kann ich diesen String als Datentyp für numpy konvertieren?

vg niesel
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Schau Dir das mal an

Code: Alles auswählen

from PyQt4.QtCore import QString
import numpy as np
import matplotlib.pyplot as plt

lineEditOutput = QString("0.5*x*2-9")
my_function_str = unicode(lineEditOutput)
my_function = eval("lambda x: " + my_function_str)
x = np.linspace(0,5,21)
y = my_function(x)

plt.figure()
plt.plot(x,y)
plt.show()
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hier ist das umfangreiche SymPy-Package ein gutes Bindeglied:

Code: Alles auswählen

import numpy as np
from sympy.abc import x, y
from sympy.parsing.sympy_parser import parse_expr
from sympy.utilities.lambdify import lambdify

def make_func(string, symbols=(x,)):
    return lambdify(symbols, parse_expr(string))

def main():
    xs = np.linspace(0, 1, 5)
    double = make_func('x*2')
    print('Original:', xs)
    print('Double:', double(xs))
    print()
    xs = np.linspace(0, 2, 3)
    ys = np.linspace(2, 4, 3)
    formula = '(x + 1) * (y + 2)'
    f = make_func(formula, (x, y))
    print('xs:', xs)
    print('ys:', ys)
    print('Formula:', formula)
    print('->', f(xs, ys))

if __name__ == '__main__':
    main()
Dies hat gegenüber der Lösung von MagBen den Vorteil, dass nicht beliebiger (Schad-)Code ausgeführt wird. Außerdem ist es flexibler in Bezug auf zusätzliche Symbole. Bringt einem zwar eine zusätzliche Abhängigkeit an, aber das ist bei wissenschaftlichen Anwendungsgebieten ja sowieso üblich.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Übergabe der SymPy-Symbole kann man übrigens auch abstrahieren (z.B. damit der Aufrufer sich den SymPy-Import spart):

Code: Alles auswählen

import numpy as np
from sympy import symbols
from sympy.parsing.sympy_parser import parse_expr
from sympy.utilities.lambdify import lambdify

def make_func(string, used_symbols='x'):
    return lambdify(symbols(used_symbols), parse_expr(string))

def main():
    f = make_func('x*2')
    g = make_func('x+y', used_symbols='x, y')
    xs = np.linspace(0, 1, 5)
    print('x-values:', xs)
    ys = np.linspace(2, 3, 5)
    print('y-values:', ys)
    print('f(x) = x * 2 ->', f(xs))
    print('g(x, y) = x + y ->', g(xs, ys))

if __name__ == '__main__':
    main()
Antworten