Избавление от лишних 2D точек без потери порядка - PullRequest
1 голос
/ 18 февраля 2020

У меня есть следующие точки:

import numpy as np
points = np.array([[49.8, 66.35],
 [49.79, 66.35],
 [49.79, 66.35],
 [44.65, 67.25],
 [44.65, 67.25],
 [44.65, 67.25],
 [44.48, 67.24],
 [44.63, 67.21],
 [44.68, 67.2],
 [49.69, 66.21],
 [49.85, 66.17],
 [50.51, 66.04],
 [49.8, 66.35]])

Когда я строю их, я получаю эту форму:

import matplotlib.pyplot as plt
x = [a[0] for a in points ]
y = [a[1] for a in points ]
plt.plot(x,y)

enter image description here

Как видно из списка точек, некоторые из них являются избыточными (т. Е. Посмотрите на точки 1 и 2 (начиная с 0)).

Чтобы сохранить только избыточные точки, я вернулся к ответу на этот вопрос: Удаление дублирующихся столбцов и строк из NumPy 2D-массива

def unique_2D(a):
    order = np.lexsort(a.T)
    a = a[order]
    diff = np.diff(a, axis=0)
    ui = np.ones(len(a), 'bool')
    ui[1:] = (diff != 0).any(axis=1) 
    return a[ui]

Я применяю эту функцию к своим точкам и получаю:

non_redundant_points = unique_2D(points)

Вот распечатанный список сохраненных точек:

[[ 50.51  66.04]
 [ 49.85  66.17]
 [ 49.69  66.21]
 [ 49.79  66.35]
 [ 49.8   66.35]
 [ 44.68  67.2 ]
 [ 44.63  67.21]
 [ 44.48  67.24]
 [ 44.65  67.25]]

Однако теперь я сталкиваюсь со следующей проблемой: когда я их строю, порядок как-то не сохраняется ...

x_nr = [a[0] for a in non_redundant_points ]
y_nr = [a[1] for a in non_redundant_points ]
plt.plot(x_nr,y_nr)

enter image description here

Знаете, как я могу решить эту проблему?

Для упрощения копирования и вставки , вот полный код:

import numpy as np    
import matplotlib.pyplot as plt

points = np.array([[49.8, 66.35],
 [49.79, 66.35],
 [49.79, 66.35],
 [44.65, 67.25],
 [44.65, 67.25],
 [44.65, 67.25],
 [44.48, 67.24],
 [44.63, 67.21],
 [44.68, 67.2],
 [49.69, 66.21],
 [49.85, 66.17],
 [50.51, 66.04],
 [49.8, 66.35]])

x = [a[0] for a in points ]
y = [a[1] for a in points ]
plt.plot(x,y)

def unique_2D(a):
        order = np.lexsort(a.T)
        a = a[order]
        diff = np.diff(a, axis=0)
        ui = np.ones(len(a), 'bool')
        ui[1:] = (diff != 0).any(axis=1) 
        return a[ui]

x_nr = [a[0] for a in non_redundant_points ]
y_nr = [a[1] for a in non_redundant_points ]
plt.plot(x_nr,y_nr)

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Вы можете использовать np.unique для получения уникальных элементов и return_index=True для получения индексов исходного массива. Затем вы можете использовать их для сортировки возвращенного уникального массива, чтобы получить исходный индексный порядок

points = np.array([[49.8, 66.35],
                   [49.79, 66.35],
                   [49.79, 66.35], ... ] # Your original input array

points, idx = np.unique(points, axis=0, return_index=True)
print (idx)
# [ 6  7  3  8  9  1  0 10 11]


arr = points[np.argsort(idx), :]

print (arr)

# [[49.8  66.35]
#  [49.79 66.35]
#  [44.65 67.25]
#  [44.48 67.24]
#  [44.63 67.21]
#  [44.68 67.2 ]
#  [49.69 66.21]
#  [49.85 66.17]
#  [50.51 66.04]]

Построение графика

plt.plot(arr[:, 0], arr[:, 1])

enter image description here

0 голосов
/ 18 февраля 2020

Вы можете отслеживать, какие точки уже существуют в set, который вы видели. Для этого вы можете создать класс, который позволяет хэшировать и сравнивать точки:

In [93]: class Point:
...:     def __init__(self, x, y):
...:         self.x=x
...:         self.y=y
...:     def __hash__(self):
...:         return hash((self.x, self.y))
...:     def __eq__(self, other):
...:         return self.x == other.x and self.y == other.y
...:     def __str__(self):
...:         return f'({self.x}, {self.y})'
...:     def __repr__(self):
...:         return str(self)
...:

In [94]: points = [[49.8, 66.35],
...:  [49.79, 66.35],
...:  [49.79, 66.35],
...:  [44.65, 67.25],
...:  [44.65, 67.25],
...:  [44.65, 67.25],
...:  [44.48, 67.24],
...:  [44.63, 67.21],
...:  [44.68, 67.2],
...:  [49.69, 66.21],
...:  [49.85, 66.17],
...:  [50.51, 66.04],
...:  [49.8, 66.35]]

Теперь мы можем преобразовать точки в массив Point's

In [95]: points = [Point(*p) for p in points]
In [96]: points
Out[96]:
[(49.8, 66.35),
 (49.79, 66.35),
 (49.79, 66.35),
 (44.65, 67.25),
 (44.65, 67.25),
 (44.65, 67.25),
 (44.48, 67.24),
 (44.63, 67.21),
 (44.68, 67.2),
 (49.69, 66.21),
 (49.85, 66.17),
 (50.51, 66.04),
 (49.8, 66.35)]

Все, что нам нужно чтобы сделать это сейчас, просто l oop через точки и добавьте его в список unique, если мы его еще не видели

In [102]: seen = set()

In [103]: new_points = []

In [104]: for point in points:
     ...:     if point not in seen:
     ...:         new_points.append(point)
     ...:         seen.add(point)
     ...:

In [105]: new_points
Out[105]:
[(49.8, 66.35),
 (49.79, 66.35),
 (44.65, 67.25),
 (44.48, 67.24),
 (44.63, 67.21),
 (44.68, 67.2),
 (49.69, 66.21),
 (49.85, 66.17),
 (50.51, 66.04)]

Теперь ваш порядок поддерживается без повторяющихся точек.

РЕДАКТИРОВАТЬ: Я думаю, что я неправильно понял часть вопроса. Я думаю, вы просто хотите игнорировать последовательные наборы? Как и в случае, только повторяя точки сразу после другой точки, но если это в конце, то вы хотите сохранить его. Если это так, вы можете сделать:

In [114]: new_points = [points[0]]

In [115]: repeat = new_points[0]

In [116]: for point in points[1:]:
     ...:     # New point found, i.e. not a repeat from previous sequential set
     ...:     if point != repeat:
     ...:         repeat = point
     ...:         new_points.append(point)
     ...:

In [117]: new_points
Out[117]:
[(49.8, 66.35),
 (49.79, 66.35),
 (44.65, 67.25),
 (44.48, 67.24),
 (44.63, 67.21),
 (44.68, 67.2),
 (49.69, 66.21),
 (49.85, 66.17),
 (50.51, 66.04),
 (49.8, 66.35)]

А затем преобразовать его для построения графика:

points = np.array([[p.x, p.y] for p in new_points])
plt.plot(points[:,0], points[:,1])

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...