নপি: সবচেয়ে দক্ষ ফ্রিকোয়েন্সি একটি অ্যারেতে অনন্য মানের জন্য গণনা করে


244

ইন numpy/ scipy, একটি হল দক্ষ উপায় হল একটি অ্যারের মধ্যে অনন্য মানের জন্য ফ্রিকোয়েন্সি গন্য পেতে?

এই লাইন বরাবর কিছু:

x = array( [1,1,1,2,2,2,5,25,1,1] )
y = freq_count( x )
print y

>> [[1, 5], [2,3], [5,1], [25,1]]

(আপনার জন্য, সেখানে আর ব্যবহারকারীগণ, আমি মূলত table()ফাংশনটি সন্ধান করছি )


5
কি collections.Counter(x)যথেষ্ট?
পাইলং

1
আপনি যদি এই প্রশ্নের উত্তরটি এখনই আপনার প্রশ্নের সঠিক হিসাবে চিহ্নিত করেন তবে এটি আরও ভাল হবে: stackoverflow.com/a/25943480/9024698
আউটকাস্ট

কালেকশন.কাউন্টারটি বেশ ধীর। আমার পোস্ট দেখুন stackoverflow.com/questions/41594940/...
Sembei Norimaki

উত্তর:


161

একবার দেখুন np.bincount:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.html

import numpy as np
x = np.array([1,1,1,2,2,2,5,25,1,1])
y = np.bincount(x)
ii = np.nonzero(y)[0]

এবং তারপর:

zip(ii,y[ii]) 
# [(1, 5), (2, 3), (5, 1), (25, 1)]

বা:

np.vstack((ii,y[ii])).T
# array([[ 1,  5],
         [ 2,  3],
         [ 5,  1],
         [25,  1]])

অথবা তবে আপনি গণনা এবং অনন্য মানগুলি একত্রিত করতে চান।


42
হাই, এক্স এর উপাদানগুলির ইনট ব্যতীত অন্য ধরণের টাইপ থাকলে এটি কাজ করবে না।
মনোজ

7
অ-নেতিবাচক ints ব্যতীত অন্য কিছু হলে এটি কাজ করবে না, এবং ints ফাঁক করে ফেলা হলে এটি খুব স্থান অকার্যকর হবে।
এরিক

ন্যালি সংস্করণ ১.১০ সহ আমি খুঁজে পেয়েছি যে পূর্ণসংখ্যার গণনা করার জন্য, এটি এনপি.উনিকের থেকে প্রায় times গুণ দ্রুত। এছাড়াও, মনে রাখবেন যে এটি সঠিকভাবে পরামিতিগুলি দেওয়া হয়, যদি এটি নেতিবাচক ints গণনা করে না।
জিহুন

@ মনোজ: আমার উপাদানগুলি এক্সে রয়েছে। আমি jme এর সমাধান পরীক্ষা করছি।
ক্যাটালিনা চিরচু

508

নম্পি ১.৯ হিসাবে, সহজ এবং দ্রুততম পদ্ধতিটি কেবল সহজেই ব্যবহার করা হয় numpy.unique, যার এখন একটি return_countsকীওয়ার্ড যুক্তি রয়েছে:

import numpy as np

x = np.array([1,1,1,2,2,2,5,25,1,1])
unique, counts = np.unique(x, return_counts=True)

print np.asarray((unique, counts)).T

যা দেয়:

 [[ 1  5]
  [ 2  3]
  [ 5  1]
  [25  1]]

এর সাথে একটি দ্রুত তুলনা scipy.stats.itemfreq:

In [4]: x = np.random.random_integers(0,100,1e6)

In [5]: %timeit unique, counts = np.unique(x, return_counts=True)
10 loops, best of 3: 31.5 ms per loop

In [6]: %timeit scipy.stats.itemfreq(x)
10 loops, best of 3: 170 ms per loop

22
আপডেট করার জন্য ধন্যবাদ! এটি এখন, আইএমও, সঠিক উত্তর।
এরভ 1879

1
BAM! এই কারণেই আমরা আপডেট করি ... যখন আমরা এর মতো উত্তর পাই। এত দীর্ঘ অদ্ভুত 1.8। আমরা কীভাবে এটি তালিকার শীর্ষে পেতে পারি?
ব্যবহারকারী 1269942

আপনি যদি ত্রুটিটি পেয়ে থাকেন: প্রকারের ত্রুটি: অনন্য () একটি অপ্রত্যাশিত কীওয়ার্ড আর্গুমেন্ট 'রিটার্ন_ অ্যাকাউন্টস' পেয়েছে, কেবল করুন: অনন্য, গণনাগুলি = এনপি.উনিক (এক্স, ট্রু)
নুমসসঙ্গুইস

3
@ নুমসসঙ্গুইস আপনি নম্পির কোন সংস্করণ ব্যবহার করছেন? V1.9 এর আগে, return_countsকীওয়ার্ড যুক্তি উপস্থিত ছিল না, যা ব্যতিক্রমটি ব্যাখ্যা করতে পারে। সেক্ষেত্রে, ডক্স যে সুপারিশ np.unique(x, True)সমতুল্য হয় np.unique(x, return_index=True), যা গন্য ফেরত দেয় না।
jme

1
পুরানো ছদ্মবেশী সংস্করণগুলিতে একই জিনিসটি পেতে আদর্শ আইডিয়াম unique, idx = np.unique(x, return_inverse=True); counts = np.bincount(idx)। যখন এই বৈশিষ্ট্যটি যুক্ত করা হয়েছিল ( এখানে দেখুন ) কিছু অনানুষ্ঠানিক পরীক্ষায় return_countsদ্রুত 5x এর বেশি ক্লকিংয়ের ব্যবহার ছিল ।
জাইমে

133

আপডেট: মূল উত্তরে উল্লিখিত পদ্ধতিটি অবচয় করা হয়েছে, পরিবর্তে আমাদের নতুন পদ্ধতিটি ব্যবহার করা উচিত:

>>> import numpy as np
>>> x = [1,1,1,2,2,2,5,25,1,1]
>>> np.array(np.unique(x, return_counts=True)).T
    array([[ 1,  5],
           [ 2,  3],
           [ 5,  1],
           [25,  1]])

আসল উত্তর:

আপনি scipy.stats.itemfreq ব্যবহার করতে পারেন

>>> from scipy.stats import itemfreq
>>> x = [1,1,1,2,2,2,5,25,1,1]
>>> itemfreq(x)
/usr/local/bin/python:1: DeprecationWarning: `itemfreq` is deprecated! `itemfreq` is deprecated and will be removed in a future version. Use instead `np.unique(..., return_counts=True)`
array([[  1.,   5.],
       [  2.,   3.],
       [  5.,   1.],
       [ 25.,   1.]])

1
এখন পর্যন্ত সবচেয়ে পাইথোনিক পদ্ধতির মতো মনে হচ্ছে। এছাড়াও, "কাঙ্ক্ষিত অ্যারেগুলির জন্য খুব গভীরভাবে অবজেক্ট" বিষয়গুলির সাথে আমি 100k x 100 কে ম্যাট্রিকগুলিতে এনপি.বিঙ্কাউন্টের সমস্যার সম্মুখীন হয়েছি।
মেটাসেকোয়া

1
আমি বরং মূল প্রশ্নের উত্তরদাতাকে প্রথমটির উত্তর থেকে পরিবর্তিত হয়ে এর উত্তরটি পরিবর্তনের জন্য এর দৃষ্টিভঙ্গি বাড়ানোর পরামর্শ
দিই

যদিও 0.14 এর আগে সংস্করণগুলির জন্য এটি ধীর গতির।
জেসন এস

লক্ষ করুন যে অ্যারেটি যদি স্ট্রিংয়ে পূর্ণ থাকে তবে প্রত্যাবর্তিত প্রতিটি আইটেমের উভয় উপাদানই স্ট্রিং are
ব্যবহারকারী 1269942

দেখে মনে হচ্ছে আইটেমফ্রেইককে অবমূল্যায়ন করা হয়েছে
টেরেন্স পারর

48

আমি এটিতে আগ্রহীও ছিলাম, তাই আমি কিছুটা পারফরম্যান্স তুলনা করেছি ( আমার একটি পোষ্য প্রকল্প পারফ্লোট ব্যবহার করে )। ফলাফল:

y = np.bincount(a)
ii = np.nonzero(y)[0]
out = np.vstack((ii, y[ii])).T

এখন পর্যন্ত দ্রুততম। (লগ-স্কেলিং নোট করুন।)

এখানে চিত্র বর্ণনা লিখুন


প্লট তৈরির কোড:

import numpy as np
import pandas as pd
import perfplot
from scipy.stats import itemfreq


def bincount(a):
    y = np.bincount(a)
    ii = np.nonzero(y)[0]
    return np.vstack((ii, y[ii])).T


def unique(a):
    unique, counts = np.unique(a, return_counts=True)
    return np.asarray((unique, counts)).T


def unique_count(a):
    unique, inverse = np.unique(a, return_inverse=True)
    count = np.zeros(len(unique), np.int)
    np.add.at(count, inverse, 1)
    return np.vstack((unique, count)).T


def pandas_value_counts(a):
    out = pd.value_counts(pd.Series(a))
    out.sort_index(inplace=True)
    out = np.stack([out.keys().values, out.values]).T
    return out


perfplot.show(
    setup=lambda n: np.random.randint(0, 1000, n),
    kernels=[bincount, unique, itemfreq, unique_count, pandas_value_counts],
    n_range=[2 ** k for k in range(26)],
    logx=True,
    logy=True,
    xlabel="len(a)",
)

1
প্লট উত্পন্ন করতে কোড পোস্ট করার জন্য ধন্যবাদ। পারফ্ল্লট সম্পর্কে এখন আগে জানতাম না । হ্যান্ডসেট লাগছে।
ruffsl

আমি বিকল্প যোগ করে আপনার কোড রান করতে সক্ষম হন equality_check=array_sorteqযে perfplot.show()। (পাইথন 2 এ) কোন ত্রুটি সৃষ্টি করছিল pd.value_countsতা ছিল (এমনকি সাজান = মিথ্যা দিয়েও)।
ব্যবহারকারী 2314737

33

পান্ডাস মডিউল ব্যবহার:

>>> import pandas as pd
>>> import numpy as np
>>> x = np.array([1,1,1,2,2,2,5,25,1,1])
>>> pd.value_counts(x)
1     5
2     3
25    1
5     1
dtype: int64

5
পিডি.সারিজ () প্রয়োজনীয় নয়। অন্যথায়, ভাল উদাহরণ। নোংরা পাশাপাশি। পান্ডারা ইনপুট হিসাবে একটি সহজ তালিকা নিতে পারে।
যোহান ওবাদিয়া

1
@ যোহানবাবাদিয়া - অ্যারের আকারের উপর নির্ভর করে অ্যারেটিকে প্রথমে একটি সিরিজে রূপান্তর করা আমার পক্ষে চূড়ান্ত অপারেশনটিকে দ্রুততর করে তুলেছে। আমি প্রায় 50,000 মান হিসাবে চিহ্নিত করতে হবে।
n1k31t4

1
আমি @ যোহানবাবাদিয়া
ivankeller

19

এটি এখন পর্যন্ত সবচেয়ে সাধারণ এবং পারফরম্যান্ট সমাধান; অবাক করা এখনও এটি পোস্ট করা হয়নি।

import numpy as np

def unique_count(a):
    unique, inverse = np.unique(a, return_inverse=True)
    count = np.zeros(len(unique), np.int)
    np.add.at(count, inverse, 1)
    return np.vstack(( unique, count)).T

print unique_count(np.random.randint(-10,10,100))

বর্তমানে গৃহীত উত্তরের মতো নয়, এটি এমন কোনও ডেটাটাইপতে কাজ করে যা বাছাইযোগ্য (কেবলমাত্র ইতিবাচক ints নয়), এবং এটির সর্বোত্তম কার্যকারিতা রয়েছে; একমাত্র উল্লেখযোগ্য ব্যয় হ'ল এনপি.উনিক দ্বারা বাছাই করা।


কাজ করে না:AttributeError: 'numpy.ufunc' object has no attribute 'at'
PR

একটি সহজ পদ্ধতি কল করা হবেnp.bincount(inverse)
ali_m

15

numpy.bincountসম্ভবত সেরা পছন্দ। আপনার অ্যারেতে যদি ছোট ঘন পূর্ণসংখ্যার পাশাপাশি কিছু থাকে তবে এটি এ জাতীয় কিছু মোড়ানো কার্যকর হতে পারে:

def count_unique(keys):
    uniq_keys = np.unique(keys)
    bins = uniq_keys.searchsorted(keys)
    return uniq_keys, np.bincount(bins)

উদাহরণ স্বরূপ:

>>> x = array([1,1,1,2,2,2,5,25,1,1])
>>> count_unique(x)
(array([ 1,  2,  5, 25]), array([5, 3, 1, 1]))

8

যদিও ইতিমধ্যে এটির উত্তর দেওয়া হয়েছে, আমি একটি ভিন্ন পদ্ধতির পরামর্শ দিচ্ছি যা ব্যবহার করে numpy.histogram। এই জাতীয় ক্রিয়াকলাপটিকে একটি সিকোয়েন্স দেওয়া হয় যা এটি বিনের মধ্যে গোষ্ঠীযুক্ত উপাদানগুলির ফ্রিকোয়েন্সি প্রদান করে ।

যদিও সাবধান : এটি এই উদাহরণে কাজ করে কারণ সংখ্যাটি পূর্ণসংখ্যা। যদি তারা যেখানে আসল সংখ্যা, তবে এই সমাধানটি দুর্দান্তভাবে প্রযোজ্য হবে না।

>>> from numpy import histogram
>>> y = histogram (x, bins=x.max()-1)
>>> y
(array([5, 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       1]),
 array([  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,
        12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.,  20.,  21.,  22.,
        23.,  24.,  25.]))

5
import pandas as pd
import numpy as np
x = np.array( [1,1,1,2,2,2,5,25,1,1] )
print(dict(pd.Series(x).value_counts()))

এটি আপনাকে দেয়: {1: 5, 2: 3, 5: 1, 25: 1}


1
collections.Counter(x)একই ফলাফল দিন। আমি বিশ্বাস করি যে ওপি একটি আউটপুট চায় যা আর tableফাংশনটির অনুরূপ । রাখা Seriesআরও কার্যকর হতে পারে।
পাইলং

দয়া করে নোট করুন যে এটি pd.Series(x).reshape(-1)বহুমাত্রিক অ্যারে হলে স্থানান্তর করা প্রয়োজন হবে।
নাটসাপো

4

অনন্য অ ইন্টিজারগুলি গণনা করতে - ইলকো হুগেনডুরউনের উত্তরের মতো তবে যথেষ্ট দ্রুত (আমার মেশিনে 5 টি ফ্যাক্টর), আমি কিছুটা সি-কোডের সাথে weave.inlineএকত্রিত করতাম numpy.unique;

import numpy as np
from scipy import weave

def count_unique(datain):
  """
  Similar to numpy.unique function for returning unique members of
  data, but also returns their counts
  """
  data = np.sort(datain)
  uniq = np.unique(data)
  nums = np.zeros(uniq.shape, dtype='int')

  code="""
  int i,count,j;
  j=0;
  count=0;
  for(i=1; i<Ndata[0]; i++){
      count++;
      if(data(i) > data(i-1)){
          nums(j) = count;
          count = 0;
          j++;
      }
  }
  // Handle last value
  nums(j) = count+1;
  """
  weave.inline(code,
      ['data', 'nums'],
      extra_compile_args=['-O2'],
      type_converters=weave.converters.blitz)
  return uniq, nums

প্রোফাইল তথ্য

> %timeit count_unique(data)
> 10000 loops, best of 3: 55.1 µs per loop

Eelco এর বিশুদ্ধ numpyসংস্করণ:

> %timeit unique_count(data)
> 1000 loops, best of 3: 284 µs per loop

বিঃদ্রঃ

এখানে অপ্রয়োজনীয়তা রয়েছে ( uniqueএকটি সাজানও সম্পাদন করে) যার অর্থ uniqueসি কোড লুপের ভিতরে কার্যকারিতা রেখে কোডটি সম্ভবত আরও অনুকূলিত করা যেতে পারে ।


4

পুরানো প্রশ্ন, তবে আমি আমার নিজস্ব সমাধান সরবরাহ করতে চাই যা সবচেয়ে দ্রুতগতিতে পরিণত হয় , আমার বেঞ্চ পরীক্ষার ভিত্তিতে ইনপুট (বা প্রথমে তালিকায় স্থানান্তরকরণ) listনা হয়ে সাধারণ ব্যবহার np.arrayকরুন।

আপনি যদি এটির মুখোমুখি হন তবে এটি পরীক্ষা করে দেখুন

def count(a):
    results = {}
    for x in a:
        if x not in results:
            results[x] = 1
        else:
            results[x] += 1
    return results

উদাহরণ স্বরূপ,

>>>timeit count([1,1,1,2,2,2,5,25,1,1]) would return:

100000 লুপগুলি, প্রতি লুপে 3: 2.26 এর মধ্যে সেরা

>>>timeit count(np.array([1,1,1,2,2,2,5,25,1,1]))

100000 লুপগুলি, প্রতি লুপে 3: 8.8 µ সর্বোত্তম

>>>timeit count(np.array([1,1,1,2,2,2,5,25,1,1]).tolist())

100000 লুপগুলি, প্রতি লুপে 3: 5.85 µ সেরা

যদিও গৃহীত উত্তরটি ধীর হবে এবং scipy.stats.itemfreqসমাধানটি আরও খারাপ।


আরও নির্লিপ্ত পরীক্ষাটি সূচিত প্রত্যাশার সত্যতা দেয়নি

from zmq import Stopwatch
aZmqSTOPWATCH = Stopwatch()

aDataSETasARRAY = ( 100 * abs( np.random.randn( 150000 ) ) ).astype( np.int )
aDataSETasLIST  = aDataSETasARRAY.tolist()

import numba
@numba.jit
def numba_bincount( anObject ):
    np.bincount(    anObject )
    return

aZmqSTOPWATCH.start();np.bincount(    aDataSETasARRAY );aZmqSTOPWATCH.stop()
14328L

aZmqSTOPWATCH.start();numba_bincount( aDataSETasARRAY );aZmqSTOPWATCH.stop()
592L

aZmqSTOPWATCH.start();count(          aDataSETasLIST  );aZmqSTOPWATCH.stop()
148609L

সূত্র। ক্যাশে এবং অন্যান্য ইন-র্যামের পার্শ্ব-প্রতিক্রিয়াগুলির নীচে মন্তব্যগুলি যা একটি ছোট ডেটাসেটকে ব্যাপকভাবে পুনরাবৃত্তিযোগ্য পরীক্ষার ফলাফলগুলিকে প্রভাবিত করে।


এই উত্তরটি সত্যিই ভাল, কারণ এটি দেখায় numpyযে অগত্যা যাওয়ার উপায় নয় to
মাহদী

পছন্দ করুন আপনি কিছু অ-ক্যাশে-সক্ষম ডেটাসেট আকারেও তালিকা-অনুমানকে ক্রস-বৈধ করেছেন? একটি উপস্থাপনায় একটি 150.000 এলোমেলো আইটেম ধরে নেওয়া যাক এবং aZmqStopwatch.start (); গণনা (aRepmittedation); aZmqStopwatch.stop () উদাহরণ দ্বারা একটি একক রান উপর কিছুটা নির্ভুল পরিমাপ করা যাক ?
ব্যবহারকারী3666197

কিছু পরীক্ষা করে নি এবং হ্যাঁ, বাস্তব ডেটাসেট পারফরম্যান্সে বিশাল পার্থক্য রয়েছে। পরীক্ষার জন্য পাইথন অভ্যন্তরীণ মেকানিক্সের দিকে আরও কিছুটা অন্তর্দৃষ্টি প্রয়োজন কেবল একটি ব্রুট-ফোর্স স্কেলড লুপগুলি চালানো এবং ভিট্রো-ইন-ভিট্রো ন্যানোসেকেন্ডগুলির উদ্ধৃতি than পরীক্ষিত হিসেবে - একটি np.bincount () মধ্যে 150.000 অ্যারের হ্যান্ডেল করতে তৈরি করা যেতে পারে কম 600 [আমাদের] যখন উপরে Def -ed গণনা () একটি প্রি-রূপান্তরিত তালিকা উপস্থাপনা উপর উহার নেন চেয়ে বেশি 122,000 [আমাদের]
user3666197

হ্যাঁ, আমার নিয়মমাফিক থাম্বটি এমন কোনও কিছুর জন্য অদৃশ্য যা ক্ষুদ্র পরিমাণে বিলম্বিতা পরিচালনা করতে পারে তবে খুব বড় হওয়ার সম্ভাবনা রয়েছে, ছোট ডেটা সেটগুলির জন্য তালিকা দেয় যেখানে বিলম্বিতা সমালোচনা এবং অবশ্যই সত্যিকারের বেঞ্চমার্কিং এফটিডব্লু :)
ডেভিড

1

এর মতো কিছু জিনিস এটি করা উচিত:

#create 100 random numbers
arr = numpy.random.random_integers(0,50,100)

#create a dictionary of the unique values
d = dict([(i,0) for i in numpy.unique(arr)])
for number in arr:
    d[j]+=1   #increment when that value is found

এছাড়াও, দক্ষতার সাথে অনন্য উপাদান গণনা করার এই আগের পোস্টটি আপনার প্রশ্নের সাথে বেশ মিল বলে মনে হচ্ছে, যদি না আমি কিছু অনুপস্থিত।


লিঙ্কযুক্ত প্রশ্নটি একই রকম, তবে দেখে মনে হচ্ছে তিনি আরও জটিল ডেটা ধরণের কাজ করছেন।
আবে

1

বহু-মাত্রিক ফ্রিকোয়েন্সি গণনা, অর্থাৎ অ্যারে গণনা।

>>> print(color_array    )
  array([[255, 128, 128],
   [255, 128, 128],
   [255, 128, 128],
   ...,
   [255, 128, 128],
   [255, 128, 128],
   [255, 128, 128]], dtype=uint8)


>>> np.unique(color_array,return_counts=True,axis=0)
  (array([[ 60, 151, 161],
    [ 60, 155, 162],
    [ 60, 159, 163],
    [ 61, 143, 162],
    [ 61, 147, 162],
    [ 61, 162, 163],
    [ 62, 166, 164],
    [ 63, 137, 162],
    [ 63, 169, 164],
   array([     1,      2,      2,      1,      4,      1,      1,      2,
         3,      1,      1,      1,      2,      5,      2,      2,
       898,      1,      1,  


0
from collections import Counter
x = array( [1,1,1,2,2,2,5,25,1,1] )
mode = counter.most_common(1)[0][0]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.