I have a function that produces an array within it, and I want to do work on the generated array outside of the function, in python. How can I make the function save the array such that this can be done?
Thanks!
My function is here:
def lane_emden(n, delxi=0.00001, xilim=25):
theta = 1
dtdx = 0
xi = 0.01
#Starting values
dtdx_values = [dtdx]
theta_values = [theta]
xi_values = [xi]
#Initial values for the lists
while theta>=0 and xi<=xilim :
dtdx_new = dtdx - ((2*(2/xi*dtdx)) + theta**n)*delxi
theta_new = theta + delxi*dtdx_new
xi_new = xi + delxi
#Equations to create new values for iterative diff eq solving
dtdx = dtdx_new
theta = theta_new
xi = xi_new
#Replace the old values with the new ones
dtdx_values.append(dtdx)
theta_values.append(theta)
xi_values.append(xi)
#Store these new values in previously defined lists
results = np.array((theta_values, xi_values))
#create an array of the results (probably done incorrectly)
return results
#This is how I tried to get the array saved outside the function
I'm very new to Python, any help would be greatly appreciated!
[Edit] Function call as requested.
Input
lane_emden(5)
Output
array([[ 1.00000000e+00, 1.00000000e+00, 1.00000000e+00, ...,
2.10576105e-01, 2.10576063e-01, 2.10576022e-01],
[ 1.00000000e-02, 1.00100000e-02, 1.00200000e-02, ...,
2.49999900e+01, 2.50000000e+01, 2.50000100e+01]])
You already return your array, so now you just need to use it. array = lane_emden(3) for example.
Looks like you are using numpy: results = np.array((theta_values, xi_values)). The documentation for numpy.array() states the first argument must be an array-like object:
An array, any object exposing the array interface, an object whose array method returns an array, or any (nested) sequence.
I think you want numpy.asarray() instead: results = np.asarray((theta_values, xi_values)).
Related
This MATLAB code is from Main_MOHHO.m from https://www.mathworks.com/matlabcentral/fileexchange/80776-multi-objective-harris-hawks-optimization-mohho. I want to make the same code using python, but I can't make the Rabbits variabel.
clc;
clear;
close all;
%% Problem Definition
nVar=3; % Number of Decision Variables
VarSize=[1 nVar]; % Size of Decision Variables Matrix
VarMin=0; % Lower Bound of Variables
VarMax=1; % Upper Bound of Variables
nPop=5; % Population Size
%% Initialization
empty_Rabbit.Location=[];
empty_Rabbit.Cost=[];
empty_Rabbit.Sol=[];
empty_Rabbit.IsDominated=[];
empty_Rabbit.GridIndex=[];
empty_Rabbit.GridSubIndex=[];
Rabbits=repmat(empty_Rabbit,nPop,1);
for i=1:nPop
Rabbits(i).Location = rand(VarSize).*(VarMax-VarMin)+VarMin;
X(i,:) = rand(VarSize).*(VarMax-VarMin)+VarMin;
end
I try to make it on google colab like this.
import numpy as np
nVar = 3 # Number of Decision Variables
VarSize = np.array((1, nVar)) # Size of Decision Variables Matrix
VarMin = 0 # Lower Bound of Variables
VarMax = 1 # Upper Bound of Variables
nPop = 5 # Population Size
class empty_Rabbit:
Location = []
Cost = []
IsDominated = []
GridIndex = []
GridSubIndex = []
Sol = []
Rabbits = np.tile(empty_Rabbit, (nPop, 1))
X = np.zeros((nPop, nVar))
Rabbit_Location = np.zeros((VarSize))
Rabbit_Energy = math.inf
for i in range(nPop):
Rabbits[i, 0].Location = np.multiply(np.random.rand(VarSize[0], VarSize[1]),
(VarMax-VarMin) + VarMin)
print(Rabbits[i,0].Location)
But, the Rabbits_Location same for each row.
Output Google Colab
What is the correct way to create Rabbits variable in python so the output like the output with number 1 in the pic? Thank you.
Two issues exist in your code. First, np.tile repeats the same object (nPop, 1) times. So, when you change one of the objects, you actually change the same memory location. Second, you want to initialize a different object each time instead of referring to the same object, so you want to write empty_Rabbit() to create a new instance of that object. Both suggestions can be achieved using a comprehension like [empty_Rabbit() for i in range(nPop)] and reshape to any new dimensions if required.
import numpy as np
nVar = 3 # Number of Decision Variables
VarSize = np.array((1, nVar)) # Size of Decision Variables Matrix
VarMin = 0 # Lower Bound of Variables
VarMax = 1 # Upper Bound of Variables
nPop = 5 # Population Size
class empty_Rabbit:
Location = []
Cost = []
IsDominated = []
GridIndex = []
GridSubIndex = []
Sol = []
Rabbits = np.array([empty_Rabbit() for i in range(nPop)]).reshape(nPop,1)
X = np.zeros((nPop, nVar))
Rabbit_Location = np.zeros((VarSize))
Rabbit_Energy = np.inf
for i in range(nPop):
Rabbits[i, 0].Location = np.multiply(np.random.rand(VarSize[0], VarSize[1]),
(VarMax-VarMin) + VarMin)
print(Rabbits[i,0].Location)
for i in range(nPop):
print(Rabbits[i,0].Location)
Now, the output of both print statements will be identical with distinct rows:
[[0.5392264 0.39375339 0.59483626]]
[[0.53959355 0.91049574 0.58115175]]
[[0.46152304 0.43111977 0.06882631]]
[[0.13693784 0.82075653 0.49488394]]
[[0.06901317 0.34133836 0.91453956]]
[[0.5392264 0.39375339 0.59483626]]
[[0.53959355 0.91049574 0.58115175]]
[[0.46152304 0.43111977 0.06882631]]
[[0.13693784 0.82075653 0.49488394]]
[[0.06901317 0.34133836 0.91453956]]
scipy.io.loadmat uses structured arrays when loading struct from MATLAB .mat files. But I think that's too advanced for you.
I think you need to create a set of numpy arrays, rather than try for some sort of class or more complicated structure.
empty_Rabbit.Location=[];
empty_Rabbit.Cost=[];
empty_Rabbit.Sol=[];
empty_Rabbit.IsDominated=[];
empty_Rabbit.GridIndex=[];
empty_Rabbit.GridSubIndex=[];
becomes instead
location = np.zeros(nPop)
cost = np.zeros(nPop)
sol = np.zeros(nPop)
isDominated = np.zeros(nPop) # or bool dtype?
gridIndex = np.zeros(nPop)
gridSubIndex = np.zeros(nPop)
np.zeros makes a float array; for some of those you might want np.zeros(nPop, dtype=int) (if used as index).
rabbit= np.zeros(nPop, dtype=[('location',float), ('cost',float),('sol',float), ....])
could be used to make structured array, but you'll need to read more about those.
MATLAB lets you use iteration freely as in
for i=1:nPop
Rabbits(i).Location = rand(VarSize).*(VarMax-VarMin)+VarMin;
X(i,:) = rand(VarSize).*(VarMax-VarMin)+VarMin;
end
but that's slow (as it used to be MATLAB before jit compilation). It's better to use whole array calculations
location = np.random.rand(nPop,VarSize) * (VarMax-VarMin)+VarMin
will make a (nPop,VarSize) 2d array, not the 1d that np.zeros(nPop) created.
Looks like X could be created in the same way (without iteration).
a:
[array([[0.10865657, 0.10638294, 0.10471012, 0.09508586, 0.09283491],
[0.10892282, 0.10664408, 0.10496752, 0.09531553, 0.09305617],
[0.11664 , 0.1143077 , 0.11259081, 0.1026154 , 0.10025029],
[0.11626453, 0.11392252, 0.11219875, 0.10217754, 0.09980005]]),
array([[0.04213751, 0.04178241, 0.04158858, 0.04331489, 0.04447674],
[0.04213751, 0.04178241, 0.04158858, 0.04331489, 0.04447674],
[0.04267657, 0.04255925, 0.04253528, 0.04520177, 0.04655534],
...
I can do a[0].mean and I will get desired result. By I want to do it to the whole length of the 'a' with for loop.
I have tried:
mean_all = []
for i in len(dist):
mean = dist[i].mean
mean_all.append(mean)
TypeError: 'int' object is not iterable
First of all, dist[0].mean returns a function and NOT the mean. You need, in general, dist[0].mean().
You can avoid the for loop easily using list comprehension:
from numpy import array
dist = [array([[0.10865657, 0.10638294, 0.10471012, 0.09508586, 0.09283491],
[0.10892282, 0.10664408, 0.10496752, 0.09531553, 0.09305617],
[0.11664 , 0.1143077 , 0.11259081, 0.1026154 , 0.10025029],
[0.11626453, 0.11392252, 0.11219875, 0.10217754, 0.09980005]]),
array([[0.04213751, 0.04178241, 0.04158858, 0.04331489, 0.04447674],
[0.04213751, 0.04178241, 0.04158858, 0.04331489, 0.04447674],
[0.04267657, 0.04255925, 0.04253528, 0.04520177, 0.04655534]])]
mean_all = [dist[i].mean() for i in range(len(dist))]
print(mean_all)
[0.10536720549999998, 0.04307523133333334]
If you really want to use the for loop, use this:
mean_all = []
for i in range(len(dist)):
mean = dist[i].mean()
mean_all.append(mean)
print(mean_all)
[0.10536720549999998, 0.04307523133333334]
Use the correct format of using range()
for i in range(len(dist))
I am trying to iterate through a CSV file and create a numpy array for each row in the file, where the first column represents the x-coordinates and the second column represents the y-coordinates. I then am trying to append each array into a master array and return it.
import numpy as np
thedoc = open("data.csv")
headers = thedoc.readline()
def generatingArray(thedoc):
masterArray = np.array([])
for numbers in thedoc:
editDocument = numbers.strip().split(",")
x = editDocument[0]
y = editDocument[1]
createdArray = np.array((x, y))
masterArray = np.append([createdArray])
return masterArray
print(generatingArray(thedoc))
I am hoping to see an array with all the CSV info in it. Instead, I receive an error: "append() missing 1 required positional argument: 'values'
Any help on where my error is and how to fix it is greatly appreciated!
Numpy arrays don't magically grow in the same way that python lists do. You need to allocate the space for the array in your "masterArray = np.array([])" function call before you add everything to it.
The best answer is to import directly to a numpy array using something like genfromtxt (https://docs.scipy.org/doc/numpy-1.10.1/user/basics.io.genfromtxt.html) but...
If you know the number of lines you're reading in, or you can get it using something like this.
file_length = len(open("data.csv").readlines())
Then you can preallocate the numpy array to do something like this:
masterArray = np.empty((file_length, 2))
for i, numbers in enumerate(thedoc):
editDocument = numbers.strip().split(",")
x = editDocument[0]
y = editDocument[1]
masterArray[i] = [x, y]
I would recommend the first method but if you're lazy then you can always just build a python list and then make a numpy array.
masterArray = []
for numbers in thedoc:
editDocument = numbers.strip().split(",")
x = editDocument[0]
y = editDocument[1]
createdArray = [x, y]
masterArray.append(createdArray)
return np.array(masterArray)
My data is as follows:
mx_ranges1 = [
(848,888),
(806,848),
(764,806),
(722,764),
(680,722),
(638,680),
(596,638),
(554,596),
(512,554),
(470,512),
(428,470),
(386,428),
(344,386),
(302,344),
(260,302),
(218,260),
(176,218),
(134,176),
]
a=((mx_ranges1[0][1]-mx_ranges1[0][0])/2)+(mx_ranges1[0][0])
b=((mx_ranges1[1][1]-mx_ranges1[1][0])/2)+(mx_ranges1[1][0])
c=((mx_ranges1[2][1]-mx_ranges1[2][0])/2)+(mx_ranges1[3][0])
print(a)
print(b)
print(c)`
That way is not really efficient, I know it can somehow be represented in a for loop, I just don't know how I might do it. Please give me some references since I'm new to python and programming in general. I then have another list with y which also need to take the distance then add it to the first element.
Not sure if it can be placed directly into a single 2D array but just doing the first part should be good enough for me. I can do the rest manually.
You can use a simple list comprehension:
[(j-i)/2 + i for i,j in mx_ranges1]
# [868.0, 827.0, 785.0, 743.0, 701.0, 659.0, 617.0 ...
Which is equivalent to the following for loop:
res = []
for i,j in mx_ranges1:
res.append((j-i)/2 + i)
You also mention using numpy arrays. Note that this would be the most efficient and simple way to do it, as it is a matter of Basic Slicing and Indexing:
a = np.array(mx_ranges1)
(a[:,1] - a[:,0]) /2 + a[:,0]
# array([868., 827., 785., 743., ...
Numpy will be much faster!
import numpy as np
mx_ranges1 = [
(848,888),
(806,848),
(764,806),
(722,764),
(680,722),
(638,680),
(596,638),
(554,596),
(512,554),
(470,512),
(428,470),
(386,428),
(344,386),
(302,344),
(260,302),
(218,260),
(176,218),
(134,176),
]
a = np.array(mx_ranges1)
# the first index accessor : says all rows, the second specifies a column
result = (a[:,1] - a[:,0])/2 + a[:,0]
# result contains one value for each row/tuple in `mx_ranges1`
print(result)
This returns:
[868. 827. 785. 743. 701. 659. 617. 575. 533. 491. 449. 407. 365. 323.
281. 239. 197. 155.]
Which contains one value for each row of your input 2D array. So 868 = 888-848/2 + 848.
I have my geographical coordinates of rectangles represented as numpy ndarray like this:
(each row corresponds to a rectangle and each column contains its lower left and upper right longitudes and latitudes)
array([
[ 116.17265886, 39.92265886, 116.1761427 , 39.92536232],
[ 116.20749721, 39.90373467, 116.21098105, 39.90643813],
[ 116.21794872, 39.90373467, 116.22143255, 39.90643813]])
I want to call a coordinate-converting API whose input is a string like this:
'lon_0,lat_0;lon_1,lat_1;lon_2,lat_2;...;lon_n,lat_n'
So I wrote a stupid iteration to convert my ndarray to the required string like this:
coords = ''
for i in range(0, my_rectangle.shape[0]):
coords = coords + '{left_lon},{left_lat};{right_lon},{rigth_lat}'.format(left_lon = my_rectangle[i][0], left_lat = my_rectangle[i][1], \
right_lon = my_rectangle[i][2], rigth_lat = my_rectangle[i][3])
if i != my_rectangle.shape[0] - 1:
coords = coords + ';'
And the output is like this:
'116.172658863,39.9226588629;116.176142698,39.9253623188;116.207497213,39.9037346711;116.210981048,39.9064381271;116.217948718,39.9037346711;116.221432553,39.9064381271'
I'm wondering whether there exists a smarter & faster approach achieving this without iteration(or some helpful documentation I could refer to)?
Let's try using functional style:
values = [[ 116.17265886, 39.92265886, 116.1761427 , 39.92536232],
[ 116.20749721, 39.90373467, 116.21098105, 39.90643813],
[ 116.21794872, 39.90373467, 116.22143255, 39.90643813]]
def prettyPrint(coords):
return '{0},{1};{2},{3}'.format(coords[0], coords[1], coords[2], coords[3])
asString = formating(list(map(prettyPrint,values)))
print(";".join(asString)) #edited thanks to comments
map apply a function to each element of an iterable. So you define the process to apply on one element, and then using map replace each element by its result.
Hope you find it smarter ;)
Edit :
You can also write it like this :
asString = [prettyPrint(value) for value in values]