eshangj/stackoverflow_q_and_a_sample huggingface dataset:
Question: I am using Apache Airflow and trying to trigger multiple DAGs from within another DAG using TriggerDagRunOperator.expand(). I have two lists being returned from an upstream task via XCom: confs → A list of dictionaries containing conf parameters. dags_to_trigger → A list of DAG IDs to be triggered. Each list contains 5 elements, and I want to pair them one-to-one (i.e., the first element of confs should be used with the first element of dags_to_trigger, the second with the second, and so on). Problem: When I use expand() like this: trigger_my_dags = TriggerDagRunOperator.partial( task_id="trigger_my_dags", wait_for_completion=False, ).expand(conf=confs, trigger_dag_id=dags_to_trigger)  Airflow cross-pairs the elements, triggering 25 DAG runs instead of 5 (it takes each conf from description_sources and pairs it with every DAG ID from dags_to_trigger, rather than pairing them by index). Question: How can I ensure that Airflow correctly pairs the elements from both lists so that each DAG run gets the corresponding conf from description_sources? Would restructuring the data into a single list of dictionaries like this help? [{"conf": { ... }, "trigger_dag_id": "dag_1"}, {"conf": { ... }, "trigger_dag_id": "dag_2"}, ...]  If so, how do I correctly use expand() with this structure? Thanks in advance!

Answer: Don't know your Airflow version but hope this helps. You can use execute() method instead of partial() + expand(). Here is an example: from datetime import datetime from typing import Any from airflow import DAG from airflow.models import BaseOperator from airflow.operators.empty import EmptyOperator from airflow.operators.trigger_dagrun import TriggerDagRunOperator from airflow.utils.context import Context class RunnerOperator(BaseOperator): def execute(self, context: Context) -> Any: # params for DAG run. from XCOM / API / doesn't matter params = { 'configs': [ {'conf': {'param_a': 1}, 'trigger_dag_id': 'dag_1'}, {'conf': {'param_b': 2}, 'trigger_dag_id': 'dag_2'}, ] } for dag_params in params['configs']: trigger_dag_id = dag_params['trigger_dag_id'] TriggerDagRunOperator( task_id=f'{trigger_dag_id}_task', trigger_dag_id=trigger_dag_id, conf=dag_params['conf'], wait_for_completion=False, ).execute(context) dag = DAG(dag_id='igor_atsberger', start_date=datetime(2025, 1, 1), schedule=None) RunnerOperator(dag=dag, task_id='runner') dag_1 = DAG(dag_id='dag_1', start_date=datetime(2025, 1, 1), schedule=None) dag_2 = DAG(dag_id='dag_2', start_date=datetime(2025, 1, 1), schedule=None) for _dag in [dag_1, dag_2]: EmptyOperator(dag=_dag, task_id=f'{_dag.dag_id}_task')  Let's check dag_1 config:  Let's check dag_2 config:  Another easy way is just to use Airflow REST API
Question: In python, given a list mylist of lists el of integers, I would like to remove duplicates that are equivalent under specific permutations of the indices. The question is more general but I have in mind "decorated" McKay graphs where each node is given an integer defining el whose sum is equal to a certain number. Generating mylist is easy enough, but there is a lot of redundancy depending on the symmetry of the graph. For instance, for the "D4" diagram, el represents the following decorated graph:  a | el = [a, b, c, d, e] <--> b-c―d | e  The two lists [1,0,4,0,0] and [0,0,4,0,1] are duplicates because there are the same up to a reflection of the graph around the horizontal axis. More generally, the lists el duplicates if there are equivalent under any permutation of a,b,d,e. Is there a simple way of removing duplicates given an arbitrary symmetry? The way I did it for this particular graph was to sort the indices 0,1,3,4 and compare: from itertools import product def check_duplicate(f, li): for l in li: if l[2] == f[2] and sorted(l[:2] + l[3:]) == sorted(f[:2] + f[3:]): return True return False mylist = [list(i) for i in product(range(5), repeat=5) if sum(i) == 5] newlist = [] for f in my_list: if check_duplicate(f, newlist) == False: newlist.append(f)  Here tmp is generated brute force, but the condition is more involved in my real case. This works well enough for this particular example, but is a bit clunky, and the implementation is harder to generalize to more involved cases. Is there a way to remove the duplicates in a more optimized way, in particular one that can easily implement removing duplicates given a particular symmetry of the indices of el?

Answer: It will probably be better to add "seen" cases to a set, and then continue to check if new elements have already been "seen", rather than comparing every element to every other element in the list iteratively (an operation with O(n^2) time complexity). Hopefully I understand what you're trying to accomplish, but here's how I'd do it: from itertools import product def to_key(f): # Creates a hashable key, keeping order-insensitive values sorted, and noting the middle value""" return (f[2], tuple(sorted(f[:2] + f[3:]))) mylist = [list(i) for i in product(range(5), repeat=5) if sum(i) == 5] # Init an empty set. We'll add to it if a key isn't there seen = set() # If we add to the seen set, we'll add the element to newList newlist = [] for f in mylist: key = to_key(f) # Create the hashable key if key not in seen: # Check if key in seen seen.add(key) newlist.append(f)
Question: I was making user-entered variable configurable via command line parameters & ran into this weird behaviour: PS D:> python -c "import sys; print(sys.argv)" -imgs ".\Test V4\Rilsa\" -nl 34 ['-c', '-imgs', '.\\Test V4\\Rilsa" -nl 34'] PS D:> python -c "import sys; print(sys.argv)" -imgs ".\TestV4\Rilsa\" -nl 34 ['-c', '-imgs', '.\\TestV4\\Rilsa\\', '-nl', '34']  If the name of my folder is Test V4 with a space character, then all following parameters end up in the same argument element '.\\Test V4\\Rilsa" -nl 34'. There is also a trailing " quote after the directory name. I tried this again in CMD, thinking it was a Powershell quirk & experienced the same behaviour. What's going on here? I'm assuming it has something to do with backslashes in Powershell -- though it's the default in Windows for directory paths -- but why do I get diverging behaviour depending on space characters & what's a good way to handle this assuming Windows paths are auto-completed into this form by the shell (i.e. trailing \)?

Answer:  You're seeing a bug in Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1), which has since been fixed in PowerShell (Core) 7, as detailed in this answer.  In short, as you've since discovered yourself, the problem occurs when you pass arguments that contain space(s) and end in \ to external programs, because Windows PowerShell - when it constructs the true process command line behind the scenes - blindly encloses such arguments in "...", causing most target programs to interpret the closing \" sequence as an escaped " char. (Since arguments without spaces are not subject to this "..." enclosure, they are not affected.)    Workarounds (required in Windows PowerShell only, but should also work in PowerShell 7):  Manually add a trailing \ to your argument: # Note the '\\' python -c "import sys; print(sys.argv)" -imgs ".\Test V4\Rilsa\\" -nl 34   Alternatively, add a trailing space, relying on the fact that on Windows trailing spaces in paths are usually ignored: # Note the trailing space before the closing " python -c "import sys; print(sys.argv)" -imgs ".\Test V4\Rilsa " -nl 34    In either case, if the path must be passed via a variable rather than a literal and the variable value may or may not end in \, use "...", i.e. an expandable (interpolating) string, such as "$dirPath\" or "$dirPath "
Question: I need to backfill a column in a python polars dataframe over one of three possible columns, based on which one matches the non-null cell in the column to be backfilled. My dataframe looks something like this: ┌─────┬─────┬─────┬─────────┐ │ id1 ┆ id2 ┆ id3 ┆ call_id │ │ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ i64 ┆ i64 ┆ i64 │ ╞═════╪═════╪═════╪═════════╡ │ 1 ┆ 4 ┆ 9 ┆ null │ │ 1 ┆ 5 ┆ 9 ┆ null │ │ 1 ┆ 5 ┆ 9 ┆ null │ │ 2 ┆ 5 ┆ 9 ┆ null │ │ 2 ┆ 6 ┆ 9 ┆ 2 │ │ 2 ┆ 7 ┆ 10 ┆ null │ │ 3 ┆ 7 ┆ 11 ┆ null │ │ 3 ┆ 7 ┆ 12 ┆ null │ │ 3 ┆ 7 ┆ 13 ┆ 7 │ │ 3 ┆ 8 ┆ 13 ┆ null │ └─────┴─────┴─────┴─────────┘  And I want it to look like this: ┌─────┬─────┬─────┬─────────┐ │ id1 ┆ id2 ┆ id3 ┆ call_id │ │ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ i64 ┆ i64 ┆ i64 │ ╞═════╪═════╪═════╪═════════╡ │ 1 ┆ 4 ┆ 9 ┆ null │ │ 1 ┆ 5 ┆ 9 ┆ null │ │ 1 ┆ 5 ┆ 9 ┆ null │ │ 2 ┆ 5 ┆ 9 ┆ 2 │ │ 2 ┆ 6 ┆ 9 ┆ 2 │ │ 2 ┆ 7 ┆ 10 ┆ 7 │ │ 3 ┆ 7 ┆ 11 ┆ 7 │ │ 3 ┆ 7 ┆ 12 ┆ 7 │ │ 3 ┆ 7 ┆ 13 ┆ 7 │ │ 3 ┆ 8 ┆ 13 ┆ null │ └─────┴─────┴─────┴─────────┘  If I knew which column matched, I would have used something to the effect of .with_columns(pl.col('call_id').backfill().over('id1'), but for the life of me I can't figure out how to systematically choose which column to backfill over.

Answer: Assuming that your dataframe is in a variable called df and your backfill value is always the same (which is the case in your example) df.with_columns( call_id=pl.coalesce( pl.when( (pl.col("^id.*$") == pl.col("call_id")).backward_fill().over("^id.*$") ) .then("^id.*$") ) ) # shape: (10, 4) # ┌─────┬─────┬─────┬─────────┐ # │ id1 ┆ id2 ┆ id3 ┆ call_id │ # │ --- ┆ --- ┆ --- ┆ --- │ # │ i64 ┆ i64 ┆ i64 ┆ i64 │ # ╞═════╪═════╪═════╪═════════╡ # │ 1 ┆ 4 ┆ 9 ┆ null │ # │ 1 ┆ 5 ┆ 9 ┆ null │ # │ 1 ┆ 5 ┆ 9 ┆ null │ # │ 2 ┆ 5 ┆ 9 ┆ 2 │ # │ 2 ┆ 6 ┆ 9 ┆ 2 │ # │ 2 ┆ 7 ┆ 10 ┆ 7 │ # │ 3 ┆ 7 ┆ 11 ┆ 7 │ # │ 3 ┆ 7 ┆ 12 ┆ 7 │ # │ 3 ┆ 7 ┆ 13 ┆ 7 │ # │ 3 ┆ 8 ┆ 13 ┆ null │ # └─────┴─────┴─────┴─────────┘
Question: So I'm brushing up on my algebra and trying to learn sympy at the same time. Following an algebra tutorial on youtube, I'm at this point:  I can't quite figure out how to isolate y What I've tried: p1 = sym.Point(-1, 1) m = -2 eq = sym.Line(p1, slope=m).equation() eq  returns: 2x + y + 1 eq1 = sym.Eq(eq, 0) eq1  Gives me: 2x + y + 1 = 0 and.. eq2 = sym.simplify(eq1) eq2  Returns: 2x + y = -1 ..but that's as close as I can get to isolating y (y = -2x - 1). I'm sure it's a simple answer but I've been searching on the intertubes for 2 days now without success. I've tried solve() and subs(), solve just returns an empty set and subs gives the original equation back. What am I doing wrong?

Answer: I believe that the code below gives what you want. I believe solve wasn't working for you because you needed to define x, y as symbols. Then you can use the solution to create your equation using Eq. Note that the solution is a list. Hope this helps. import sympy as sym from sympy.solvers import solve p1 = sym.Point(-1, 1) m = -2 eq = sym.Line(p1, slope=m).equation() print(eq) eq1 = sym.Eq(eq, 0) print(eq1) x, y = sym.symbols('x y', real = True) sol = solve(eq, y) print(sol) eq1 = sym.Eq(y, sol[0]) print(eq1)  Output: 2*x + y + 1 Eq(2*x + y + 1, 0) [-2*x - 1] Eq(y, -2*x - 1)
Question: I have the following df: | day | first mover | | -------- | -------------- | | 1 | 1 | | 2 | 1 | | 3 | 0 | | 4 | 0 | | 5 | 0 | | 6 | 1 | | 7 | 0 | | 8 | 1 |  i want to group this Data frame in the order bottom to top with a frequency of 4 rows. Furthermore if first row of group is 1 make all other entries 0. Desired output: | day | first mover | | -------- | -------------- | | 1 | 1 | | 2 | 0 | | 3 | 0 | | 4 | 0 | | 5 | 0 | | 6 | 0 | | 7 | 0 | | 8 | 0 |  The first half i have accomplished. I am confuse about how to make other entries 0 if first entry in each group is 1. N=4 (df.iloc[::-1].groupby(np.arange(len(df))//N 

Answer: I would use for-loop for this for name, group in df.groupby(...):  this way I could use if/else to run or skip some code. To get first element in group: (I don't know why but .first() doesn't work as I expected - it asks for some offset) first_value = group.iloc[0]['first mover']  To get indexes of other rows (except first): group.index[1:]  and use them to set 0 in original df df.loc[group.index[1:], 'first mover'] = 0   Minimal working code which I used for tests: import pandas as pd df = pd.DataFrame({ 'day': [1,2,3,4,5,6,7,8,], 'first mover': [1,1,0,0,0,1,0,1] }) N = 4 for name, group in df.groupby(by=lambda index:index//N): #print(f'\n---- group {name} ---\n') #print(group) first_value = group.iloc[0]['first mover'] #print('first value:', first_value) if first_value == 1 : #print('>>> change:', group.index[1:]) df.loc[group.index[1:], 'first mover'] = 0 print('\n--- df ---\n') print(df)
Question: I would like to compute the dot product (matmul) of the inner dimension of two 3D arrays. In the following example, I have an array of 10 2x3 matrixes (X) and an array of 8 1x3 matrixes. The result Z should be a 10 element array of an 8 x 2 matrix (you might also think of this as an 10 x 8 array of 2-d vectors.) X = np.arange(0, 10 * 2 * 3).reshape(10, 2, 3) Y = np.arange(0, 8 * 1 * 3).reshape(8, 1, 3) # write to Z, which has the dot-product of internal dims of X and Y Z = np.empty((10, 8, 2)) for i, x_i in enumerate(X): for j, y_j in enumerate(Y): z = x_i @ y_j.T # subscriptz to flatten it. Z[i, j, :] = z[:, 0]  is correct, but I would like a vectorized solution.

Answer: Einsum You could use einsum np.einsum('ijk,lmk->ilj', X, Y)  It produces an array whose shape is 3 axis  axis 0 (i) the size of first axis of X (here 10) axis 1 (l) size of first axis of Y (here 8) axis 2 (j) second axis of X (2) m is just ignored (size 1) and k (3rd axis of both), since it is repeated is used to sum product So, that is, for each i, l and j, result[i,l,j] is Σₖ X[i,j,k]*Y[l,m,k] (m being 0 anyway)  Dot product You could also just use matmul as you intended. It can work with bigger than 2D arrays (and then operation are element-wise, like + or * for all axis, but the 2 last, which behave like the 2D dot product). But for that you need some adjustment to your shapes before. Since you want 10x8 array of result, those 10 and 8 must be on their own axis. So axis 0 for size 10, axis 1 for size 8. So we need to reshape X as a (10, 1, 2, 3) array. And Y as a (1, 8, 1, 3) array. So that the "element-wise" behavior of the 2 first axis result in broadcast (you can do element-wise operations as long as you have either matching size of each axis, or one of the axis is size 1, and is then broadcasted. So, here, the (10,1) & (1,8) sizes of the 2 first axis of X and Y would result to a (10,8) result.) And furthermore, to be able to have some dot product on the 2 last axis, they must be in the traditional (n,m) (m,k) pattern. Here (2,3) (3,1). So we need also to swap the 2 last axis of Y. All together (X[:,None,...] @ (Y[None,...].transpose(0,1,3,2)))[...,0]  The [...,0] being the same as yours, to ignore the size 1 axis. Note that all those operations (but the matmul itself, of course) are almost for free. No data is moved, copied or modified by X[:,None,...] or by .transpose(0,1,3,2). Only meta data (strides and shape) are changed. That is O(1) cost. Only the 10x832 multiplications are done on the data. Which of course is needed. So performance-wise that is as vectorized as it can be. Performance-wise, on your example (and my computer), it is 21 μs vs 7 μs (so in favor of second solution). But that could be different for other shapes. For example, with sizes (30,50,60) and (20,1,60), it is even 3ms vs 3ms. So einsum could be faster in the long run. But well, both are completely "vectorized" (all iterations are done in internal C code)
Question: I have an MINLP problem and let's say the continuous variable Q can only be 0 when the binary variable z is 0. Two ways to formulate this would be: m.Equation(Q*(1-z) == 0) (1) or m.Equation(Q < z*10000) (2) whereby 10000 would be the upper bound to the continuous variable Q. Does (1) or (2) have any benefits over the other? I've used (1) in my model for heat exchanger network synthesis and I got a good solution pretty quickly. Using (2) takes around 100x longer and it gives worse solution than the one given using (1). From what I can see, the MINLP relaxation to (1) would still require z to be exactly 1 for Q to take on non-zero values. Does this have any effect on how APOPT solve the problem?

Answer: Q(1-z) = 0 is non-linear and non-convex while Q <= 10000z is linear (and convex). The last one is much better as long as the big-M constant is small. If you can't reduce the size of the big-M constant, consider using indicator constraints (using suitable modeling tools and solvers).
Question: I try to convert cyrillic string to readable format. I have the similar code for php and it work fine. But python was harder. import re from sys import getdefaultencoding def decodeString(matches): return chr(int(matches.group(0).lstrip('\\'), 8)) my_string = r'\320\222\321\213\320\263\321\200\321\203\320\267\320\272\320\260 \320\267\320\260\321\217\320\262\320\276\320\272' decoded_string = re.sub(r'\\[0-7]{3}', decodeString, my_string) print(decoded_string) my_string2 = "\320\222\321\213\320\263\321\200\321\203\320\267\320\272\320\260 \320\267\320\260\321\217\320\262\320\276\320\272" print(my_string2) print(sys.stdin.encoding, sys.stdout.encoding)  Both these way return the same result: ÐÑÐ³ÑÑÐ·ÐºÐ° Ð·Ð°ÑÐ²Ð¾Ðº Ð² 1C ÐÑÐ³ÑÑÐ·ÐºÐ° Ð·Ð°ÑÐ²Ð¾Ðº Ð² 1C utf-8 utf-8  Expected result - "Выгрузка заявок".

Answer: If you are able to get around using r'' then using b'' should work: def decode_utf8(byte_string: bytes) -> str: return byte_string.decode('utf-8') # Example usage byte_string = b'\320\222\321\203\320\263\321\200\321\203\320\267\320\272\320\260 \320\267\320\260\321\217\320\262\320\276\320\272' print(decode_utf8(byte_string)) # Output: "Выгрузка заявок"  If r'' is necessary somehow then you can do this: Those \320\222 sequences are octal-escaped bytes of a UTF-8 string. To do this in Python, try:  Convert each \NNN (octal) to its single byte (0–255). Combine those bytes into a bytes object. You should use latin-1 Decode that bytes object as UTF-8.  Example: import re def decode_octal_utf8(octal_string): # 1) Replace each \NNN with its corresponding byte (0–255). def replace_octal(m): return chr(int(m.group(1), 8)) # e.g. "320" -> 208 # 2) Convert to a "byte-like" string (via latin-1 to keep bytes 0-255 unchanged). tmp = re.sub(r'\\([0-7]{3})', replace_octal, octal_string) raw_bytes = tmp.encode('latin-1') return raw_bytes.decode('utf-8')  Output using that string: Выгрузка заявок
Question: I know set_bad can colour the pixel into a specific colour but in my example I only want to have edge colour for blue and grey pixels with values and not the bad pixels (red) import matplotlib.pyplot as plt import xarray as xr import numpy as np from matplotlib import colors fig, ax = plt.subplots(1, 1, figsize=(12, 8)) # provide example data array with a mixture of floats and nans in them data = xr.DataArray([np.random.rand(10, 10)]) # Example data # set a few nans data[0, 1, 1] = np.nan data[0, 1, 2] = np.nan data[0, 1, 3] = np.nan data[0, 2, 1] = np.nan data[0, 2, 2] = np.nan data[0, 2, 3] = np.nan data[0, 3, 1] = np.nan data[0, 3, 2] = np.nan data[0, 3, 3] = np.nan cmap = colors.ListedColormap(['#2c7bb6', "#999999"]) # make nan trends invalid and set edgecolour to white cmap.set_bad(color = 'red') data.plot(edgecolor = "grey", cmap = cmap)  

Answer: Update: I was premature in my original answer (see below), and you can actually pass a list of edge colours (see pcolormesh) that can be used for each "box" within the plot. So, you could use: import xarray as xr import numpy as np from matplotlib import pyplot as plt from matplotlib import colors fig, ax = plt.subplots(1, 1, figsize=(12, 8)) # provide example data array with a mixture of floats and nans in them data = xr.DataArray([np.random.rand(10, 10)]) # Example data # set a few nans data[0, 1, 1] = np.nan data[0, 1, 2] = np.nan data[0, 1, 3] = np.nan data[0, 2, 1] = np.nan data[0, 2, 2] = np.nan data[0, 2, 3] = np.nan data[0, 3, 1] = np.nan data[0, 3, 2] = np.nan data[0, 3, 3] = np.nan # get edgecolors - "grey" for good values red for "bad" edgecolors = [ "grey" if np.isfinite(c) else "red" # could also just have "none" for c in data.values.flatten() ] cmap = colors.ListedColormap(['#2c7bb6', "#999999"]) cmap.set_bad("red") data.plot(edgecolors=edgecolors, cmap = cmap) plt.show()   Original answer I'm afraid you can't remove the edge color from only around the "bad" values, but what you can do is overplot the bad values without any edge color set. E.g., import xarray as xr import numpy as np from matplotlib import pyplot as plt from matplotlib import colors fig, ax = plt.subplots(1, 1, figsize=(12, 8)) # provide example data array with a mixture of floats and nans in them data = xr.DataArray([np.random.rand(10, 10)]) # Example data # set a few nans data[0, 1, 1] = np.nan data[0, 1, 2] = np.nan data[0, 1, 3] = np.nan data[0, 2, 1] = np.nan data[0, 2, 2] = np.nan data[0, 2, 3] = np.nan data[0, 3, 1] = np.nan data[0, 3, 2] = np.nan data[0, 3, 3] = np.nan cmap = colors.ListedColormap(['#2c7bb6', "#999999"]) data.plot(edgecolors="grey", cmap = cmap) # get new array of "bad" values with values of 1 and non-bad values with values of NaN data_bad = xr.where(data.isnull(), 1.0, np.nan) ax = plt.gca() # plot "bad" values as red without any edge color cmap_bad = colors.ListedColormap(["red"]) data_bad.plot(ax=ax, edgecolors="none", cmap=cmap_bad, add_colorbar=False) plt.show()
Question: Being a total newbie in the python ecosystem, I'm discovering uv and was wondering if there was a difference between the following commands : uv lock --upgrade and uv sync If there's any, what are the exact usage for each of them ?

Answer: uv lock commands are all about managing the uv.lock file (or creating it). But what they NOT do: upgrading the actual package versions in your environment! The uv lock --upgrade command updates the lock file (uv.lock) by allowing package upgrades, even if they were previously pinned. But still it is a managing command for the uv.lock file and does NOT upgrade anything in the environment (package versions). It upgrades only the lock file. uv sync commands are upgrading the actual environment and packages within ensuring the actual environment's package versions align with what’s recorded in uv.lock file. You can get detailed info about both commands by typing: uv help lock  or: uv help sync
Question: I am given a two-dimensional array. Each element represents the x,y coordinates of a trapezium. I do not want negative values so I need to adjust the minimum x value to zero and I want to adjust the minimum y value to zero. I can do this (see below), but in a very long winded way. Is there a more elegant way to normalise the arrays? import numpy as np # This line is given pa = np.array([[ 213.00002 , 213.00002 ],[ -213.00002 , 213.00002 ],[ 213.00002 , -213.00002 ],[ -213.00002 , -213.00002 ]]) # This line is given #1 get values pa_x_values = np.array([(pa[0][0]),(pa[1][0]),(pa[2][0]),(pa[3][0])]) pa_y_values = np.array([(pa[0][1]),(pa[1][1]),(pa[2][1]),(pa[3][1])]) #2 get minimum value pa_min_x = min(pa_x_values) pa_min_y = min(pa_y_values) #3 calculate difference from zero p1_dx = 0 - pa_min_x p1_dy = 0 - pa_min_y #4 make new array p1 = np.array([[0,0],[0,0],[0,0],[0,0]],dtype=np.float32) #5 normalise for i in range(4): p1[i][0] = (pa[i][0]) + p1_dx p1[i][1] = (pa[i][1]) + p1_dy # RESULT # p1 # [[426.00003, 426.00003], [ 0, 426.00003], [426.00003, 0 ], [ 0, 0 ]] 

Answer: You can use .min(0) to get the minimum for each of x and y individually and then subtract that from the entire array. pa -= pa.min(0)