我有两个数组a
和b
,我想为它们找到第一个 n 唯一索引(在a
和{{ 1}})项。最好用一个例子来解释:
b
对于n = 1,我期望结果为# 0 1 2 3 4 5 6 7 8 9 10 11 12
a = np.asarray([1, 1, 2, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6])
b = np.asarray([0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 1, 1, 1])
(列表不包含index = 1,因为它已经由index = 0([0, 2, 3, 4, 5, 7, 8, 10]
)给出,而不是index = 6,因为那是已经由结果列表中的index = 4给出,但不包括index = 9,因为index = 8是等效的。)
对于n = 2,结果应为(a[0], b[0]) == (a[1], b[1])
(结果中允许在[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
和a
上出现2个唯一的出现)。
我不知道如何用numpy来表达这一点……感谢您的帮助。
答案 0 :(得分:3)
检查以下内容,我正在使用lexsort
通过两个数组获取排序顺序,然后使用diff
和flatnonzero
查找需要添加split
点的组< / p>
ind = np.lexsort((a, b))
v=np.column_stack([a,b])
sid=np.flatnonzero(np.any(np.diff(v[ind,:].T)>0,0))+1
yourlist=np.split(np.arange(len(a))[ind], sid)
n=1
np.concatenate([x[:n]for x in yourlist])
Out[347]: array([ 0, 3, 4, 7, 8, 2, 10, 5])
答案 1 :(得分:2)
这不是100%NumPy解决方案。最后一步使用列表理解。我不确定100%NumPy解决方案是否可行。但是:
将数组合并为二维数组:
ab2d = np.stack([a, b]).T
查找唯一值:
uniq = np.unique(ab2d, axis=0)
对于每个唯一值,请在2d数组中找到其最小的索引N
:
N = 2
np.concatenate([np.argwhere((pair == ab2d).all(axis=1))[:N, 0]
for pair in uniq])
#array([ 0, 1, 3, 2, 4, 6, 5, 7, 8, 9, 10, 11])
答案 2 :(得分:1)
方法1::如果可以使用pandas
,则非常简单明了-
In [41]: import pandas as pd
In [42]: df = pd.DataFrame({'a':a,'b':b})
In [43]: [np.flatnonzero(df.groupby(['a','b']).cumcount()<n) for n in [1,2]]
Out[43]:
[array([ 0, 2, 3, 4, 5, 7, 8, 10]),
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])]
方法2:对于具有ints
且注重性能的输入数组,我们可以使用 more-NumPy 版本,如下所示->
# https://stackoverflow.com/a/43211485/ @Divakar
def array_cumcount(a):
idx = np.flatnonzero(a[1:] != a[:-1])+1
shift_arr = np.ones(a.size,dtype=int)
shift_arr[0] = 0
if len(idx)>=1:
shift_arr[idx[0]] = -idx[0]+1
shift_arr[idx[1:]] = -idx[1:] + idx[:-1] + 1
return shift_arr.cumsum()
ab = a*(b.max()+1) + b
sidx = ab.argsort()
ab_s = ab[sidx]
cumcounts = array_cumcount(ab_s)[sidx]
out = [np.flatnonzero(cumcounts<n) for n in [1,2]]
答案 3 :(得分:1)
@Divakar的第二种方法似乎最快。
@DYZ 1000 loops, best of 3: 1.02 ms per loop
@Wen-Ben 1000 loops, best of 3: 234 µs per loop
@Divakar(pandas) 100 loops, best of 3: 1.9 ms per loop
@Divakar(numpy) 10000 loops, best of 3: 58.5 µs per loop
经过测试
a = np.random.randint(10, size=1000, dtype=int)
b = np.random.randint(5, size=1000, dtype=int)
n = 5
,但结论也适用于较小的数组大小和 n 值。粗略地看@DYZ的方法表明np.unique
相对较慢,@ Wen-Ben的np.lexsort
也相对较慢(列表理解对运行时的贡献不大)。