戰略
- 由於
x
不一定排序,我們將對其進行排序,並通過argsort
跟蹤排序排列,所以我們可以扭轉排列。
- 我們將使用
np.searchsorted
對x
與x - d
找到x
的值開始超過x - d
的起始位置。
- 再做一次在另一邊,除了我們不得不使用
np.searchsorted
參數side='right'
和使用x + d
- 採取正確的區別和左searchsorts計算元素是每個元素的+/- d內的數
- 使用argsort扭轉排序排列
限定方法中問題呈現爲pir1
def pir1(a, d):
return (np.abs(a[:, None] - a) <= d).sum(-1)
我們將定義一個新的功能pir2
def pir2(a, d):
s = x.argsort()
a_ = a[s]
return (
a_.searchsorted(a_ + d, 'right')
- a_.searchsorted(a_ - d)
)[s.argsort()]
演示
pir1(x, d)
[5 2 1 2 5 1 5 5 5 1]
pir1(x, d)
[5 2 1 2 5 1 5 5 5 1]
時機
pir2
是明顯的贏家!
代碼
功能
def pir1(a, d):
return (np.abs(a[:, None] - a) <= d).sum(-1)
def pir2(a, d):
s = x.argsort()
a_ = a[s]
return (
a_.searchsorted(a_ + d, 'right')
- a_.searchsorted(a_ - d)
)[s.argsort()]
#######################
# From Divakar's post #
#######################
def pir3(a,d): # Short & less efficient
sidx = a.argsort()
p1 = a.searchsorted(a+d,'right',sorter=sidx)
p2 = a.searchsorted(a-d,sorter=sidx)
return p1 - p2
def pir4(a, d): # Long & more efficient
s = a.argsort()
y = np.empty(s.size,dtype=np.int64)
y[s] = np.arange(s.size)
a_ = a[s]
return (
a_.searchsorted(a_ + d, 'right')
- a_.searchsorted(a_ - d)
)[y]
測試
from timeit import timeit
results = pd.DataFrame(
index=np.arange(1, 50),
columns=['pir%s' %i for i in range(1, 5)])
for i in results.index:
np.random.seed([3,1415])
x = np.random.randint(1000000, size=i)
for j in results.columns:
setup = 'from __main__ import x, {}'.format(j)
results.loc[i, j] = timeit('{}(x, 10)'.format(j), setup=setup, number=10000)
results.plot()
延伸到了更大的陣列
擺脫pir1
from timeit import timeit
results = pd.DataFrame(
index=np.arange(1, 11) * 1000,
columns=['pir%s' %i for i in range(2, 5)])
for i in results.index:
np.random.seed([3,1415])
x = np.random.randint(1000000, size=i)
for j in results.columns:
setup = 'from __main__ import x, {}'.format(j)
results.loc[i, j] = timeit('{}(x, 10)'.format(j), setup=setup, number=100)
results.insert(0, 'pir1', 0)
results.plot()
非常感謝。我已經更新了測試結果以包含這些變體並擴展了數組的大小。 – piRSquared
@piRSquared這些是有道理的。對於較小的數組,'pir4'中用於創建獲取's.argsort()'的範圍數組的開銷使其不如簡單排序更有價值。對於您爲了計算這個計數問題而使用'searchsorted'好心想! – Divakar