Unzip a NumPy array - python

I am trying two print the columns individually of a variable I obtained by applying a function from zipping two variables. Please find below:
x5 = list(zip(x3,x4))
x6 = np.array(x5)
print(x6)
Applying the function:
n = 1
br = myfunction(x3,x4,n)
print('this is the result ... ', br)
Note as suggested, a reproducible way of generating data of the type myfunction outputs is:
br = numpy.random.rand((5, 2))
Output looks like this :
finally result ... [[[5.37692693e+03 3.78425697e-
03]
[1.36092539e+03 3.35722632e-03]
[5.43477586e+03 3.90104194e-03]
...
[5.93759455e+03 4.05490440e-03]
[3.00855802e+03 3.65746871e-03]
[4.69875286e+03 3.93713784e-03]]]
I have tried many methods such as:
First:
x10,x11 = zip(*br)
print(x10,x11) /print(np.array(x10),np.array(x11))
Hasn't worked giving the error (too many values to unpack two are expected)
Second:
def column(matrix,i):
return [row[i] for row in matrix]
x10 = column(br,0)
x11 = column(br,1)
print(x10,x11)
For which the output is :
[array([5.37692693e+03, 3.78425697e-03])]
[array([1.36092539e+03, 3.35722632e-03])]
and third:
x11 = [i[0] for i in br]
x12 = [i[1] for i in br]
print(x11.split(),x12.split())
I believe this aren't working because the output of my function is of type [[[....]]]
Many thanks

You can only ever unpack the first dimension of an array, but the dimension you want to unpack is the second one. This means in your case, you can do:
x10, x11 = br.T
Be aware that x10 and x11 will be a view into br! This means if you change any of the values in any of these arrays, you will change the other variables too.
If your array has more than 2D dimensions (extra [ and ]), check the shape of your array using
br.shape
and if you see superfluous empty dimensions (1), remove them using
br = br.squeeze()

Another possible solution is
br = [[[5.37692693e+03, 3.78425697e-03], [1.36092539e+03, 3.35722632e-03], [5.43477586e+03, 3.90104194e-03], [5.93759455e+03, 4.05490440e-03], [3.00855802e+03, 3.65746871e-03], [4.69875286e+03, 3.93713784e-03]]]
x10,x11 = zip(*br[0])
print(x10,x11)
Output
(5376.92693, 1360.92539, 5434.77586, 5937.59455, 3008.55802, 4698.75286) (0.00378425697, 0.00335722632, 0.00390104194, 0.0040549044, 0.00365746871, 0.00393713784)

Related

How can I specify each iteration in a for loop's output? Python

I have a .json file with multiple values, seperated by commas. I would like to go through the file and output each value sequentially, as variables. The first one being x1, the second one being x2 and so on. The point is so that I can use these values in an equation later on.
The output would look like this:
x1 = 0.0234
x2 = 0.512
x3 = 0.9782
I pretty sure I need to use a for loop after this:
g = open('beat_times_knownsong1.json')
another_song = json.load(g)
EDIT: this is some of the .json data:
0.023219954648526078,
0.5108390022675737,
0.9752380952380952,
1.4628571428571429,
1.9504761904761905,
2.414875283446712,
2.9024943310657596,
3.3668934240362813,
3.8545124716553287,
4.31891156462585,
4.806530612244898,
5.270929705215419,
5.758548752834467,
6.222947845804988,
6.710566893424036,
7.174965986394557,
they're just numbers increasing in value. If I just do:
g = open('beat_times_knownsong1.json')
another_song = json.load(g)
for beat in another_song:
print(beat)
then it just prints the values. I would like for it to save each value to an "x" variable, increasing from x1 = 0.023219954648526078 to x2, x3 and so on.
Use enumerate to get the index of the current value in the list you are iterating over.
There are different ways in Python to convert a string to a variable (see e.g. here). One is using the locals method, which returns a dict that reflects all local variables defined in a scope (e.g. a function) and allows manipulating them (e.g. reassigning, adding new variables or deleting existing ones).
Example:
g = open('beat_times_knownsong1.json')
another_song = json.load(g)
for i, beat in enumerate(another_song):
locals()[f"x{i}"] = beat
print(x0)
print(x1)
...
Why not using a dictionary instead of variable:
g = open('beat_times_knownsong1.json')
another_song = json.load(g)
variable_dict={}
i=0
for beat in another_song:
variable_dict["x"+str(i)]=beat
i+=1
and you can get the value you want like this:
variable_dict["x1"]

Python too many values to unpack

so I want to find distance between two xyz file coordinate using python,
I was given this for example
0.215822, -1.395942, -1.976109
0.648518, -0.493053, -2.101929
In python, I wrote,
f = open('First_Ten_phenolMeNH3+.txt', 'r')
lines = f.readlines()
a = lines[0] #(0.215822, -1.395942, -1.976109)
(x1,y1,z1) = a
b = lines[1] #(0.648518, -0.493053, -2.101929)
(x2,y2,z2) = b
distance = math.sqrt((x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2)
print(distance)
f.close()
I want to use tuple unpacking and to calucalte distance, however, I keep getting too many values to unpack (expected 3), I think it is because of the txt file, Is there any better way I can do it ?? The problem is i need have 5000 coordinate file to sort through, so it will be inefficient to plug in coordinate one by one.
Thank you
You could use this:
from scipy.spatial import distance
from ast import literal_eval
a = literal_eval(lines[0]) #(0.215822, -1.395942, -1.976109)
b = literal_eval(lines[1]) #(0.648518, -0.493053, -2.101929)
dst = distance.euclidean(a, b) #1.009091198622305
you are trying to assign a string to a tuple. try using split() first:
a = lines[0].split() #(0.215822, -1.395942, -1.976109)
(x1,y1,z1) = a
also, this will put strings into x1,x2,x3, you need to convert them to float:
x1 = float(x1)
x2 = float(x2)
x3 = float(x3)
line[0] is a string, as it in a text file. You need to convert it into tuple of floats
x1, y1, z1 = (float(value) for value in line[1:-1].split(', '))

Nested for loop producing more number of values than expected-Python

Background:I have two catalogues consisting of positions of spatial objects. My aim is to find the similar ones in both catalogues with a maximum difference in angular distance of certain value. One of them is called bss and another one is called super.
Here is the full code I wrote
import numpy as np
def crossmatch(bss_cat, super_cat, max_dist):
matches=[]
no_matches=[]
def find_closest(bss_cat,super_cat):
dist_list=[]
def angular_dist(ra1, dec1, ra2, dec2):
r1 = np.radians(ra1)
d1 = np.radians(dec1)
r2 = np.radians(ra2)
d2 = np.radians(dec2)
a = np.sin(np.abs(d1-d2)/2)**2
b = np.cos(d1)*np.cos(d2)*np.sin(np.abs(r1 - r2)/2)**2
rad = 2*np.arcsin(np.sqrt(a + b))
d = np.degrees(rad)
return d
for i in range(len(bss_cat)): #The problem arises here
for j in range(len(super_cat)):
distance = angular_dist(bss_cat[i][1], bss_cat[i][2], super_cat[j][1], super_cat[j][2]) #While this is supposed to produce single floating point values, it produces numpy.ndarray consisting of three entries
dist_list.append(distance) #This list now contains numpy.ndarrays instead of numpy.float values
for k in range(len(dist_list)):
if dist_list[k] < max_dist:
element = (bss_cat[i], super_cat[j], dist_list[k])
matches.append(element)
else:
element = bss_cat[i]
no_matches.append(element)
return (matches,no_matches)
When put seperately, the function angular_dist(ra1, dec1, ra2, dec2) produces a single numpy.float value as expected. But when used inside the for loop in this crossmatch(bss_cat, super_cat, max_dist) function, it produces numpy.ndarrays instead of numpy.float. I've stated this inside the code also. I don't know where the code goes wrong. Please help

Iterations of equations using sequences

To start off with I have two files, lets call them fileA and fileB.
In fileB I have two sequences, lets call them initial and final. Each sequences has exactly 32 values, most of which are simple equations that slightly differ from each other, hence the 32 unique values. For simplicity's sake let's scope them down to 5 each. so for initial it would look something like.
~fileB
T1 = 60
inital = [0.112, 0.233, 0.322*T1, 0.55*T1, 0.665*T1]
Variable T1 does not change at any point at all, So initial is constant permanently. The 2nd variable is called "final"
For final I have:
T2 = 120
k_0 = T2**2 - T1**2
final = [x * k_0 for x in initial]
This gives me the values I want for final and it gives me a sequence of the same length. In fileA I want to evalute an iterator at multiple T2 values and get an "answer" for each respective T2 value. However, since I am new, i'm limiting my self so that i'm only doing this for the very first final value.
So now on to fileA:
~fileA
import fileB
import math
answer = []
T2 = np.array(120,400,10)
x = symbols('x')
int1 = Integral(x**2 -1,x)
eq1 = int.doit()
for i in T2:
k = k_0*final[0]
answer.append(solve(eq1 - k, x))
This is where things get tricky, as i want it to evaluate this ONLY for the first "final" value
final[0]
but i want it to re-evaluate the two variables
k_0 = T2**2 - T1**2
and
answer = []
At each and every T2 value, how can I do this so that I can make an array/table that looks like the following
T2 (header) Answer(header)
value_1 Value_1
value_2 Value_2
value_3 Value_3
value_4 Value_4
.... ....
If you need me to explain it better of have questions feel free to ask.
If necessary i'm using python 3.6/3.7 in the anaconda distribution.
Okay my question was a bit confusing but I figured out how to solve it.
The first step was to write a list comprehension for T2 instead of a np array, like so:
T2 = [20 + x*1.01 +273.15 for x in range(40)]
Then I assigned the integral i wanted solved to a variable, let's call it int1.
int1 = Integral((1-x)**-2,x)
Then I have to create two new and separate empty sequences.
answer = []
X = []
For the first sequence (answer) I did the following:
for i,temp in enumerate(t2):
k_0 = math.exp((ee/r)*((1/t1)-(1/t2[i])))
k = initial_k[0]*k_0
v_0 = 2
Fa_0 = 5
Ca_0 = Fa_0/v_0
Q = (k*Ca_0*V)/v_0
eq1 = int1.doit()
answer.append(solve(eq1 - Q,x))
While this will give the numerical answers I was looking for, each and every individual answer is returned as a sequence, which is inside of a sequence.
answer = [[value1],[value2],[value3],[value4]]
This causes problems when trying to use the numerical answers in other equations or operations.
To fix this i used the same technique as above and returned all of the numerical float values into a single sequence
for i,val in enumerate(answer):
X.append(float(answer[i][0]))
This finally allowed me to use the numerical float values original stored in answer[] by simply transferring them to a new sequence where they are not nested.
Ca = [(1-x)*Ca_0 for x in X]
Fa = [(1-x)*Fa_0 for x in X]
Finally, I was able to get the table I originally wanted!
Temperature Conversion Ca Fa
293.15 0.44358038322375287 1.3910490419406178 2.7820980838812357
303.15 0.44398389128120275 1.390040271796993 2.780080543593986
313.15 0.44436136324002395 1.38909659189994 2.77819318379988
323.15 0.4447152402068642 1.3882118994828396 2.7764237989656793
I'm not completely sure why I had to do this but it worked, however, any help or insight into this would be appreciated.

Get x,y from 2d list and pass on

I'm trying to take a 2d list of locations that incl lat/ longs and get only the coordinates from the list (in column 3 and 4) to send to another function so that distances can be calculated... but I'm totally stumped.
What I have is...
EDITED from OP to show where I'm at...
x1 = -18.00 #These values don't change
y1 = 118.00
x2 = float(origList[3])
y2 = float(origList[4])
n = len(origList)
appList = []
for i in range (n-1):
appList.append(findDistance(x1, y1, x2, y2))
print appList
But now I get...File "F:\Storage\t_2\coord_find.py", line 27, in main,x2=math.fabs(origList[3])
TypeError: a float is required
So the problem is in the conversion to float???
Then all I have so far for the findDistance function (I only just started it and just want to test if arguments are being passed correctly)...
def findDistance(x1, y1, x2, y2):
cosX = math.fabs(y1 - y2)
a = 90 - x2
b = 90 - x1
Here's my updated code that is giving me this...
delx = math.fabs(y1 - y2)
TypeError: unsupported operand type(s) for -: 'float' and 'list'
I'm posting it up because I obviously didn't give a clear enough explanation and have made some changes since. AS you can see, I want to get the x2,y2 from cols 3,4.
Tried x2=float(origList[3]), y2=float(origList[4]) but that doesn't work either- I get "float()argument must be a string or a number".
Do I need to split the list somehow before trying to extract the values as floats??
import csv
import math
def fZone():
origList = [['200','12_7','Cons_pl','-20.10','120.10','C_10_T2'],['....'...]]
# origList has 30+ lines like this
x1 = -20.68 # Fixed point
x2 = 117.19 # Fixed point
n = len(origList) # list length
appList = [] # to hold returned
for i in range (n):
x2= origList[3] # I wanna get the '-20.10' col each iteration
y2= origList[4] # I wanna get the '120.10' col each iteration
appList.append(findDist(x1, y1, x2, y2))
print appList
def findDist(x1,y1,x2,y2):
delx = math.fabs(y1 - y2)
a = 90 - x2
b = 90 - x1 # formula is not finished
Your origList[0:] evaluates to origList. Try origList[0].
range(0,n-1) only goes up to n-2, and you have no need to specify the starting value of 0 since that's the default anyway. Use range(n).
You say the coordinates are in columns 3 and 4. It looks like you're somewhat new to indexing in a programming language, so I hope I don't offend with a gratuitous reminder that you might be looking for list elements 2 and 3, if you mean that these are the 3rd and 4th columns.
Also, the print should be outside the loop.
Apparently your list is containing pairs of strings, not of numbers.
In Python this conversion is never automatic so you will probably have to change the code to:
findDistance(x1, y1, float(origList[i][3]), float(origList[i][4]))
An error like
lat2= float(stnList[3])
TypeError: float() argument must be a string or a number
clearly says what was passed to float was neither a number nor a string.
Just add a print repr(stnList[3]) right before the offending statement and check out what was passed instead.
You can also the python debugger to find what the problem is, check for example this short video of a pdb session example

Categories