引言
本文想要解决以下问题:存在一二维矩阵X = { x 1 , x 2 , x 3 . . . } , x i ∈ R 2 X=\{x_1,x_2,x_3...\},x_i\in R^2X={x1,x2,x3...},xi∈R2,x i x_ixi中元素无序,即x i = ( a , b ) ⇔ x j = ( b , a ) x_i=(a,b)\Leftrightarrow x_j=(b,a)xi=(a,b)⇔xj=(b,a),想要从X中清除重复元素。附加约束:X XX中第一列到第二列为单射。
解决方案
提取重复元素
使用python中的set类型,set为无序集合,有集合的所有操作性质如取交集、并集等等,将二维矩阵定义为set类型得到集合S 1 S_1S1,交换X中每个元素内标量的顺序在定义为set类型得到集合S 2 S_2S2,取S 1 , S 2 S_1,S_2S1,S2的交集即得到了重复元素
代码:
x=np.array([[1,3],[5,9],[3,11],[2,7],[10,12],[11,3],[4,6],[6,4],[7,2],[8,11]])
s1=set(tuple([x[i,0],x[i,1]]) for i in range(x.shape[0]))
s2=set(tuple([x[i,1],x[i,0]]) for i in range(x.shape[0]))
bond=s1&s2
结果:
s1
Out[10]: {(1, 3),(2, 7),(3, 11),(4, 6),(5, 9),(6, 4),(7, 2),(8, 11),(10, 12), (11, 3)}
bond
Out[11]: {(2, 7), (3, 11), (4, 6), (6, 4), (7, 2), (11, 3)}
删除重复元素
得到重复元素之后,每个重复元素都可组成形如( a , b ) , ( b , a ) (a,b),(b,a)(a,b),(b,a)的对子,因此我们不能直接用原始集合减去重复元素集合,否则会失去这些数据,而是应该删去对子中的任意一个以达到去重的目的。删去重复元素方法如下:
首先,我们对重复元素数据进行排序,排序的依据为数组中每个二维元素的较小值,代码及结果如下:
temp_inter=[]
for i in bond:
temp_inter.append(i)
temp_inter=np.array(temp_inter)
temp_inter=temp_inter[temp_inter.min(axis=1).argsort()]
结果:
array([[ 2, 7],
[ 7, 2],
[11, 3],
[ 3, 11],
[ 6, 4],
[ 4, 6]])
可以看出通过上述操作奇偶位置的元素即构成了一组对子,通过slice操作即可取出重复元素对子中的一个,代码及结果如下:
temp_inter=temp_inter[::2,:]
结果:
array([[ 2, 7],
[11, 3],
[ 6, 4]])
整体代码如下:
x=np.array([[1,3],[5,9],[3,11],[2,7],[10,12],[11,3],[4,6],[6,4],[7,2],[8,11]])
s1=set(tuple([x[i,0],x[i,1]]) for i in range(x.shape[0]))
s2=set(tuple([x[i,1],x[i,0]]) for i in range(x.shape[0]))
bond=s1&s2
temp_inter=[]
for i in bond:
temp_inter.append(i)
temp_inter=np.array(temp_inter)
temp_inter=temp_inter[temp_inter.min(axis=1).argsort()]
temp_inter=temp_inter[::2,:]
temp_inter=set(tuple([temp_inter[i,0],temp_inter[i,1]]) for i in range(temp_inter.shape[0]))
s1=s1-temp_inter
总结
值得注意的是,这种去重方法存在着局限性,隐含的条件是
如果将二维矩阵的第一列视为自变量,第二列视为因变量,则其中的映射应当是单射的,即虽然存在着x i = ( a , b ) ⇔ x j = ( b , a ) x_i=(a,b)\Leftrightarrow x_j=(b,a)xi=(a,b)⇔xj=(b,a)这种重复元素,但不应存在x i = ( a , b ) ⇔ x j = ( b , a ) , x i ′ = ( a , c ) ⇔ x j ′ = ( c , a ) x_i=(a,b)\Leftrightarrow x_j=(b,a),x'_i=(a,c)\Leftrightarrow x'_j=(c,a)xi=(a,b)⇔xj=(b,a),xi′=(a,c)⇔xj′=(c,a),否则使用使用上述代码就可能出现问题,举例如下:
重复元素:(2,4),(2,3),(3,2),(4,2)
排序后排布:(2,4),(2,3),(4,2),(3,2)
提取出重复元素:(2,3),(3,2)