1

I have a 2d NumPy array that looks like this:

array([[1, 1],
       [1, 2],
       [2, 1],
       [2, 2],
       [3, 1],
       [5, 1],
       [5, 2]])

and I want to group it and have an output that looks something like this:

         Col1 Col2
group 1: 1-2, 1-2
group 2: 3-3, 1-1
group 3: 5-5, 1-2

I want to group the columns based on if they are consecutive.

So, for a unique value In column 1, group data in the second column if they are consecutive between rows. Now for a unique grouping of column 2, group column 1 if it is consecutive between rows.

The result can be thought of as corner points of a grid. In the above example, group 1 is a square grid, group 2 is a a point, and group 3 is a flat line.

My system won't allow me to use pandas so I cannot use group_by in that library but I can use other standard libraries.

Any help is appreciated. Thank you

6
  • 1
    I don't understand how the output corresponds to the input - will you please elaborate? Commented Mar 18, 2022 at 22:08
  • 1
    @richardec I cannot seem to edit the question at the moment. For each unique value in column 1, group column 2 if column 2 is consecutive. Once this is grouped, for each grouped column 2, group column 1 if it is consecutive. You see that the first 4 rows form a square (if plotted). The 5th rows is a dot if plotted. And rows 6 and 7 form a flat line if plotted. Does this help? Commented Mar 18, 2022 at 22:15
  • I can't see why row [3,1] doesn't belong into group 1 according to your logic. Commented Mar 18, 2022 at 23:41
  • @MichaelSzczesny because column 2 is not consecutive with the row below with the same column 1 value. The row below isn't the same column value. Commented Mar 18, 2022 at 23:55
  • If [3,1] isn't a unique grouping according to step 1, shouldn't it belong to no group according to step 2 for a unique grouping of column 2, group column 1...? Commented Mar 19, 2022 at 0:17

1 Answer 1

3

Here you go ...

Steps are:

  • Get a list xUnique of unique column 1 values with sort order preserved.
  • Build a list xRanges of items of the form [col1_value, [col2_min, col2_max]] holding the column 2 ranges for each column 1 value.
  • Build a list xGroups of items of the form [[col1_min, col1_max], [col2_min, col2_max]] where the [col1_min, col1_max] part is created by merging the col1_value part of consecutive items in xRanges if they differ by 1 and have identical [col2_min, col2_max] value ranges for column 2.
  • Turn the ranges in each item of xGroups into strings and print with the required row and column headings.
  • Also package and print as a numpy.array to match the form of the input.
import numpy as np
data = np.array([
    [1, 1],
    [1, 2],    
    [2, 1],    
    [2, 2],
    [3, 1],
    [5, 1],
    [5, 2]])
xUnique = list({pair[0] for pair in data})
xRanges = list(zip(xUnique, [[0, 0] for _ in range(len(xUnique))]))
rows, cols = data.shape
iRange = -1
for i in range(rows):
    if i == 0 or data[i, 0] > data[i - 1, 0]:
        iRange += 1
        xRanges[iRange][1][0] = data[i, 1]
    xRanges[iRange][1][1] = data[i, 1]
xGroups = []
for i in range(len(xRanges)):
    if i and xRanges[i][0] - xRanges[i - 1][0] == 1 and xRanges[i][1] == xRanges[i - 1][1]:
        xGroups[-1][0][1] = xRanges[i][0]
    else:
        xGroups += [[[xRanges[i][0], xRanges[i][0]], xRanges[i][1]]]

xGroupStrs = [ [f'{a}-{b}' for a, b in row] for row in xGroups]

groupArray = np.array(xGroupStrs)
print(groupArray)

print()
print(f'{"":<10}{"Col1":<8}{"Col2":<8}')
[print(f'{"group " + str(i) + ":":<10}{col1:<8}{col2:<8}') for i, (col1, col2) in enumerate(xGroupStrs)]

Output:

[['1-2' '1-2']
 ['3-3' '1-1']
 ['5-5' '1-2']]

          Col1    Col2
group 0:  1-2     1-2
group 1:  3-3     1-1
group 2:  5-5     1-2
Sign up to request clarification or add additional context in comments.

5 Comments

Breaks for [[1, 1],[2, 1]] and all consecutive 'point shapes'.
@Michael Szczesny [[1, 1], [2, 1]] gives [['1-2' '1-1']] as output. Is that not what you would expect?
@constantstranger this is giving the answer I am looking for - thank you very much!!
@Aidan O'Farrell Thanks for confirming. Do you need any more help with your question?
@constantstranger no I do not. That is exactly what I need, many thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.