Call a Python function inside a MATLAB loop

In a Matlab script, is there a way to call a Python function, in loop for, in such a way that at every iteration the inputs of the Python function are different?
This is my case, where the arrays "a" and "b" are always different, and they return, obviously, different outputs:
% My Python function
import numpy as np
from scipy import stats
a = [7, 42, 61, 81, 115, 137, 80, 100, 121, 140, 127, 110, 81, 39, 59, 45, 38, 32, 29, 27, 35, 25, 22, 20, 19, 14, 12, 9, 8, 6, 3, 2, 2, 0, 0, 1, 0, 1, 0, 0];
b = a;
rng = np.random.default_rng()
method = stats.PermutationMethod(n_resamples=9999, random_state=rng)
res = stats.anderson_ksamp([a,b], method=method)
print(res.statistic)
print(res.critical_values)
print(res.pvalue)
To add more details, I would like to have something like this in Matlab:
% Call my Python function inside a MATLAB loop
for i = 1 : 10
a = randi([1 100],1,50);
b = randi([1 100],1,50);
out = call_my_python_function_here(a,b);
end

6 Comments

I've never used Python, so obviously "I know nuthink!", but what keeps you from writing precisely what you want?
Sim
Sim on 5 Aug 2024
Edited: Sim on 5 Aug 2024
Hi @dpb, thanks for commenting... well... a bit long function to write from scratch, which has been already tested (within Python)... coupled to a shortage of time to accomplish some task.... :-)
I meant why can't you simply call the Python function inside the loop directly? Don't variables pass through to the Python functions just like they would with a native MATLAB function? Would seem it would be pretty worthless interface if not...
Sim
Sim on 5 Aug 2024
Edited: Sim on 5 Aug 2024
Yes, you are right, but..... I do not know how to do it.... :-)
I don't have Python installed so can't play at it, but looks to me like the basics of your function wish in MATLAB would simply be something about like
function stats=anderson(a,b)
stats=py.scipy.stats.anderson_ksamp([a,b]);
end
and you'd simply call it as any other MATLAB function.
The doc implies you don't need to import stuff (although you could for shorthand if were referencing the same module repeatedly) but just prefix with the py.module and it will resolve the name itself.
I ignored whatever you're trying to do with the RNG; you can deal with it as you see fit/need but if I were generating RNGs besides, I'd certainly call the native MATLAB version there, not pass that off to Python.
Thanks a lot @dpb! :-)

Sign in to comment.

Answers (2)

Hello Sim,
To call a Python function within a MATLAB loop with different inputs at each iteration, define your Python function and save it in a file, say my_python_function.py,ensure that your Python file is in the current working directory or the Python path.
In MATLAB, you can try using a similar code to call a Python function inside a loop
% Loop to call the Python function with different inputs
for i = 1:10
% Generate random arrays a and b
a = randi([1 100], 1, 50);
b = randi([1 100], 1, 50);
% Convert MATLAB arrays to Python lists
py_a = py.list(a);
py_b = py.list(b);
% Call the Python function
result = py.my_python_function.anderson_ksamp_test(py_a, py_b);
% Extract results from the Python function output
statistic = double(result{1});
critical_values = double(result{2});
pvalue = double(result{3});
% Display the results
fprintf('Iteration %d:\n', i);
fprintf('Statistic: %f\n', statistic);
fprintf('Critical Values: %s\n', mat2str(critical_values));
fprintf('P-value: %f\n', pvalue);
end
Here are some useful resources from MathWorks documentation that provide more details on how to integrate MATLAB and Python:
Hope this helps you in moving forward

11 Comments

Thanks a lot @Pavan Sahith!!
I tried to create my function, that I called anderson_darling.py
def anderson_darling(a,b):
import numpy as np
from scipy import stats
rng = np.random.default_rng()
method = stats.PermutationMethod(n_resamples=9999, random_state=rng)
res = stats.anderson_ksamp([a,b], method=method)
print(res.statistic)
print(res.critical_values)
print(res.pvalue)
which I saved in the current working directory.
However, once I run your code, I got the following error:
Unable to resolve the name 'py.anderson_darling.anderson_ksamp_test'.
Error in untitled (line 12)
result = py.anderson_darling.anderson_ksamp_test(py_a , py_b);
What am I doing wrong? :-(
def anderson_darling(a,b):
You do not define any property or sub-function named anderson_ksamp_test so it is not clear what py.anderson_darling.anderson_ksamp_test is intended to resolve to.
I "know nothink!" about Python, but I can't find any reference to def as a MATLAB name, @Walter Roberson? That looks like Python code(???) wearing MATLAB cape?
That's python code for sure.
Dear @dpb @Pavan Sahith @Walter Roberson Thanks a lot for your comments!! ...I think I am getting closer, but still something does not work..... I try to explain here below what I did...
I focused for a while on Python, and I can tell you that the following file, called "anderson_darling.py", works for me:
def ADtest(a,b):
rng = np.random.default_rng()
method = stats.PermutationMethod(n_resamples=9999, random_state=rng)
res = stats.anderson_ksamp([a,b], method=method)
print(a)
print(b)
print(res.statistic)
print(res.critical_values)
print(res.pvalue)
if __name__ == "__main__":
import sys
import numpy as np
from scipy import stats
input_list1 = list(map(int, sys.argv[1].strip('[]').split(',')))
input_list2 = list(map(int, sys.argv[2].strip('[]').split(',')))
a = np.array(input_list1)
b = np.array(input_list2)
ADtest(a,b)
To run this file, I opened a Terminal (throgh Visual Studio Code, but this is not relevant), then I went to the folder where my file "anderson_darling.py" was saved, and I gave the following command:
(base) xyz@xyz myfolder % python3 anderson_darling.py "[1,3,5,6,4,6,7,1,2,7]" "[1,3,5,6,4,6,7,1,2,7]"
The result, that appeared on the Terminal, was the following:
[1 3 5 6 4 6 7 1 2 7] % <-- array a
[1 3 5 6 4 6 7 1 2 7] % <-- array b
-1.4363560826434034 % <-- res.statistic
[0.325 1.226 1.961 2.718 3.752 4.592 6.546] % <-- res.critical_values
1.0 % <-- res.pvalue
After that, I thought to run the same function on the editor of Matlab, by following some of the indications of @Pavan Sahith, i.e.:
a = [1,3,5,6,4,6,7,1,2,7];
b = [1,3,5,6,4,6,7,1,2,7];
% Convert MATLAB arrays to Python lists
py_a = py.list(a);
py_b = py.list(b);
py.anderson_darling.ADtest(py_a,py_b)
but I got the following error on the Matlab Command Window:
Error using anderson_darling>ADtest
Python Error: NameError: name 'np' is not defined
If I got that error, it means that Matlab was able to go inside the Python function, but (I think) it was not able to read the command used to import the Python's "numpy", i.e.
import numpy as np
Am I doing something wrong with Matlab?
If it can help, my Python, Anaconda (the "numpy" and "scipy" packages are contained in (Ana)conda) and Matlab versions are the following ones:
From Terminal:
(base) xyz@xyz ~ % python3 --version
Python 3.12.4
(base) xyz@xyz ~ % conda --version
conda 24.7.1
(base) xyz@xyz ~ % conda info --envs
# conda environments:
#
base * /opt/anaconda3
/usr/local/anaconda3
From the Matlab's Command Window:
% Python Version for your system (inside Matlab)
% https://ch.mathworks.com/help/matlab/ref/pyenv.html
>> pyenv
ans =
PythonEnvironment with properties:
Version: "3.9"
Executable: "/Library/Developer/CommandLineTools/usr/bin/python3"
Library: "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/libpython3.9.dylib"
Home: "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9"
Status: Loaded
ExecutionMode: InProcess
ProcessID: "4128"
ProcessName: "MATLAB"
% Matlab version
>> version
ans =
'23.2.0.2515942 (R2023b) Update 7'
Sim
Sim on 7 Aug 2024
Edited: Sim on 7 Aug 2024
Or, maybe, someone at @MathWorks Support Team could help, if the problem is about the python paths, which allow "numpy" and "scipy" to be read by the Matlab system?
dpb
dpb on 7 Aug 2024
Edited: dpb on 7 Aug 2024
Again, "I know nuthink!", but that appears to me that if not running in the Python environment, the main logic branch that did the imports isn't getting called -- and that wouldn't suprprise me that startup code wouldn't be exercised from the MATLAB environment just as it isn't compiled into a DLL instead of an executable under C or Fortran.
I'd stick the necessary imports inside the function itself so they're defined there...
Mayhaps @Walter Roberson who runs Mac will stumble by and help, but I'd think <following the idea here> excepting for how to accomplish the same thing under Mac OS would fix it...
If messing around there doesn't help, I'd think it worthy of an official support Q?; remember Answers is "only" a volunteer site, not official support channel. Then again, they may tell you "unsupported" as an out in which case it'll be see if can get a hack to work.
I fail to understand the love for Python, but I'm an old dog past new tricks...
I know very very little about python, sorry.
Thanks @dpb and @Walter, I greatly appreciate your comments and help, thanks :-)

Sign in to comment.

Using <FEX Submittal> with your example dummy data, it generated the exact same statistic without all the mucking around with Python...
>> X=[[x.' ones(size(x)).'];[x.' 2*ones(size(x)).']]; % data with grouping variable 2nd column
AnDarksamtest(X)
K-sample Anderson-Darling Test
----------------------------------------------------------------------------
Number of samples: 2
Sample sizes: 10 10
Total number of observations: 20
Number of ties (identical values): 13
Mean of the Anderson-Darling rank statistic: 1
Standard deviation of the Anderson-Darling rank statistic: 0.6962062
----------------------------------------------------------------------------
Not adjusted for ties.
----------------------------------------------------------------------------
Anderson-Darling rank statistic: 0.0000000
Standardized Anderson-Darling rank statistic: -1.4363561
Probability associated to the Anderson-Darling rank statistic = 0.8963729
...
It looks to be well done, theoretically and is completely documented in the file as to how is computed, including the interpolation to return the critical values...

5 Comments

Thanks @dpb, very kind... I tried some days ago that one... But the thing is... If I perform the 2-sample AD test using that code, and between an array/distribution (the first sample) and itself (the second sample), the p-value, that to my understanding is the "Probability associated to the Anderson-Darling rank statistic", should be equal to 1, and not to 0.8963729. The 2-sample AD test, still performed among the same array/distribution with itself, by using the Python implementation, returns a p-value equal to 1. So, why this mismatch? Shouldn't the p-value be 1, when I compare an array/distribution with itself, as resulting from the 2-sample AD test implemented in Python?
But they computed identical test statistic, so the base is the same; at worst perhaps the interpolation used for the p-value may break down if the two are identical; I'd have to go read the guts of the code itself.
But, you'll note that the FEX submission also tells you that specifically...
"The populations from which the k-samples of data were drawn are identical: natural groupings have no significant effect (unstructurated)."
I would think the real case of having identical distributions would be nil and there's no need to run the statistical test to tell you that.
If it were me, I'd look into that just a little rather than beating my head against the wall with Python.
Sim
Sim on 7 Aug 2024
Edited: Sim on 7 Aug 2024
Yes, you are perfectly right... These are just some thoughts that I have for days, maybe already a week... I mean, yes, that Matlab code looks a great implementation of the Scholz and Stephens (1987) paper, or at least the math written there looks the same... But then, why is there some discrepancy in the p-values between the MATLAB and the Python implementations? I am not able to see the details of the Python code, even though they refer to the same paper... So what could be different? Of course the base is/should be the same, and of course the p-value alone is not sufficient to draw conclusions on a statistical hypothesis test(e.g. type I and type II errors)... But still... That mismatch on the p-values between the two implementations leaves me some doubt, especially when reviewers pointed towards those values, in other tests, criticizing them a lot... Yes, probably better to use the MATLAB function of the k-sample AD test and move on...
The critical values for A-D are/were derived by simulation, not theoretically and any software implementation is using some sort of interpolation or lookup from those. It's quite possible internal to the Python implementation the case of identical distributions is special-cased and returns the integer unity value for that reason.
The interpolation technique used in the FEX submission is at least documented and you can figure out by comparison to the tables if it is breaking down near boundaries (which wouldn't be too surprising if so). Being as that is the case, it's likely the original tables don't go to the extreme with what is, in this case a very small sample size of only 10 elements and so exact values from the published table(s) may not be available for the specific case.
"...especially when reviewers pointed towards those values, in other tests, criticizing them a lot..."
Who/where might that be? On the Python or FEX side? I'd take the open version that can look at in detail over one I couldn't see; I'm not actually sure about what the "right" answer would be for the case without more consideration; it's been too long since I really studied it.
Yes, it might be something related to the table... Right...
About the reviewers, well, they were "from" a journal of the Nature Portfolio..
Yes, it is wiser to take an open version, to be then able to check what you are doing :-)

Sign in to comment.

Asked:

Sim
on 5 Aug 2024

Commented:

Sim
on 7 Aug 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!