python是否有一个谓词来测试矩阵的行是否排序?

时间:2014-09-11 20:31:03

标签: python numpy

我想检查一系列 N 整数的numpy向量是lexicographically ordered。序列中的所有向量都具有1×2的形状。( N 的值很大,所以如果它已经排序,我想避免对这个序列进行排序。)

Python或numpy是否已提供谓词来执行此类测试?

(自行推出并不难,但我更喜欢使用内置工具。)

3 个答案:

答案 0 :(得分:1)

您可以使用np.diff和np.any:

A = np.array([[1,2,3], [2,3,1], [3, 4, 5]])
diff =  np.diff(A, axis=0)
print np.all(diff>=0, axis=0)

答案 1 :(得分:1)

要拥有issorted谓词,您需要一个明确定义的排序,或者至少是一种比较项目的明确方法。

关注我的数据性质问题。听起来好像你有这样的东西:

In [130]: x=[[1,3],[3,4],[1,2],[3,1],[0,2],[6,5]]
In [131]: x1=[np.array(i).reshape(1,2) for i in x]
In [132]: x1
Out[132]: 
[array([[1, 3]]),
 array([[3, 4]]),
 array([[1, 2]]),
 array([[3, 1]]),
 array([[0, 2]]),
 array([[6, 5]])]

Python排序是词法 - 也就是说,是子列表中的第一个元素,然后是第二个元素。

In [137]: sorted(x)
Out[137]: [[0, 2], [1, 2], [1, 3], [3, 1], [3, 4], [6, 5]]

numpy排序不保留对 - 取决于按列排序的axis规范,或行(或平面)。但是np.sort doc确实说复数是按字母顺序排序的:

In [157]: xj = np.dot(x,[1,1j])
In [158]: xj
Out[158]: array([ 1.+3.j,  3.+4.j,  1.+2.j,  3.+1.j,  0.+2.j,  6.+5.j])
In [159]: np.sort(xj)
Out[159]: array([ 0.+2.j,  1.+2.j,  1.+3.j,  3.+1.j,  3.+4.j,  6.+5.j])

这匹配Python列表排序。


如果我对您的数据类型的猜测是正确的,那么基于比较的测试将使用如下内容:

In [167]: [i.__lt__(j) for i,j in zip(x[:-1],x[1:])]
Out[167]: [True, False, True, False, True]
In [168]: xs=sorted(x)
In [169]: [i.__lt__(j) for i,j in zip(xs[:-1],xs[1:])]
Out[169]: [True, True, True, True, True]

这也适用于复杂数组:

In [173]: xjs=np.sort(xj)
In [174]: [i.__lt__(j) for i,j in zip(xjs[:-1],xjs[1:])]
Out[174]: [True, True, True, True, True]

对于大型列表,我尝试使用其中一个itertools进行短路迭代。

但是当应用于(普通)数组时,显然它是否已排序的问题需要进一步说明。

In [172]: [i.__lt__(j) for i,j in zip(x1[:-1],x1[1:])]
Out[172]: 
[array([[ True,  True]], dtype=bool),
 array([[False, False]], dtype=bool),
 array([[ True, False]], dtype=bool),
 array([[False,  True]], dtype=bool),
 array([[ True,  True]], dtype=bool)]

顺便说一下,(2,1)数组的列表看起来像这样:

[np.array(i).reshape(1,2) for i in x]

[array([[1, 3]]),
 array([[3, 4]]),
 array([[1, 2]]),
 array([[3, 1]]),
 array([[0, 2]]),
 array([[6, 5]])]

如果变成数组则会有(6,1,2)形状。或者你想要一个(6,2)数组?

In [179]: np.array(x)
Out[179]: 
array([[1, 3],
       [3, 4],
       [1, 2],
       [3, 1],
       [0, 2],
       [6, 5]])

答案 2 :(得分:1)

numpy有 lexsort ,但这是一种排序,而不是对数据是否排序的测试。尽管如此,在排序数据上运行它的速度大约是未排序数据的两倍。

import numpy as np
import timeit

def data(N):
    return np.random.randint(0,10,(N,2))

def get_sorted(x):
    return x[np.lexsort(x.T)]

x = data(5)
y  = get_sorted(x)

print x  # to verify lex sorting
print
print y
print

x = data(1000)
y  = get_sorted(x)

# to test the time for sorted vs unsorted data
print timeit.timeit("np.lexsort(x.T)", "from __main__ import np, x", number=1000)
print timeit.timeit("np.lexsort(y.T)", "from __main__ import np, y", number=1000)

以下是结果:

[[6 7]   # unsorted
 [4 3]
 [6 7]
 [9 2]
 [7 3]]

[[9 2]   # sorted by the second column first
 [4 3]
 [7 3]
 [6 7]
 [6 7]]

0.0788  # time to lex sort 1000x2 unsorted data values
0.0381  # time to lex sort 1000x2 pre-sorted data values

另请注意,python与numpy的速度将取决于列表,因为python有时会短路其测试。因此,如果您认为您的列表通常是未排序的,那么纯python解决方案可以在前几个值中解决这个问题,这可能要快得多;而numpy解决方案通常适用于整个阵列。