【问题标题】:Finding ONLY Unique Coordinates in List仅在列表中查找唯一坐标
【发布时间】:2018-05-13 17:13:53
【问题描述】:

我有一个坐标列表,比如

list_cor = 
    [[4190091.4195999987, 7410226.618699998], 
    [4190033.2124999985, 7410220.0823], 
    [4190033.2124999985, 7410220.0823], 
    [4190035.7005000003, 7410208.670500003], 
    [4190033.2124999985, 7410220.0823], 
    [4190022.768599998, 7410217.844300002]]

我只需要获取这些值:

[[4190091.4195999987, 7410226.618699998], 
[4190035.7005000003, 7410208.670500003], 
[4190022.768599998, 7410217.844300002]]

试过numpy.unique(),但它添加了这个项目[4190033.2124999985, 7410220.0823],我不需要。

【问题讨论】:

  • 可能令人困惑的是np.unique(list_cor, axis=0) 为您提供删除重复的数组;它不会将数组过滤为原始数组中唯一的元素
  • 现在我明白了

标签: python list numpy unique


【解决方案1】:

你快到了:

coords=[ x+1j*y for (x,y) in list_cor] # using complex; a way for grouping
uniques,counts=np.unique(coords,return_counts=True)
res=[ [x.real,x.imag] for x in uniques[counts==1] ] # ungroup

对于:

[[4190022.7685999982, 7410217.8443000019],
 [4190035.7005000003, 7410208.6705000028],
 [4190091.4195999987, 7410226.6186999977]]

【讨论】:

  • 似乎 return_counts=True 只能在 Numpy >= 1.9 的情况下使用。
  • @B. M. 您的代码有效,但我还没有使用 numpy,根据 @tobias_k 评论,Numpy >= 1.9 是什么意思?
  • @PavelPereverzev 我的意思是这个功能是在 Numpy 1.9 版中添加的。您可以通过import numpy; print(numpy.__version__)查看您的版本
  • @tobias_k 检查版本,它是 1.9.3 ,所以一切正常
【解决方案2】:

对于没有 return_counts 参数的旧版本 numpy,您可以自行使用 collections.Counter

>>> list_cor = np.array(list_cor)  # assuming list_cor is a numpy array
>>> counts = collections.Counter(map(tuple, list_cor))
>>> counts_arr = np.array([counts[tuple(x)] for x in list_cor])
>>> list_cor[counts_arr == 1]
array([[ 4190091.4196,  7410226.6187],
       [ 4190035.7005,  7410208.6705],
       [ 4190022.7686,  7410217.8443]])

【讨论】:

  • 嗯,给我TypeError: only integer arrays with one element can be converted to an index
  • @PavelPereverzev 这很奇怪。请注意,我假设您的 list_cor 是一个 numpy 数组,因为您将问题标记为 numpy。它不适用于数组吗?
  • 是的,与数组对话后一切正常
【解决方案3】:

在简单的纯python基本类型中:

# transform to tuples
list_cor=[tuple(c) for c in list_cor]
# transform back after using set to select unique elements only
list_cor_unique=[list(l) for l in list(set(list_cor))]
# create a copy
list_cor_more_than_once = [i for i in list_cor]
# drop all the elements appearing only once
[list_cor_more_than_once.remove(tuple(l)) for l in list_cor_unique if tuple(l) in list_cor]
# finally, keep the uniques not appearing more than once
list_cor_unique=[l for l in list_cor_unique if (tuple(l) in list_cor) and (not (tuple(l) in list_cor_more_than_once)) ]

优点:

  • 没有外部库

  • 适用于更高维度的坐标

【讨论】:

  • 不幸的是,它提供了一个我不需要在 list_cor_unique 中的值:[4190033.2124999985, 7410220.0823]
【解决方案4】:

我喜欢使用字典来记录计数:

>>> counts = {}
>>> for coordinate in list_cor:
...     coordinate = tuple(coordinate) # so it can be hashed and used as dict key
...     counts.setdefault(coordinate, 0) # add coordinate to dict
...     counts[coordinate] += 1 # increment count for coordinate
...

然后你有一个看起来像这样的字典:

>>> counts
{(4190091.4195999987, 7410226.618699998): 1, (4190033.2124999985, 7410220.0823): 3, (4190035.7005000003, 7410208.670500003): 1, (4190022.768599998, 7410217.844300002): 1}

然后您可以使用列表推导来创建唯一坐标列表:

>>> [list(coordinate) for coordinate, count in counts.items() if count == 1]
[[4190091.4195999987, 7410226.618699998], [4190035.7005000003, 7410208.670500003], [4190022.768599998, 7410217.844300002]]

如果您可以将坐标保留为元组,您可以将list(coordinate) 替换为coordinate

【讨论】:

  • 我也考虑过使用字典,但认为有一种更快的方法来获取唯一值,而不是运行多个循环。无论如何,您的代码工作正常!
  • 我不确定更快的方法是什么。我能想到的唯一不会再次迭代的算法是创建两个集合:一个“找到”集合和一个“再次找到”集合。对于每个坐标,如果它已经在“找到”集中,则将其添加到“再次找到”集中;否则将其添加到“找到”集中。然后从 'found' 集合中减去 'found again' 集合以创建一个 'found once' 集合。
  • 知道了。好吧,我认为两套不会节省太多时间,所以字典对我来说足够简单和快速。
【解决方案5】:

numpy.uniqueaxisreturn_counts 参数一起使用:

arr, uniq_cnt = np.unique(list_cor, axis=0, return_counts=True)
uniq_arr = arr[uniq_cnt==1]

【讨论】: