【问题标题】:How to remove duplicate elements for two numpy arrays in python如何在python中删除两个numpy数组的重复元素
【发布时间】:2016-12-06 01:26:29
【问题描述】:

我有两个数组命名为 u,v, 例如

u=np.array([1.0,2.0,2.0,3.0,4.0])
v=np.array([10.0,21.0,18.0,30.0,40.0])
a=np.array([100.0,210.0,220.0,300.0,400.0])

如果 u 中的两个元素相同,则删除 v 值较高的那个。 对于上面的例子,结果应该是

u_new=np.array([1.0,2.0,3.0,4.0])
v_new=np.array([10.0,18.0,30.0,40.0])
a_new=np.array([100.0,220.0,300.0,400.0])

def remove_duplicates(u,v,a):
    u_new, indices = np.unique(u, return_index=True)
    v_new = np.zeros(len(u_new), dtype=np.float64)
    a_new = np.zeros(len(u_new), dtype=np.float64)
    for i in range(len(indices)):
        j1 = indices[i]
        if i < len(indices) - 1:
            j2 = indices[i + 1]
        else:
            j2 = j1 + 1
        v_new[i] = np.amin(v[j1:j2])
        k = np.argmin(v[j1:j2]) + j1
        a_new[i] = a[k]

    return u_new,v_new,a_new

上面的代码在处理浮点数时存在问题,因为两个浮点数之间不完全相等。所以我不得不把它改成一种非常“愚蠢”的方式

def remove_duplicates(u, v, a):
    u_new=u
    v_new=v
    a_new=a
    cnt = 0
    for i in range(len(u)):
        if cnt <1:
            u_new[cnt] = u[i]
            v_new[cnt] = v[i]
            a_new[cnt] = a[i]
            cnt += 1
        else:
            if abs(u[i]-u_new[cnt-1]) > 1e-5:
                u_new[cnt] = u[i]
                v_new[cnt] = v[i]
                a_new[cnt] = a[i]
                cnt += 1
            else:
                print("Two points with same x coord found.ignore", i)
                if v_new[cnt-1] > v[i]:
                    v_new[cnt-1] = v[i]
                    a_new[cnt-1] = a[i]

    return u_new[:cnt], v_new[:cnt], a_new[:cnt]

如何以 Python 方式对其进行编程? 谢谢。

【问题讨论】:

  • 通过循环前两个数组来构造一个新数组对我来说似乎是最可行的。我认为没有就地操作是可取的。
  • 感谢您的评论。我想要更多类似 python 的代码来执行此操作,因为我认为数组上的循环很耗时。
  • 数组是否总是一维并按照您的示例排序?
  • 是的,它们总是一维数组。

标签: python numpy duplicates element


【解决方案1】:

有点厚颜无耻地改变你的问题,但在这里。

def remove_duplicates(u,v,a,d=1e-5):
    s=np.argsort(u)
    ud=abs(u[s][1:]-u[s][:-1])<d
    vd=v[s][1:]<v[s][:-1]
    drop=np.union1d(s[:-1][ud&vd],s[1:][ud&~vd])
    return np.delete(u,drop),np.delete(v,drop),np.delete(a,drop)

这应该使用阈值来清理你的浮动。

【讨论】:

  • 这是我认为最简洁易懂的方法。非常感谢。
【解决方案2】:

您可以使用zipsortedgroupby 函数:

from itertools import groupby
u1, v1 = zip(*[next(g) for k, g in groupby(sorted(zip(u, v)), key = lambda x: x[0])])
# note here use next to take the first element(smaller v value) from each group    

u1
# (1.0, 2.0, 3.0, 4.0)

v1
# (10.2, 22.0, 28.0, 41.0)

【讨论】:

  • 非常漂亮的解决方案。非常感谢。
  • 当numpy数组元素为浮点数时,上面的方法会出现问题,因为两个浮点数之间的比较不准确,没有给出公差。我怎样才能给予宽容并使其发挥作用?谢谢。
  • 我认为您可以将密钥四舍五入到您想要的精度。例如u1, v1 = zip(*[next(g) for k, g in groupby(sorted(zip(u, v)), key = lambda x: round(x[0], 10))])
  • 将浮点数路由到一定精度是一种替代方法。谢谢。
【解决方案3】:

方法#1:这是一种将浮点数分割成可容忍(通过给定的容差值)接近度组的方法 -

tol = 1e-5 # Set tolerance for floating pt number match
A = np.split( v, np.flatnonzero(np.diff(u) > tol)+1)
lens = np.array(list(map(len,A)))
idx = np.array([np.argmax(i) for i in A]) 
idx[1:] += lens[:-1].cumsum()
m = ~np.in1d(np.arange(a.size), idx[lens>1])
u_new, v_new, a_new = u[m], v[m], a[m]

样本输入、输出-

In [143]: u=np.array([1.0,2.0,2.00000001,3.0,3.9999998, 4.0, 4.00000001])
     ...: v=np.array([10.0,21.0,18.0,30.0,36.0, 40.0, 38.0])
     ...: a=np.array([100.0,210.0,220.0,300.0,77.0, 400.0, 67.00])
     ...: 

In [144]: u_new
Out[144]: array([ 1.        ,  2.00000001,  3.        ,  3.9999998 ,  4.00000001])

In [145]: v_new
Out[145]: array([ 10.,  18.,  30.,  36.,  38.])

In [146]: a_new
Out[146]: array([ 100.,  220.,  300.,   77.,   67.])

方法#2:这是另一种不拆分的方法,因此必须更有效 -

u_idx = np.append(False, np.diff(u) > tol).cumsum()
max_idx = (np.append(np.unique(u_idx, return_index=1)[1], u_idx.size)-1)[1:]
sidx = (v.max()*u_idx + v).argsort()
m = ~np.in1d(np.arange(a.size), sidx[max_idx][np.bincount(u_idx)>1])
u_new, v_new, a_new = u[m], v[m], a[m]

【讨论】:

  • 感谢您的两种方法。我相信它们都会很好地工作,尽管我不确定我是否能完全理解它们。
猜你喜欢
  • 2016-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 2018-02-08
  • 1970-01-01
相关资源
最近更新 更多