Related
I am reforming the 2D coordinate number in a aligned way which was not aligned (coordinate numbers were suffled) before.
I have below input coordinates,
X = [2, 2, 3, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 5, 4, 3, 5, 5, 5]
Y = [2, 3, 3, 3, 4, 5, 6, 6, 6, 5, 4, 3, 2, 2, 2, 2, 3, 4, 5]
I have to make it aligned. Therefore, I first applied Sorted function on this coordinates. I got below output after it.
merged_list1 = sorted(zip(X, Y))
output
X1_coordinate_reformed = [2, 2, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6]
Y1_coordinate_reformed = [2, 3, 2, 3, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6]
Still it iot aligned properly. I want two consecutive nodes place next to each other. Therefore I am applying the approach to find the nearest coordinate from origin to find the very first node. Then from the first node, I found another nearest coordinate and so on...For that, I have applied below code,
First I wrote a function which calculates the distance and gives index of the nearest coordinate from the list.
def solve(pts, pt):
x, y = pt
idx = -1
smallest = float("inf")
for p in pts:
if p[0] == x or p[1] == y:
dist = abs(x - p[0]) + abs(y - p[1])
if dist < smallest:
idx = pts.index(p)
smallest = dist
elif dist == smallest:
if pts.index(p) < idx:
idx = pts.index(p)
smallest = dist
return idx
coor2 = list(zip(X1_coordinate_reformed, Y1_coordinate_reformed)) # make a list which contains tuples of X and Y coordinates
pts2 = coor2.copy()
origin1 = (0, 0)
new_coor1 = []
for i in range(len(pts2)):
pt = origin1
index_num1 = solve(pts2, pt)
print('index is', index_num1)
origin1 = pts2[index_num1]
new_coor1.append(pts2[index_num1])
del pts2[index_num1]
After running the code, I got below output,
[(6, 6), (5, 6), (4, 6), (4, 5), (4, 4), (4, 3), (3, 3), (2, 3), (2, 2), (3, 2), (4, 2), (5, 2), (5, 3), (5, 4), (5, 5), (6, 5), (6, 4), (6, 3), (6, 2)]
Which is not correct because it can be clearly understand that,
coor2 = [(2, 2), (2, 3), (3, 2), (3, 3), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6)]
origin = (0, 0)
if we find the distance between Origin which was (0, 0) in very first and from every coordinate from above coor2 list, we will get (2,2) is nearest coordinate. Then How come my code gives (6,6) is the nearest coordinate??
The interesting thing is, if I apply the same procedure (sorting followed by finding nearest coordinate) on below coordinates,
X2_coordinate = [2, 4, 4, 2, 3, 2, 4, 3, 1, 3, 4, 3, 1, 2, 0, 3, 4, 2, 0]
Y2_coordinate = [3, 4, 2, 1, 3, 2, 1, 0, 0, 2, 3, 4, 1, 4, 0, 1, 0, 0, 1]
After applying sorted function
X2_coordinate_reformed = [0, 0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4]
Y2_coordinate_reformed = [0, 1, 0, 1, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
After applying method of searching nearest coordinates mentioned above, the result I got
[(0, 0), (0, 1), (1, 1), (1, 0), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 4), (3, 3), (3, 2), (3, 1), (3, 0), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]
Kindly suggest me where I am doing wrong and what should I change??
It is better to use scipy for finding closest coordinate.
The code given below works.
from scipy import spatial
pts = merged_list1.copy()
origin = (0, 0)
origin = np.array(origin)
new_coordi = []
for i in range(len(pts)):
x = origin
distance,index = spatial.KDTree(pts).query(x)
new_coordi.append(pts[index])
origin = np.array(pts[index])
del pts[index]
I'm using subplot2grid to define a grid of plots as shown below.
Works great, it's a good functionality.
plot_axes_1 = plt.subplot2grid((6, 4), (0, 0), rowspan=2, colspan=3) ##1
plot_axes_2 = plt.subplot2grid((6, 4), (2, 0), rowspan=2, colspan=3, sharex=scatter_axes_1) ##2
x_hist_axes_2 = plt.subplot2grid((6, 4), (4, 0), colspan=3, sharex=scatter_axes_2) ##3
y_hist_axes_1 = plt.subplot2grid((6, 4), (0, 3), rowspan=2, sharey=scatter_axes_1) ##4
y_hist_axes_2 = plt.subplot2grid((6, 4), (2, 3), rowspan=2, sharey=scatter_axes_2, sharex= y_hist_axes_1) ##5
Now I want to consider the 5 plots from the image as a unit, and plot 6 copies of it, arranged on 3 rows and 2 columns.
fig, ax= plt.subplots(3,2)
for l in range(3):
for m in range(2):
ax[l,m].subplot2grid((6, 4), (0, 0), rowspan=2, colspan=3) ##1
ax[l,m].subplot2grid((6, 4), (2, 0), rowspan=2, colspan=3, sharex=scatter_axes_1) ##2
ax[l,m].subplot2grid((6, 4), (4, 0), colspan=3, sharex=scatter_axes_2) ##3
ax[l,m].subplot2grid((6, 4), (0, 3), rowspan=2, sharey=scatter_axes_1) ##4
ax[l,m].subplot2grid((6, 4), (2, 3), rowspan=2, sharey=scatter_axes_2, sharex= y_hist_axes_1) ##5
But I can't use subplot2grid like this, I get the error
'AxesSubplot' object has no attribute 'subplot2grid'
Is there another function I can use with AxesSubplot to do that?
I'm a little confused by what you are trying to do. However, a perhaps an alternate way to deal with different widths and heights is to use width ratios?
EDIT: use subfigure to keep logical groups of axes.
import matplotlib.pyplot as plt
fig = plt.figure(constrained_layout=True, figsize=(8, 12))
sfigs = fig.subfigures(3, 2)
for nn, sf in enumerate(sfigs.flat):
sf.suptitle(nn)
axs = sf.subplots(3, 2, gridspec_kw={'width_ratios': [2, 1],
'height_ratios': [2, 2, 1]})
sf.delaxes(axs[2, 1])
plt.show()
I think this is a job for matplotlib's sematic figure composition function, i.e., the subplot_mosaic function. This is available in matplotlib > 3.3. You will need to define a basic layout for your 5 panels, and then generate a full layout depending on how many rows/columns you want. As far as I can see, this will be quite convoluted and hard (although not impossible!) to create by subplot2grid or Gridspec or any of the other approaches.
import matplotlib.pyplot as plt
import numpy as np
def layout(panel, rows=3, cols=2, empty_sentinal=999):
"""Takes in a single layout and arranges it in multiple
rows and columns"""
npanels = rows * cols
panel[panel >= empty_sentinal] = empty_sentinal
minipanels = len(np.unique(panel))
panels = np.array([i * (minipanels) + panel for i in range(npanels)])
panel_rows = [np.hstack(panels[i : i + cols]) for i in range(0, npanels, cols)]
panel_cols = np.vstack(panel_rows)
panel_cols[panel_cols > empty_sentinal] = empty_sentinal
return panel_cols
A) Generating a single panel:
single_panel = np.array([
[1, 1, 1, 1, 1, 1, 2, 2, 999],
[1, 1, 1, 1, 1, 1, 2, 2, 999],
[1, 1, 1, 1, 1, 1, 2, 2, 999],
[1, 1, 1, 1, 1, 1, 2, 2, 999],
[3, 3, 3, 3, 3, 3, 4, 4, 999],
[3, 3, 3, 3, 3, 3, 4, 4, 999],
[3, 3, 3, 3, 3, 3, 4, 4, 999],
[3, 3, 3, 3, 3, 3, 4, 4, 999],
[5, 5, 5, 5, 5, 5, 999, 999, 999],
[5, 5, 5, 5, 5, 5, 999, 999, 999],
[5, 5, 5, 5, 5, 5, 999, 999, 999],
[999] * 9,
[999] * 9,
])
fig, ax = plt.subplot_mosaic(single_panel, figsize=(10, 10), empty_sentinel=999)
for k, v in ax.items():
v.set_xticklabels([])
v.set_yticklabels([])
v.text(0.5, 0.5, k, ha="center", va="center", fontsize=25)
plt.show()
(B) "Tiling" the above single panel
my_layout = layout(panel=single_panel, rows=3, cols=2)
fig, ax = plt.subplot_mosaic(my_layout, figsize=(10, 10), empty_sentinel=999)
for k, v in ax.items():
v.set_xticklabels([])
v.set_yticklabels([])
v.text(0.5, 0.5, k, ha="center", va="center", fontsize=25)
plt.show()
Some Notes:
The empty_sentinal is set to 999. If you have more than 999 subplots, increase that to a higher number.
Each "mini-panel" can be individually acessed. You might need to write other functions to access "panel-group"
I have a list that looks like this
mylist = [('Part1', 5, 5), ('Part2', 7, 7), ('Part3', 11, 9),
('Part4', 45, 45), ('part5', 5, 5)]
I am looking for all the tuples that has a number closest to my input
now i am using this code
result = min([x for x in mylist if x[1] >= 4 and x[2] >= 4])
The result i am getting is
('part5', 5, 5)
But i am looking for an result looking more like
[('Part1', 5, 5), ('part5', 5, 5)]
and if there are more tuples in it ( i have 2 in this example but it could be more) then i would like to get all the tuples back
the whole code
mylist = [('Part1', 5, 5), ('Part2', 7, 7), ('Part3', 11, 9), ('Part4', 45, 45), ('part5', 5, 5)]
result = min([x for x in mylist if x[1] >= 4 and x[2] >= 4])
print(result)
threshold = 4
mylist = [('Part1', 5, 5), ('Part2', 7, 7), ('Part3', 11, 9), ('Part4', 45, 45), ('part5', 5, 5)]
filtered = [x for x in mylist if x[1] >= threshold and x[2] >= threshold]
keyfunc = lambda x: x[1]
my_min = keyfunc(min(filtered, key=keyfunc))
result = [v for v in filtered if keyfunc(v)==my_min]
# [('Part1', 5, 5), ('part5', 5, 5)]
I want to reshape array of shape (2, *(x, y)) to (1, *(x,y), 2) while preserving the values of (x, y)?
(2, *(x,y)) where 2 represents the frames of game screen with (x, y) being an array with pixel values. I wish to convert it into an array of shape of (1, *(x, y), 2), such that the number 2 still represents the frame index, while (x,y) array value is preserved. 1 will be used to index the batch for training the neural network.
numpy.reshape(1, *(x,y), 2) doesn't preserve the (x,y) array.
Use numpy.transpose(), e.g.:
import numpy as np
arr = np.arange(2 * 3 * 4).reshape((2, 3, 4))
arr.shape
# (2, 3, 4)
arr.transpose(1, 2, 0).shape
# (3, 4, 2)
new_arr = arr.transpose(1, 2, 0)[None, ...]
new_arr.shape
# (1, 3, 4, 2)
# the `(3, 4)` array is preserved:
arr.transpose(1, 2, 0)[:, :, 0]
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
arr[0, :, :]
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
I want to define sth like
list([[i0,i1,i2,i3, ..., ik]] for i0 in T[0] for i1 in T[1] for i2 in T[2] for i3 in T[3] for ...)
as k is indefinite, I cannot do this like
list([[i0,i1,i2,i3]] for i0 in T[0] for i1 in T[1] for i2 in T[2] for i3 in T[3]).
Is there a general solution?
Many thanks!
Your nested fors will make a Cartesian product of the sublists in T. Itertools has a product() function that will give you an iterator of these values, which you can use like:
from itertools import product
T = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10,11, 12]]
p = product(*T)
for i in p:
print(i)
(1, 4, 7, 10)
(1, 4, 7, 11)
(1, 4, 7, 12)
(1, 4, 8, 10)
(1, 4, 8, 11)
(1, 4, 8, 12)
(1, 4, 9, 10)
(1, 4, 9, 11)
...
(3, 6, 9, 10)
(3, 6, 9, 11)
(3, 6, 9, 12)
Of course you can also pass it to list() if want the values in a list.