问题是,如何在数组中删除多次出现的元素。下面你会看到一个在更大的阵列上非常慢的方法。 有没有想过这样做的numpy-way?提前致谢。
import numpy as np
count = 0
result = []
input = np.array([[1,1], [1,1], [2,3], [4,5], [1,1]]) # array with points [x, y]
# count appearance of elements with same x and y coordinate
# append to result if element appears just once
for i in input:
for j in input:
if (j[0] == i [0]) and (j[1] == i[1]):
count += 1
if count == 1:
result.append(i)
count = 0
print np.array(result)
再次明确:如何从数组/列表中删除多次出现的关于某个属性的元素?这里:列表包含长度为6的元素,如果每个元素的第一个和第二个条目在列表中都出现多次,则从列表中删除所有相关元素。希望我不要混淆。 Eumiro在这方面给了我很多帮助,但是我没有设法将输出列表弄平,因为它应该是:(
import numpy as np
import collections
input = [[1,1,3,5,6,6],[1,1,4,4,5,6],[1,3,4,5,6,7],[3,4,6,7,7,6],[1,1,4,6,88,7],[3,3,3,3,3,3],[456,6,5,343,435,5]]
# here, from input there should be removed input[0], input[1] and input[4] because
# first and second entry appears more than once in the list, got it? :)
d = {}
for a in input:
d.setdefault(tuple(a[:2]), []).append(a[2:])
outputDict = [list(k)+list(v) for k,v in d.iteritems() if len(v) == 1 ]
result = []
def flatten(x):
if isinstance(x, collections.Iterable):
return [a for i in x for a in flatten(i)]
else:
return [x]
# I took flatten(x) from http://stackoverflow.com/a/2158522/1132378
# And I need it, because output is a nested list :(
for i in outputDict:
result.append(flatten(i))
print np.array(result)
所以,这很有效,但是对于大型列表来说这是不切实际的。 首先,我得到了 RuntimeError:cmp中超出的最大递归深度 申请后 sys.setrecursionlimit(10000) 我有 分段故障 我怎样才能为大名单实施Eumiros解决方案> 100000个元素?
答案 0 :(得分:3)
np.array(list(set(map(tuple, input))))
返回
array([[4, 5],
[2, 3],
[1, 1]])
更新1:如果您想删除[1, 1]
(因为它出现多次),您可以执行以下操作:
from collections import Counter
np.array([k for k, v in Counter(map(tuple, input)).iteritems() if v == 1])
返回
array([[4, 5],
[2, 3]])
更新2:与input=[[1,1,2], [1,1,3], [2,3,4], [4,5,5], [1,1,7]]
:
input=[[1,1,2], [1,1,3], [2,3,4], [4,5,5], [1,1,7]]
d = {}
for a in input:
d.setdefault(tuple(a[:2]), []).append(a[2])
d
现在是:
{(1, 1): [2, 3, 7],
(2, 3): [4],
(4, 5): [5]}
所以我们想要获取所有键值对,它们具有单个值并重新创建数组:
np.array([k+tuple(v) for k,v in d.iteritems() if len(v) == 1])
返回:
array([[4, 5, 5],
[2, 3, 4]])
更新3:对于较大的数组,您可以将我以前的解决方案调整为:
import numpy as np
input = [[1,1,3,5,6,6],[1,1,4,4,5,6],[1,3,4,5,6,7],[3,4,6,7,7,6],[1,1,4,6,88,7],[3,3,3,3,3,3],[456,6,5,343,435,5]]
d = {}
for a in input:
d.setdefault(tuple(a[:2]), []).append(a)
np.array([v for v in d.itervalues() if len(v) == 1])
返回:
array([[[456, 6, 5, 343, 435, 5]],
[[ 1, 3, 4, 5, 6, 7]],
[[ 3, 4, 6, 7, 7, 6]],
[[ 3, 3, 3, 3, 3, 3]]])
答案 1 :(得分:2)
这是Hooked答案的更正版本。 count_unique
计算密钥中每个唯一密钥的出现次数。
import numpy as np
input = np.array([[1,1,3,5,6,6],
[1,1,4,4,5,6],
[1,3,4,5,6,7],
[3,4,6,7,7,6],
[1,1,4,6,88,7],
[3,3,3,3,3,3],
[456,6,5,343,435,5]])
def count_unique(keys):
"""Finds an index to each unique key (row) in keys and counts the number of
occurrences for each key"""
order = np.lexsort(keys.T)
keys = keys[order]
diff = np.ones(len(keys)+1, 'bool')
diff[1:-1] = (keys[1:] != keys[:-1]).any(-1)
count = np.where(diff)[0]
count = count[1:] - count[:-1]
ind = order[diff[1:]]
return ind, count
key = input[:, :2]
ind, count = count_unique(key)
print key[ind]
#[[ 1 1]
# [ 1 3]
# [ 3 3]
# [ 3 4]
# [456 6]]
print count
[3 1 1 1 1]
ind = ind[count == 1]
output = input[ind]
print output
#[[ 1 3 4 5 6 7]
# [ 3 3 3 3 3 3]
# [ 3 4 6 7 7 6]
# [456 6 5 343 435 5]]
答案 2 :(得分:1)
从下面的评论中,新的解决方案是:
idx = argsort(A[:, 0:2], axis=0)[:,1]
kidx = where(sum(A[idx,:][:-1,0:2]!=A[idx,:][1:,0:2], axis=1)==0)[0]
kidx = unique(concatenate((kidx,kidx+1)))
for n in arange(0,A.shape[0],1):
if n not in kidx:
print A[idx,:][n]
> [1 3 4 5 6 7]
[3 3 3 3 3 3]
[3 4 6 7 7 6]
[456 6 5 343 435 5]
kidx
是您不想要的元素的索引列表。这保留了前两个内部元素与任何其他内部元素不匹配的行。因为一切都是通过索引来完成的,所以它应该是快速的(ish),尽管它需要对前两个元素进行排序。请注意,原始行顺序不会保留,但我不认为这是一个问题。
如果我理解正确,你只想过滤掉列表列表的结果,其中每个内部列表的第一个元素等于第二个元素。
根据您的更新A=[[1,1,3,5,6,6],[1,1,4,4,5,6],[1,3,4,5,6,7],[3,4,6,7,7,6],[1,1,4,6,88,7],[3,3,3,3,3,3],[456,6,5,343,435,5]]
的输入,以下行会删除A[0]
,A[1]
和A[4]
。 A[5]
也会被移除,因为这似乎符合您的条件。
[x for x in A if x[0]!=x[1]]
如果你可以使用numpy,有一种非常灵活的方式来做上述事情。假设A
是一个数组,那么
A[A[0,:] == A[1,:]]
将拉出相同的值。如果你想循环它,这可能比上面列出的解决方案更快。
答案 3 :(得分:-2)
为什么不创建另一个数组来保存输出?
遍历您的主列表并检查每个i
检查i
是否在您的其他数组中,如果没有附加它。
这样,您的新数组将不包含多个元素