নমপি অ্যারেতে মোড সন্ধান করার সবচেয়ে কার্যকরী উপায়


89

আমার কাছে 2D অ্যারে রয়েছে পূর্ণসংখ্যাগুলি (ধনাত্মক বা orণাত্মক উভয়)। প্রতিটি সারি নির্দিষ্ট স্থানিক সাইটের জন্য সময়ের সাথে সাথে মানগুলিকে উপস্থাপন করে, যেখানে প্রতিটি কলাম একটি নির্দিষ্ট সময়ের জন্য বিভিন্ন স্থানিক সাইটের মানগুলিকে উপস্থাপন করে।

সুতরাং অ্যারের মতো হলে:

1 3 4 2 2 7
5 2 2 1 4 1
3 3 2 2 1 1

ফলাফল হওয়া উচিত

1 3 2 2 2 1

নোট করুন যে মোডের জন্য যখন একাধিক মান থাকে, তখন যে কোনও একটি (এলোমেলোভাবে নির্বাচিত) মোড হিসাবে সেট করা যেতে পারে।

আমি কলামগুলি একবারে মোড সন্ধানের মাধ্যমে পুনরাবৃত্তি করতে পারি তবে আমি আশা করছিলাম যে এটি করার জন্য নম্পির কিছুটা অন্তর্নির্মিত ফাংশন থাকতে পারে। বা লুপিং ছাড়াই দক্ষতার সাথে এটি খুঁজে পাওয়ার কোনও কৌশল আছে।



4
@ টম 10: আপনার মানে স্কিপি.স্ট্যাটস.মোড () , তাই না? অন্যটি একটি মুখোশযুক্ত অ্যারে আউটপুট বলে মনে হচ্ছে।
fgb

@fgb: ঠিক আছে, সংশোধনের জন্য ধন্যবাদ (এবং আপনার উত্তরের জন্য +1)।
tom10

উত্তর:


121

চেক scipy.stats.mode() (@ টম 10 এর মন্তব্যে অনুপ্রাণিত):

import numpy as np
from scipy import stats

a = np.array([[1, 3, 4, 2, 2, 7],
              [5, 2, 2, 1, 4, 1],
              [3, 3, 2, 2, 1, 1]])

m = stats.mode(a)
print(m)

আউটপুট:

ModeResult(mode=array([[1, 3, 2, 2, 1, 1]]), count=array([[1, 2, 2, 2, 1, 2]]))

আপনি দেখতে পাচ্ছেন, এটি মোডের পাশাপাশি গণনা উভয়ই প্রদান করে। আপনি সরাসরি মাধ্যমে মোডগুলি নির্বাচন করতে পারেনm[0] :

print(m[0])

আউটপুট:

[[1 3 2 2 1 1]]

4
সুতরাং খালি নিজেই এই জাতীয় কোনও কার্যকারিতা সমর্থন করে না?
নিক

4
স্পষ্টতই নয়, তবে স্কিপির বাস্তবায়ন কেবল অদ্ভুতের উপর নির্ভর করে , সুতরাং আপনি কেবল কোডটি নিজের ফাংশনে অনুলিপি করতে পারেন।
fgb

12
ভবিষ্যতে এই বিষয়টির দিকে নজর দেওয়া লোকদের জন্য কেবল একটি নোট: আপনার import scipy.statsস্পষ্টভাবে বলা দরকার , আপনি যখন কেবল কোনও কাজ করেন তখন এটি অন্তর্ভুক্ত হয় না import scipy
ffledgling

4
আপনি দয়া করে ব্যাখ্যা করতে পারবেন এটি ঠিক কীভাবে মোডের মানগুলি এবং গণনা প্রদর্শন করছে? প্রদত্ত ইনপুট দিয়ে আমি আউটপুটটি সম্পর্কিত করতে পারি না।
রাহুল

4
@ রাহুল: আপনাকে ডিফল্ট দ্বিতীয় যুক্তির বিষয়টি বিবেচনা করতে হবে axis=0। উপরের কোডটি ইনপুটটির প্রতি কলামে মোডের প্রতিবেদন করছে। গণনাটি আমাদের জানাচ্ছে যে এটি প্রতিটি কলামে প্রতিবেদন করা মোডটি কতবার দেখেছিল। আপনি যদি সামগ্রিক মোডটি চান, আপনার নির্দিষ্ট করা দরকার axis=None। আরও তথ্যের জন্য, দয়া করে ডকস.স্কিপি.অর্গ
ডক /

22

হালনাগাদ

scipy.stats.modeফাংশন উল্লেখযোগ্যভাবে পোস্টটি যেহেতু অপ্টিমাইজ করা হয়েছে, এবং প্রস্তাবিত পদ্ধতি হবে

পুরানো উত্তর

এটি একটি জটিল সমস্যা, যেহেতু অক্ষ সহ মোড গণনা করার মতো খুব বেশি কিছু নেই। সমাধান 1-ডি অ্যারে, যেখানে জন্য সোজা এগিয়ে numpy.bincountকুশলী হয়, সহ numpy.uniqueসঙ্গে return_countsযেমন ARG True। আমি দেখতে পাই সবচেয়ে সাধারণ এন-ডাইমেনশনাল ফাংশনটি হ'ল স্কিপি.স্ট্যাটস.মোড, যদিও এটি নিষিদ্ধভাবে ধীর - বিশেষত অনেকগুলি অনন্য মান সহ বড় অ্যারেগুলির জন্য। সমাধান হিসাবে, আমি এই ফাংশনটি বিকাশ করেছি এবং এটি ব্যবহার করে প্রচুর পরিমাণে:

import numpy

def mode(ndarray, axis=0):
    # Check inputs
    ndarray = numpy.asarray(ndarray)
    ndim = ndarray.ndim
    if ndarray.size == 1:
        return (ndarray[0], 1)
    elif ndarray.size == 0:
        raise Exception('Cannot compute mode on empty array')
    try:
        axis = range(ndarray.ndim)[axis]
    except:
        raise Exception('Axis "{}" incompatible with the {}-dimension array'.format(axis, ndim))

    # If array is 1-D and numpy version is > 1.9 numpy.unique will suffice
    if all([ndim == 1,
            int(numpy.__version__.split('.')[0]) >= 1,
            int(numpy.__version__.split('.')[1]) >= 9]):
        modals, counts = numpy.unique(ndarray, return_counts=True)
        index = numpy.argmax(counts)
        return modals[index], counts[index]

    # Sort array
    sort = numpy.sort(ndarray, axis=axis)
    # Create array to transpose along the axis and get padding shape
    transpose = numpy.roll(numpy.arange(ndim)[::-1], axis)
    shape = list(sort.shape)
    shape[axis] = 1
    # Create a boolean array along strides of unique values
    strides = numpy.concatenate([numpy.zeros(shape=shape, dtype='bool'),
                                 numpy.diff(sort, axis=axis) == 0,
                                 numpy.zeros(shape=shape, dtype='bool')],
                                axis=axis).transpose(transpose).ravel()
    # Count the stride lengths
    counts = numpy.cumsum(strides)
    counts[~strides] = numpy.concatenate([[0], numpy.diff(counts[~strides])])
    counts[strides] = 0
    # Get shape of padded counts and slice to return to the original shape
    shape = numpy.array(sort.shape)
    shape[axis] += 1
    shape = shape[transpose]
    slices = [slice(None)] * ndim
    slices[axis] = slice(1, None)
    # Reshape and compute final counts
    counts = counts.reshape(shape).transpose(transpose)[slices] + 1

    # Find maximum counts and return modals/counts
    slices = [slice(None, i) for i in sort.shape]
    del slices[axis]
    index = numpy.ogrid[slices]
    index.insert(axis, numpy.argmax(counts, axis=axis))
    return sort[index], counts[index]

ফলাফল:

In [2]: a = numpy.array([[1, 3, 4, 2, 2, 7],
                         [5, 2, 2, 1, 4, 1],
                         [3, 3, 2, 2, 1, 1]])

In [3]: mode(a)
Out[3]: (array([1, 3, 2, 2, 1, 1]), array([1, 2, 2, 2, 1, 2]))

কিছু মানদণ্ড:

In [4]: import scipy.stats

In [5]: a = numpy.random.randint(1,10,(1000,1000))

In [6]: %timeit scipy.stats.mode(a)
10 loops, best of 3: 41.6 ms per loop

In [7]: %timeit mode(a)
10 loops, best of 3: 46.7 ms per loop

In [8]: a = numpy.random.randint(1,500,(1000,1000))

In [9]: %timeit scipy.stats.mode(a)
1 loops, best of 3: 1.01 s per loop

In [10]: %timeit mode(a)
10 loops, best of 3: 80 ms per loop

In [11]: a = numpy.random.random((200,200))

In [12]: %timeit scipy.stats.mode(a)
1 loops, best of 3: 3.26 s per loop

In [13]: %timeit mode(a)
1000 loops, best of 3: 1.75 ms per loop

সম্পাদনা: একটি পটভূমির অনেক বেশি সরবরাহ করা হয়েছে এবং আরও মেমরি-দক্ষ হওয়ার জন্য পদ্ধতির পরিবর্তন করা হয়েছে


4
দয়া করে এটি স্কিপি স্ট্যাট মডিউলটিতে অবদান রাখুন যাতে অন্যরাও এটি থেকে উপকৃত হতে পারে।
এআরএফ

বিগ ইন্ট এনডাররেয়েসের সাথে উচ্চতর মাত্রিক সমস্যার জন্য, আপনার সমাধানটি স্কিপি.স্ট্যাটস.মোডের থেকে এখনও বেশ দ্রুত বলে মনে হচ্ছে। আমাকে 4x250x250x500 নাদারের প্রথম অক্ষ বরাবর মোডটি গণনা করতে হয়েছিল এবং আপনার ফাংশনটি 10 ​​সেকেন্ড নিয়েছে, যখন স্কিপি.স্ট্যাটস.মোড প্রায় 600s নিয়েছিল।
চ্যাশায়ারগেট

11

এই পদ্ধতির প্রসারিত , ডেটাটির মোডটি অনুসন্ধানের জন্য প্রয়োগ করা হয়েছে যেখানে বিতরণের কেন্দ্র থেকে মানটি কতটা দূরে রয়েছে তা দেখার জন্য আপনাকে প্রকৃত অ্যারের সূচকের প্রয়োজন হতে পারে।

(_, idx, counts) = np.unique(a, return_index=True, return_counts=True)
index = idx[np.argmax(counts)]
mode = a[index]

লেন (এনপি.আরগম্যাক্স (গণনা))> 1 এর সময় মোডটি বাতিল করতে ভুলবেন না, এটি যদি আপনার ডেটার কেন্দ্রীয় বিতরণের প্রকৃত প্রতিনিধিত্ব করে তবে আপনি এটি পরীক্ষা করতে পারেন যে এটি আপনার স্ট্যান্ডার্ড বিচ্যুতি ব্যবস্থার মধ্যে পড়ে কিনা।


আপনি যদি অক্ষটি নির্দিষ্ট না করেন তবে এনপি.আরগম্যাক্স কখন 1 এর চেয়ে বেশি দৈর্ঘ্যের কোনও কিছু ফেরত দেয়?
লোগানজোন 16

10

একটি ঝরঝরে সমাধান শুধুমাত্র ব্যবহারসমূহ numpy(না scipyনা Counterবর্গ):

A = np.array([[1,3,4,2,2,7], [5,2,2,1,4,1], [3,3,2,2,1,1]])

np.apply_along_axis(lambda x: np.bincount(x).argmax(), axis=0, arr=A)

অ্যারে ([1, 3, 2, 2, 1, 1])


4
খুব সুন্দর এবং সংক্ষিপ্ত, তবে মূল অ্যারেগুলিতে খুব বেশি সংখ্যক উপস্থিত থাকলে সাবধানতার সাথে ব্যবহার করা উচিত কারণ বিঙ্কাউন্টটি প্রতিটি মূল অ্যারে A [i] এর জন্য লেন (সর্বোচ্চ (এ [i])) সহ বিন অ্যারে তৈরি করবে।
স্কটলিটল

এটি একটি দুর্দান্ত সমাধান। আসলে একটি অসুবিধা আছে scipy.stats.mode। যখন একাধিক মান সর্বাধিক উপস্থিতি (একাধিক মোড) থাকে, তখন এটি একটি প্রত্যাশা ফেলে দেয়। তবে এই পদ্ধতিটি স্বয়ংক্রিয়ভাবে "প্রথম মোড" নেবে।
ক্রিস্টোফার

6

আপনি যদি কেবল অদ্ভুত ব্যবহার করতে চান:

x = [-1, 2, 1, 3, 3]
vals,counts = np.unique(x, return_counts=True)

দেয়

(array([-1,  1,  2,  3]), array([1, 1, 1, 2]))

এবং এটি নিষ্কাশন:

index = np.argmax(counts)
return vals[index]

এই পদ্ধতিটি পছন্দ করুন কারণ এটি কেবল পূর্ণসংখ্যাকেই সমর্থন করে না, তবে ভাসমান এবং এমনকি স্ট্রিংগুলিকেও সমর্থন করে!
ক্রিস্টোফার

3

আমার মনে হয় কাউন্টার ক্লাসটি ব্যবহার করা খুব সহজ উপায়। তারপরে আপনি এখানে উল্লিখিত হিসাবে কাউন্টার উদাহরণের মোস্ট_কমোন () ফাংশনটি ব্যবহার করতে পারেন ।

1-ডি অ্যারেগুলির জন্য:

import numpy as np
from collections import Counter

nparr = np.arange(10) 
nparr[2] = 6 
nparr[3] = 6 #6 is now the mode
mode = Counter(nparr).most_common(1)
# mode will be [(6,3)] to give the count of the most occurring value, so ->
print(mode[0][0])    

একাধিক মাত্রিক অ্যারে (সামান্য পার্থক্য) এর জন্য:

import numpy as np
from collections import Counter

nparr = np.arange(10) 
nparr[2] = 6 
nparr[3] = 6 
nparr = nparr.reshape((10,2,5))     #same thing but we add this to reshape into ndarray
mode = Counter(nparr.flatten()).most_common(1)  # just use .flatten() method

# mode will be [(6,3)] to give the count of the most occurring value, so ->
print(mode[0][0])

এটি কার্যকর প্রয়োগ হতে পারে বা নাও হতে পারে তবে এটি সুবিধাজনক।


2
from collections import Counter

n = int(input())
data = sorted([int(i) for i in input().split()])

sorted(sorted(Counter(data).items()), key = lambda x: x[1], reverse = True)[0][0]

print(Mean)

Counter(data)ফ্রিকোয়েন্সি বড়, মোট ছাত্র এবং একটি defaultdict ফেরৎ। sorted(Counter(data).items())কীগুলি ব্যবহার করে বাছাই করুন, ফ্রিকোয়েন্সি নয়। অবশেষে, এর সাথে বাছাই করা অন্যটির সাহায্যে ফ্রিকোয়েন্সি বাছাই করা দরকার key = lambda x: x[1]। বিপরীতটি পাইথনকে বলে যে ফ্রিকোয়েন্সিটি বৃহত্তম থেকে ক্ষুদ্রতম পর্যন্ত সাজান।


যেহেতু প্রশ্নটি 6 বছর আগে জিজ্ঞাসা করা হয়েছিল, তাই স্বাভাবিক যে তিনি খুব বেশি খ্যাতি পাননি।
জেলিহা বেকটাস

1

পাইথনের সবচেয়ে সহজ উপায় একটি তালিকা বা অ্যারের মোড পেতে

   import statistics
   print("mode = "+str(statistics.(mode(a)))

এটাই

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.