নম্পি: দ্রুত মানের প্রথম সূচকটি সন্ধান করুন


105

আমি কোনও নম্পি অ্যারেতে সংখ্যার প্রথম উপস্থিতির সূচকটি কীভাবে খুঁজে পাব? গতি আমার কাছে গুরুত্বপূর্ণ। আমি নীচের উত্তরগুলিতে আগ্রহী না কারণ তারা পুরো অ্যারেটি স্ক্যান করে এবং যখন তারা প্রথম ঘটনাটি খুঁজে পায় তখন থামবে না:

itemindex = numpy.where(array==item)[0][0]
nonzero(array == item)[0][0]

দ্রষ্টব্য 1: এই প্রশ্নের উত্তরগুলির কোনওটিই প্রাসঙ্গিক বলে মনে হচ্ছে না অ্যারেতে কোনও কিছুর প্রথম সূচক ফেরত দেওয়ার জন্য কোনও নম্পি ফাংশন রয়েছে?

দ্রষ্টব্য 2: সি-সংকলিত পদ্ধতি ব্যবহার করে পাইথন লুপটিকে অগ্রাধিকার দেওয়া হয়।

উত্তর:


57

নম্পি ২.০.০ এর জন্য নির্ধারিত একটি বৈশিষ্ট্যের জন্য অনুরোধ রয়েছে: https://github.com/numpy/numpy/issues/2269


41
2018 এ দ্রুত এগিয়ে যাওয়া, ইস্যুটি এক ইঞ্চি চলে গেছে বলে মনে হয় না।
পি-জিএন

7
এবং নম্পি এখনও 1.xx
ইয়ান লিন

30

যদিও এটি আপনার জন্য অনেক দেরি হয়ে গেছে, তবে ভবিষ্যতের রেফারেন্সের জন্য: নাম্বা ( 1 ) ব্যবহার করা নিম্পি প্রয়োগ না করা অবধি সহজ উপায়। আপনি যদি অ্যানাকোন্ডা পাইথন বিতরণ ব্যবহার করেন তবে এটি ইতিমধ্যে ইনস্টল করা উচিত। কোডটি সংকলিত হবে তাই এটি দ্রুত হবে।

@jit(nopython=True)
def find_first(item, vec):
    """return the index of the first occurence of item in vec"""
    for i in xrange(len(vec)):
        if item == vec[i]:
            return i
    return -1

এবং তারপর:

>>> a = array([1,7,8,32])
>>> find_first(8,a)
2

4
পাইথন 3 এর xrangeজন্য পরিবর্তন করা দরকার range

পাইথন 3+ এ সামান্য কোড উন্নতি: enumerateযেমন ব্যবহার করুন for i, v in enumerate(vec):; if v == item: return i। ( পাইথনে এটি কোনও ভাল ধারণা নয় <= 2.7, যেখানে enumerateবেসিক
পুনরাবৃত্তির

23

আমি বিভিন্ন পদ্ধতির জন্য একটি মানদণ্ড তৈরি করেছি:

  • argwhere
  • nonzero প্রশ্ন হিসাবে
  • .tostring() @ রব রিলিংকের উত্তর হিসাবে
  • পাইথন লুপ
  • ফোর্টরান লুপ

পাইথন এবং ফোরট্রান কোড পাওয়া যায়। আমি তালিকায় রূপান্তরিত করার মতো অলাভজনকদের এড়িয়ে গেছি।

লগ স্কেল ফলাফল। এক্স-অক্ষটি হল সূঁচের অবস্থান (এটি আরও বেশি অ্যারে থেকে নিচে থাকলে এটি খুঁজে পেতে বেশি সময় নেয়); শেষ মানটি একটি সুই যা অ্যারেতে নেই। ওয়াই-অক্ষ এটি সন্ধানের সময়।

মানদণ্ডের ফলাফল

অ্যারেতে 1 মিলিয়ন উপাদান রয়েছে এবং পরীক্ষা 100 বার চালানো হয়েছিল। ফলাফলগুলি এখনও কিছুটা ওঠানামা করে তবে গুণগত প্রবণতা স্পষ্ট: পাইথন এবং এফ 2 পিপি প্রথম উপাদানটি ছেড়ে যায় যাতে তারা আলাদাভাবে স্কেল করে। পাই প্রথম 1% না থাকলে পাইথন খুব ধীর হয়ে যায়, যদিও f2pyএটি দ্রুত (তবে আপনার এটি সংকলন করা দরকার)।

সংক্ষিপ্তসার হিসাবে, f2py হ'ল দ্রুত সমাধান , বিশেষত যদি সুই মোটামুটি তাড়াতাড়ি প্রদর্শিত হয়।

এটি বিরক্তিকর এমনটি তৈরি করা হয়নি, তবে এটি সত্যই 2 মিনিটের কাজ। যোগ এই নামক একটি ফাইলে search.f90:

subroutine find_first(needle, haystack, haystack_length, index)
    implicit none
    integer, intent(in) :: needle
    integer, intent(in) :: haystack_length
    integer, intent(in), dimension(haystack_length) :: haystack
!f2py intent(inplace) haystack
    integer, intent(out) :: index
    integer :: k
    index = -1
    do k = 1, haystack_length
        if (haystack(k)==needle) then
            index = k - 1
            exit
        endif
    enddo
end

আপনি যদি অন্য কিছু খুঁজছেন তবে integerকেবল ধরণটি পরিবর্তন করুন। তারপরে ব্যবহার করে সংকলন করুন:

f2py -c -m search search.f90

এর পরে আপনি (পাইথন থেকে) করতে পারেন:

import search
print(search.find_first.__doc__)
a = search.find_first(your_int_needle, your_int_array)

2
f2py10 টির চেয়ে 1 আইটেমের জন্য ধীর কেন ?
এরিক 20

2
@ এরিক, আমার অনুমান হবে যে সেই স্কেলগুলিতে (10e-6), এটি কেবলমাত্র ডেটাতে শব্দ করে এবং প্রকৃত প্রতি-আইটেমের গতি এত দ্রুত যে এটি সামগ্রিক সময়গুলিতে এই এন <100 বা তার বেশি অবদান রাখে না meaning
ব্রেন্ডন

11

আপনি একটি বুলিয়ান অ্যারে পাইথন স্ট্রিংয়ে array.tostring()এবং তারপরে সন্ধান () পদ্ধতিটি ব্যবহার করে রূপান্তর করতে পারেন :

(array==item).tostring().find('\x01')

এটিতে ডেটা অনুলিপি করা জড়িত, যদিও পাইথনের স্ট্রিংগুলি অবিচ্ছেদ্য হওয়া দরকার। একটি সুবিধা হ'ল আপনি সন্ধান করতে পারেন যেমন উদীয়মান প্রান্তটি সন্ধান করে\x00\x01


এটি আকর্ষণীয়, তবে সবেমাত্র দ্রুত, যদি হয় তবে আপনার এখনও সমস্ত ডেটা নিয়ে কাজ করতে হবে (একটি উত্তরদণ্ডের জন্য আমার উত্তর দেখুন)।
চিহ্নিত করুন

10

সাজানো অ্যারের ক্ষেত্রে np.searchsortedকাজ করে।


2
অ্যারেতে যদি এই আইটেমটি না থাকে তবে অ্যারে দৈর্ঘ্যে ফিরে আসবে।
বরিস তেসমা

7

আমি মনে করি আপনি এমন একটি সমস্যায় পড়েছেন যেখানে অ্যারে সম্পর্কে একটি পৃথক পদ্ধতি এবং কিছু প্রাথমিক জ্ঞান সত্যই সহায়তা করবে। যে ধরণের জিনিসটিতে আপনার প্রথম উত্তর Y শতাংশের ডেটাতে আপনার উত্তর সন্ধানের এক্স সম্ভাবনা রয়েছে। ভাগ্যবান হওয়ার আশা নিয়ে সমস্যাটি বিভক্ত করে তারপরে নেস্টেড তালিকা বোঝার বা কোনও কিছুর সাহায্যে অজগরটিতে এটি করা।

এই ব্রুট ফোর্সটি করতে সি ফাংশন রচনা লেখার জন্য সিটি টাইপগুলি ব্যবহার করা খুব বেশি শক্ত নয়।

আমি একসাথে সি কোড হ্যাক করেছি (index.c):

long index(long val, long *data, long length){
    long ans, i;
    for(i=0;i<length;i++){
        if (data[i] == val)
            return(i);
    }
    return(-999);
}

অজগর:

# to compile (mac)
# gcc -shared index.c -o index.dylib
import ctypes
lib = ctypes.CDLL('index.dylib')
lib.index.restype = ctypes.c_long
lib.index.argtypes = (ctypes.c_long, ctypes.POINTER(ctypes.c_long), ctypes.c_long)

import numpy as np
np.random.seed(8675309)
a = np.random.random_integers(0, 100, 10000)
print lib.index(57, a.ctypes.data_as(ctypes.POINTER(ctypes.c_long)), len(a))

এবং আমি 92 পেয়েছি।

অজগরটিকে একটি সঠিক ফাংশনে আবদ্ধ করুন এবং আপনি সেখানে যান।

সি সংস্করণটি এই বীজের জন্য অনেকগুলি (x 20x) দ্রুত (সতর্কতা আমি সময়সীমার সাথে ভাল নই)

import timeit
t = timeit.Timer('np.where(a==57)[0][0]', 'import numpy as np; np.random.seed(1); a = np.random.random_integers(0, 1000000, 10000000)')
t.timeit(100)/100
# 0.09761879920959472
t2 = timeit.Timer('lib.index(57, a.ctypes.data_as(ctypes.POINTER(ctypes.c_long)), len(a))', 'import numpy as np; np.random.seed(1); a = np.random.random_integers(0, 1000000, 10000000); import ctypes; lib = ctypes.CDLL("index.dylib"); lib.index.restype = ctypes.c_long; lib.index.argtypes = (ctypes.c_long, ctypes.POINTER(ctypes.c_long), ctypes.c_long) ')
t2.timeit(100)/100
# 0.005288000106811523

1
অ্যারেটি যদি দ্বিগুণ হয় (মনে রাখবেন পাইথন ফ্লোটগুলি ডিফল্টরূপে সি ডাবল হয়) তবে আপনাকে কিছুটা শক্তভাবে ভাবতে হবে কারণ == আসলেই নিরাপদ নয় বা আপনি ভাসমান পয়েন্টের মানগুলির জন্য কী চান। এছাড়াও ভুলে যাবেন না যে সিটি টাইপগুলি ব্যবহার করে আপনার নাম্পার অ্যারে টাইপ করার সময় এটি সত্যিই ভাল ধারণা।
ব্রায়ান লারসেন

ধন্যবাদ @ ব্রায়ান লারসেন। আমি চেষ্টা করে দেখতে পারি আমি মনে করি এটি পরবর্তী অলস সংশোধনীর জন্য একটি তুচ্ছ বৈশিষ্ট্য অনুরোধ।
সাইবার্গ

5

টাল numbaপ্রথম সূচকটি খুঁজে পেতে ইতিমধ্যে একটি ফাংশন উপস্থাপন করেছে তবে এটি কেবল 1 ডি অ্যারেগুলির জন্যই কাজ করে। সঙ্গে np.ndenumerateআপনার কাছে একটি arbitarly মাত্রিক অ্যারের মধ্যে প্রথম সূচক পেতে পারবেন:

from numba import njit
import numpy as np

@njit
def index(array, item):
    for idx, val in np.ndenumerate(array):
        if val == item:
            return idx
    return None

নমুনা কেস:

>>> arr = np.arange(9).reshape(3,3)
>>> index(arr, 3)
(1, 0)

সময়গুলি দেখায় যে এটি তালের সমাধানের সাথে পারফরম্যান্সেও অনুরূপ :

arr = np.arange(100000)
%timeit index(arr, 5)           # 1000000 loops, best of 3: 1.88 µs per loop
%timeit find_first(5, arr)      # 1000000 loops, best of 3: 1.7 µs per loop

%timeit index(arr, 99999)       # 10000 loops, best of 3: 118 µs per loop
%timeit find_first(99999, arr)  # 10000 loops, best of 3: 96 µs per loop

1
আপনি যদি প্রথমে প্রদত্ত অক্ষের সাথে অনুসন্ধান করতে আগ্রহী হন: arrayএটিতে খাওয়ানোর আগে ট্রান্সপোজ করুন np.ndenumerate, যাতে আপনার আগ্রহের অক্ষটি প্রথমে আসে।
CheshireCat

ধন্যবাদ, এটি প্রকৃতপক্ষে দ্রুততর মাত্রার অর্ডার: ~ 171ms ( np.argwhere) থেকে 717ns (আপনার সমাধান), উভয় আকারের অ্যারের জন্য (3000000, 12))।
আর্থার কলম্বিনি গুসমো

3

যদি আপনার তালিকাটি সাজানো হয় তবে আপনি 'বাইসেক্ট' প্যাকেজটির সাহায্যে সূচীর খুব দ্রুত অনুসন্ধান অর্জন করতে পারেন । এটি ও (লগ (এন)) এর পরিবর্তে ও (এন)

bisect.bisect(a, x)

প্রথম অ্যারের উপাদানগুলির (দীর্ঘ পর্যাপ্ত তালিকাগুলির জন্য) যে কোনও সি রুটিনের তুলনায় ক্রমান্বয়ে বাছাই করা মামলার চেয়ে দ্রুত অ্যারেতে এক্স খুঁজে পাওয়া যায় definitely

মাঝে মাঝে জেনে রাখা ভাল।


>>> cond = "import numpy as np;a = np.arange(40)" timeit("np.searchsorted(a, 39)", cond)3.47867107391 সেকেন্ডের জন্য কাজ করে। timeit("bisect.bisect(a, 39)", cond2)7.0661458969116 সেকেন্ডের জন্য কাজ করে। দেখে মনে numpy.searchsortedহচ্ছে বাছাই করা অ্যারেগুলির জন্য ভাল (অন্তত ints এর জন্য)।
বরিস তেসমা

2

আমি যতদূর জানি বুলিয়ান অ্যারেগুলিতে কেবলমাত্র এনপি.আনি এবং এনপি.ল সমস্ত সংক্ষিপ্তসার্কিটেড।

আপনার ক্ষেত্রে, বুলিয়ান শর্ত তৈরি করতে এবং দ্বিতীয় বার সূচকগুলি সন্ধানের জন্য নম্পিকে পুরো অ্যারে দুইবার যেতে হবে।

এই ক্ষেত্রে আমার পরামর্শটি সিথন ব্যবহার করা হবে। আমি মনে করি এই ক্ষেত্রে উদাহরণটি সামঞ্জস্য করা সহজ হওয়া উচিত, বিশেষত যদি বিভিন্ন ধরণের এবং আকারের জন্য আপনার খুব বেশি নমনীয়তার প্রয়োজন না হয়।


2

আমার চাকরির জন্য আমার এটি দরকার ছিল তাই আমি নিজেকে পাইথন এবং নম্পির সি ইন্টারফেস শিখিয়েছি এবং আমার নিজের লেখা। http://pastebin.com/GtcXuLyd এটি শুধুমাত্র 1-D অ্যারেগুলির জন্য, তবে বেশিরভাগ ডেটা ধরণের (ইন্ট, ফ্লোট বা স্ট্রিং) কাজ করে এবং পরীক্ষায় দেখা গেছে যে এটি শুদ্ধ পাইথন-তে প্রত্যাশিত পদ্ধতির চেয়ে প্রায় 20 গুণ বেশি দ্রুত numpy।


2

খণ্ডগুলিতে অ্যারের প্রক্রিয়াজাতকরণের মাধ্যমে এই সমস্যাটি খাঁটি নিম্পিতে কার্যকরভাবে সমাধান করা যেতে পারে:

def find_first(x):
    idx, step = 0, 32
    while idx < x.size:
        nz, = x[idx: idx + step].nonzero()
        if len(nz): # found non-zero, return it
            return nz[0] + idx
        # move to the next chunk, increase step
        idx += step
        step = min(9600, step + step // 2)
    return -1

অ্যারে আকার আকারে প্রক্রিয়া করা হয় stepstepপদক্ষেপটি যত দীর্ঘ হবে তত দ্রুত শূন্য-অ্যারে (সবচেয়ে খারাপ ক্ষেত্রে) প্রক্রিয়াকরণ করা হচ্ছে। এটি যত কম ছোট, শুরুতে শূন্যহীন অ্যারের দ্রুত প্রসেসিং। কৌশলটি হল একটি ছোট দিয়ে শুরু করা stepএবং এটি তাত্পর্যপূর্ণভাবে বাড়ানো। অধিকন্তু, সীমিত সুবিধার কারণে এটি কিছু প্রান্তিকের উপরে বাড়িয়ে দেওয়ার দরকার নেই।

আমি সমাধানটিকে খাঁটি ndarary.nonzero এবং numba সমাধানের সাথে 10 মিলিয়ন অ্যারে ভাসমানের সাথে তুলনা করেছি।

import numpy as np
from numba import jit
from timeit import timeit

def find_first(x):
    idx, step = 0, 32
    while idx < x.size:
        nz, = x[idx: idx + step].nonzero()
        if len(nz):
            return nz[0] + idx
        idx += step
        step = min(9600, step + step // 2)
    return -1

@jit(nopython=True)
def find_first_numba(vec):
    """return the index of the first occurence of item in vec"""
    for i in range(len(vec)):
        if vec[i]:
            return i
    return -1


SIZE = 10_000_000
# First only
x = np.empty(SIZE)

find_first_numba(x[:10])

print('---- FIRST ----')
x[:] = 0
x[0] = 1
print('ndarray.nonzero', timeit(lambda: x.nonzero()[0][0], number=100)*10, 'ms')
print('find_first', timeit(lambda: find_first(x), number=1000), 'ms')
print('find_first_numba', timeit(lambda: find_first_numba(x), number=1000), 'ms')

print('---- LAST ----')
x[:] = 0
x[-1] = 1
print('ndarray.nonzero', timeit(lambda: x.nonzero()[0][0], number=100)*10, 'ms')
print('find_first', timeit(lambda: find_first(x), number=100)*10, 'ms')
print('find_first_numba', timeit(lambda: find_first_numba(x), number=100)*10, 'ms')

print('---- NONE ----')
x[:] = 0
print('ndarray.nonzero', timeit(lambda: x.nonzero()[0], number=100)*10, 'ms')
print('find_first', timeit(lambda: find_first(x), number=100)*10, 'ms')
print('find_first_numba', timeit(lambda: find_first_numba(x), number=100)*10, 'ms')

print('---- ALL ----')
x[:] = 1
print('ndarray.nonzero', timeit(lambda: x.nonzero()[0][0], number=100)*10, 'ms')
print('find_first', timeit(lambda: find_first(x), number=100)*10, 'ms')
print('find_first_numba', timeit(lambda: find_first_numba(x), number=100)*10, 'ms')

এবং আমার মেশিনে ফলাফল:

---- FIRST ----
ndarray.nonzero 54.733994480002366 ms
find_first 0.0013148509997336078 ms
find_first_numba 0.0002839310000126716 ms
---- LAST ----
ndarray.nonzero 54.56336712999928 ms
find_first 25.38929685000312 ms
find_first_numba 8.022820680002951 ms
---- NONE ----
ndarray.nonzero 24.13432420999925 ms
find_first 25.345200140000088 ms
find_first_numba 8.154927100003988 ms
---- ALL ----
ndarray.nonzero 55.753537260002304 ms
find_first 0.0014760300018679118 ms
find_first_numba 0.0004358099977253005 ms

খাঁটি ndarray.nonzeroনিশ্চিত লুজার। সেরা মামলার জন্য নাম্বার দ্রবণটি 5 গুণ দ্রুততর হয়। এটি সবচেয়ে খারাপ ক্ষেত্রে সার্কা 3 গুণ দ্রুত।


2

আপনি যদি প্রথম অ-শূন্য উপাদান খুঁজছেন তবে আপনি নিম্নলিখিত হ্যাক ব্যবহার করতে পারেন:

idx = x.view(bool).argmax() // x.itemsize
idx = idx if x[idx] else -1

এটি একটি খুব দ্রুত "নম্পি-খাঁটি" সমাধান তবে এটি নীচে আলোচিত কিছু ক্ষেত্রে ব্যর্থ।

সমাধানটি সংখ্যাটি যে ধরণের শূন্যের সমস্ত উপস্থাপনা 0বাইট নিয়ে গঠিত তা থেকে সুবিধা গ্রহণ করে । এটি নম্পির ক্ষেত্রেও প্রযোজ্য bool। নম্পির সাম্প্রতিক সংস্করণগুলিতে, প্রকারটি argmax()প্রক্রিয়াকরণ করার সময় ফাংশন শর্ট সার্কিট যুক্তি ব্যবহার করে bool। এর আকার bool1 বাইট।

সুতরাং একটি প্রয়োজন:

  • হিসাবে অ্যারের একটি ভিউ তৈরি করুন bool। কোনও অনুলিপি তৈরি হয় না
  • ব্যবহার argmax()প্রথম নন-জিরো শর্ট-কাটে লজিক ব্যবহার বাইট এটি
  • //বাইটস ( x.itemsize) দ্বারা প্রকাশিত একক উপাদানের আকার দ্বারা অফসেটের পূর্ণসংখ্যা বিভাগ (অপারেটর ) দ্বারা প্রথম অ-শূন্য উপাদানটির সূচকে এই বাইটের অফসেটকে পুনরায় গণনা করুন
  • x[idx]কোন শূন্য-উপস্থিত না থাকলে কেসটি সনাক্ত করতে আসলে শূন্য নয় কিনা তা পরীক্ষা করুন

আমি নাম্বার সমাধানের বিরুদ্ধে কিছু মানদণ্ড তৈরি করেছি এবং এটি তৈরি করেছি np.nonzero

import numpy as np
from numba import jit
from timeit import timeit

def find_first(x):
    idx = x.view(bool).argmax() // x.itemsize
    return idx if x[idx] else -1

@jit(nopython=True)
def find_first_numba(vec):
    """return the index of the first occurence of item in vec"""
    for i in range(len(vec)):
        if vec[i]:
            return i
    return -1


SIZE = 10_000_000
# First only
x = np.empty(SIZE)

find_first_numba(x[:10])

print('---- FIRST ----')
x[:] = 0
x[0] = 1
print('ndarray.nonzero', timeit(lambda: x.nonzero()[0][0], number=100)*10, 'ms')
print('find_first', timeit(lambda: find_first(x), number=1000), 'ms')
print('find_first_numba', timeit(lambda: find_first_numba(x), number=1000), 'ms')

print('---- LAST ----')
x[:] = 0
x[-1] = 1
print('ndarray.nonzero', timeit(lambda: x.nonzero()[0][0], number=100)*10, 'ms')
print('find_first', timeit(lambda: find_first(x), number=100)*10, 'ms')
print('find_first_numba', timeit(lambda: find_first_numba(x), number=100)*10, 'ms')

print('---- NONE ----')
x[:] = 0
print('ndarray.nonzero', timeit(lambda: x.nonzero()[0], number=100)*10, 'ms')
print('find_first', timeit(lambda: find_first(x), number=100)*10, 'ms')
print('find_first_numba', timeit(lambda: find_first_numba(x), number=100)*10, 'ms')

print('---- ALL ----')
x[:] = 1
print('ndarray.nonzero', timeit(lambda: x.nonzero()[0][0], number=100)*10, 'ms')
print('find_first', timeit(lambda: find_first(x), number=100)*10, 'ms')
print('find_first_numba', timeit(lambda: find_first_numba(x), number=100)*10, 'ms')

আমার মেশিনে ফলাফল:

---- FIRST ----
ndarray.nonzero 57.63976670001284 ms
find_first 0.0010841979965334758 ms
find_first_numba 0.0002308919938514009 ms
---- LAST ----
ndarray.nonzero 58.96685277999495 ms
find_first 5.923203580023255 ms
find_first_numba 8.762269750004634 ms
---- NONE ----
ndarray.nonzero 25.13398071998381 ms
find_first 5.924289370013867 ms
find_first_numba 8.810063839919167 ms
---- ALL ----
ndarray.nonzero 55.181210660084616 ms
find_first 0.001246920000994578 ms
find_first_numba 0.00028766007744707167 ms

সমাধানটি নাম্বার চেয়ে 33% দ্রুত এবং এটি "নিম্পি-খাঁটি"।

অসুবিধাগুলি:

  • যেমন নামী গ্রহণযোগ্য ধরণের জন্য কাজ করে না object
  • নেতিবাচক শূন্যের জন্য ব্যর্থ হয় যা মাঝে মধ্যে প্রদর্শিত হয় floatবা doubleগণনা হয়

এটি চেষ্টা করা সেরা খাঁটি নকল সমাধান ive উত্তর গ্রহণ করা উচিত। @tstisisl ive একটি অ্যারেতে প্রথম শূন্য উপাদান সন্ধান করার জন্য একইভাবে দ্রুত সমাধান পাওয়ার চেষ্টা করছে তবে এটি সর্বদা বোল রূপান্তরিত হয়ে আরগমিনে চালিত হওয়ার চেয়ে ধীরে ধীরে শেষ হয় ()। কোন ধারনা?
946

1
@ Ta946। শূন্য এন্ট্রি সন্ধানের সময় কৌশলটি ব্যবহার করা যাবে না। যেমন নন-শূন্য ডাবল এতে একটি শূন্য বাইট থাকতে পারে। আপনি যদি ন্যালি-খাঁটি সমাধানের সন্ধান করেন তবে আমার অন্য উত্তরটি সংশোধন করার চেষ্টা করুন । স্ট্যাকওভারফ্লো . com/a/58294774/4989451 দেখুন । xকল করার আগে কেবল এক টুকরোটিকে উপেক্ষা করুন nonzero()। এটি নাম্বার চেয়ে ধীর হতে পারে তবে এটি ** সম্পূর্ণ অ্যারের মাধ্যমে ** অনুসন্ধান করবে না যখন প্রথম শূন্য প্রবেশের সন্ধান করবে সুতরাং এটি আপনার প্রয়োজনের জন্য দ্রুত পর্যাপ্ত হতে পারে।
তস্তানিসল

1

দীর্ঘদিনের মতলব ব্যবহারকারী হিসাবে আমি একজন বেশ কিছুদিন ধরে এই সমস্যার কার্যকর সমাধান অনুসন্ধান করছি। অবশেষে, এই থ্রেডের একটি প্রস্তাব নিয়ে আলোচনার দ্বারা প্রেরণা নিয়ে আমি এমন একটি সমাধান নিয়ে আসতে চেষ্টা করেছি যা এখানে প্রস্তাবিত অনুরূপ একটি এপিআই বাস্তবায়ন করছে, মুহুর্তের জন্য কেবল 1D অ্যারে সমর্থন করে।

আপনি এটি এটি ব্যবহার করবে

import numpy as np
import utils_find_1st as utf1st
array = np.arange(100000)
item = 1000
ind = utf1st.find_1st(array, item, utf1st.cmp_larger_eq)

শর্তযুক্ত অপারেটরগুলি হলেন: সিএমপি_ইকোয়াল, সিএমপি_নোট_একুয়াল, সিএমপি_এলগ্রার, সিএমপি_সামেলার, সিএমপি_লার্জার_ইক, সিএমপি_সামেলার_ইক দক্ষতার জন্য এক্সটেনশন সিতে লেখা হয়।

আপনি উত্স, বেঞ্চমার্ক এবং অন্যান্য বিশদ এখানে পাবেন:

https://pypi.python.org/pypi?name=py_find_1st&:action=display

আমাদের দলে ব্যবহারের জন্য (লিনাক্স এবং ম্যাকোসে অ্যানাকোন্ডা) আমি একটি অ্যানাকোন্ডা ইনস্টলার তৈরি করেছি যা ইনস্টলেশনটিকে সহজতর করে, আপনি এখানে বর্ণিত হিসাবে এটি ব্যবহার করতে পারেন

https://anaconda.org/roebel/py_find_1st


"দীর্ঘদিনের মতলব ব্যবহারকারী হিসাবে" - এর জন্য মতলব কী বানান?
এরিক

সন্ধান করুন (এক্স, এন) প্রথম এন সূচকগুলি খুঁজে পায় যেখানে এক্স শূন্য নয়। mathworks.com/help/matlab/ref/find.html
একটি রোবেল

0

কেবলমাত্র একটি নোট যে আপনি যদি অনুসন্ধানগুলির ক্রম করে চলেছেন তবে স্ট্রিংয়ে রূপান্তর করার মতো চতুর কিছু করার মাধ্যমে পারফরম্যান্স লাভটি অনুসন্ধানের মাত্রাটি যথেষ্ট বড় না হলে বাইরের লুপে হারিয়ে যেতে পারে। উপরে যে প্রস্তাবিত স্ট্রিং রূপান্তর কৌশল ব্যবহার করে ফাইন্ড 1 পুনরুক্তি করার পারফরম্যান্স এবং অভ্যন্তরীণ অক্ষটি বরাবর আর্গম্যাক্স ব্যবহার করে ফাইন্ড 2 ব্যবহার করে (প্লাগ কোনও অ-ম্যাচ -1 হিসাবে প্রত্যাবর্তন নিশ্চিত করার জন্য একটি সমন্বয়)

import numpy,time
def find1(arr,value):
    return (arr==value).tostring().find('\x01')

def find2(arr,value): #find value over inner most axis, and return array of indices to the match
    b = arr==value
    return b.argmax(axis=-1) - ~(b.any())


for size in [(1,100000000),(10000,10000),(1000000,100),(10000000,10)]:
    print(size)
    values = numpy.random.choice([0,0,0,0,0,0,0,1],size=size)
    v = values>0

    t=time.time()
    numpy.apply_along_axis(find1,-1,v,1)
    print('find1',time.time()-t)

    t=time.time()
    find2(v,1)
    print('find2',time.time()-t)

আউটপুট

(1, 100000000)
('find1', 0.25300002098083496)
('find2', 0.2780001163482666)
(10000, 10000)
('find1', 0.46200013160705566)
('find2', 0.27300000190734863)
(1000000, 100)
('find1', 20.98099994659424)
('find2', 0.3040001392364502)
(10000000, 10)
('find1', 206.7590000629425)
('find2', 0.4830000400543213)

এটি বলেছিল যে সি তে লিখিত একটি অনুসন্ধান এই পদ্ধতিরগুলির চেয়ে কমপক্ষে কিছুটা দ্রুত হবে


0

এই সম্পর্কে

import numpy as np
np.amin(np.where(array==item))

2
যদিও এই কোডটি প্রশ্নের উত্তর দিতে পারে, কেন এবং / অথবা এটি কীভাবে প্রশ্নের উত্তর দেয় সে সম্পর্কিত অতিরিক্ত প্রসঙ্গ সরবরাহ করে এর দীর্ঘমেয়াদী মানকে উল্লেখযোগ্যভাবে উন্নতি করবে। কিছু ব্যাখ্যা যুক্ত করতে দয়া করে আপনার উত্তরটি সম্পাদনা করুন।
টবি স্পিড

1
আমি নিশ্চিত যে where(array==item)[0][0]এটি প্রশ্নের থেকেও ধীর গতিতে ...
মার্ক

-1

আপনি আপনার অ্যারেটিকে একটিতে রূপান্তর করতে পারেন listএবং এর index()পদ্ধতিটি ব্যবহার করতে পারেন :

i = list(array).index(item)

আমি যতদূর সচেতন, এটি একটি সি সংকলিত পদ্ধতি।


3
এটি সম্ভবত এনপি.ওহেন থেকে প্রথম ফলাফল গ্রহণের চেয়ে অনেকগুণ ধীর হতে পারে
cwa

1
খুব সত্য .. আমি timeit()10000 পূর্ণসংখ্যার অ্যারে ব্যবহার করেছিলাম - একটি তালিকায় রূপান্তর করা প্রায় 100 গুণ ধীর ছিল! আমি ভুলে গিয়েছিলাম যে একটি নমপি অ্যারের জন্য অন্তর্নিহিত ডেটা কাঠামো একটি তালিকা থেকে খুব আলাদা ..
ড্রেভিকো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.