Von Matlab nach Python - eval()-Befehl

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
DanielHexlon
User
Beiträge: 1
Registriert: Samstag 16. September 2017, 22:58

Hallo zusammen, ich habe ein Matlab-Script, welches ich gerne in Python umschreiben möchte. Zunächst mal der ursprüngliche (Teil des) MATLAB-CODE als Minimalbeispiel:

Code: Alles auswählen

ParamName=['x'; 'b'; 's'];                                     
initDisPar=[0.9 1.1; 0 0.05; 0.01 0.1];                        
n=5e3;                                                          

p=size(ParamName,1);
for j=1:p;                                                      
    param(j,:)= unifrnd(initDisPar(j,1),initDisPar(j,2),1,n); 
    ParamResul(j,:)=[ParamName(j,:) 'Resul'] 
    eval([ParamResul(j,:) '=param(j,:);']); 
end;                       
Und mein bisheriger Versuch, das ganze in Python umzusetzen

Code: Alles auswählen

import numpy as np

ParamName = np.array([['x'], ['b'], ['s']], dtype=str)                                    
initDisPar = np.array([[0.9, 1.1], [0, 0.05], [0.01, 0.1]])                            	
n = 5000                                                                                    		
                                                                            
p = ParamName.size
param = np.empty([p, n])

for j in range (0, p):                                                                        
    param[j,:] = np.random.uniform(initDisPar[j,0],initDisPar[j,1], n)   
    ParamResul = np.core.defchararray.add(ParamName, 'Resul')                               
    ParamResul[j] = eval('param[j,:]')
Dabei bekomme ich folgenden Fehler :roll:
ValueError: could not broadcast input array from shape (5000) into shape (1)
Meine Frage lautet nun... Wie schreibe ich den eval()-Befehl in Python, damit er mir dynamisch die Variablen
"xResul, bResul, sResul" als Array [1x5000] erzeugt und dort die zugehörigen 5000 Werte von "param" (aus der zugehörigen Zeile) hineinschreibt...

Vielen Dank schon mal im Voraus an alle, die sich damit beschäftigen!
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@DanielHexlon: auch in Matlab sollte man nicht eval verwenden, um Variablennamen zu erzeugen; Variablenzuweisungen sollten immer direkt da stehen, damit man einfach nachvollziehen kann, wo welcher Wert gesetzt wurde. Zudem Frage ich mich gerade was ein Resul ist? Fehlt da einfach nur ein `t`? Dann Frage ich mich, wafür die Zufallszahlen gut sind, denn dass das schon das Ergebnis ist, bezweifle ich mal. Variablennamen sollten aussagen, was sie denn enthalten. Sie enthalten immer das Ergebnis von irgendwas, somit hilft diese Beschreibung niemandem, das Programm zu verstehen.

Das matlab-Programm könnte ungefähr so aussehen:
[codebox=matlab file=Unbenannt.m]
distribution_parameters = struct();
distribution_parameters.x = [0.9 1.1];
distribution_parameters.b = [0 0.05];
distribution_parameters.s = [0.01 0.1];
amount = 5000;

distributions = struct();
fields = fieldnames(distribution_parameters);
for j=1:length(fields)
field = fields(j);
params = distribution_parameters.(field);
distributions.(field) = unifrnd(params(1), params(2), 1, amount)
end;
[/code]

Und alles gesagte gilt ebenso für Python. Die ParamNames würde man nicht in ein Numpy-Array schreiben, sondern in eine normale Liste. Auch bei initDisPar würde ich noch eine normale Liste bzw. Tupel nehmen. Das eigentliche Problem ist, dass Du für ParamResul eine Funktion benutzt, die garantiert nicht dafür gedacht ist direkt aufgerufen zu werden, und von der ich auch noch nie etwas gehört habe. Sie erzeugt jedenfalls ein Zeichen-Array, dem Du versuchst ein Array mit 5000 Werten zuzuweisen. Der eval-Befehl in matlab sah auch ganz anders aus (und sollte auch weder hier noch da benutzt werden).

Das umgeschriebene Matlab läßt sich dagegen ganz einfach in Python umsetzen. Aus struct werden Wörterbücher:

Code: Alles auswählen

distribution_parameters = {
    'x': (0.9, 1.1),
    'b': (0, 0.05),
    's': (0.01, 0.1),
}
amount = 5000

distributions = {}
for field, params in distribution_parameters.items():
    distributions[field] = np.random.uniform(params[0], params[1], amount)
Antworten