سؤال

ما هي الطريقة الجيدة لقيام القيم العددية في نطاق معين؟ على سبيل المثال ، لنفترض أن لدي قائمة بالقيم وأريد أن أقرصها في صناديق N بواسطة نطاقها. الآن ، أفعل شيئًا كهذا:

from scipy import *
num_bins = 3 # number of bins to use
values = # some array of integers...
min_val = min(values) - 1
max_val = max(values) + 1
my_bins = linspace(min_val, max_val, num_bins)
# assign point to my bins
for v in values:
  best_bin = min_index(abs(my_bins - v))

حيث يقوم Min_index بإرجاع فهرس الحد الأدنى للقيمة. والفكرة هي أنه يمكنك العثور على بن النقطة تسقط من خلال رؤية بن له أصغر فرق.

لكنني أعتقد أن هذا له حالات حافة غريبة. ما أبحث عنه هو تمثيل جيد من الصناديق ، من الناحية المثالية التي تكون نصف نصف مغلقة مفتوحة (بحيث لا توجد طريقة لتعيين نقطة واحدة إلى صناديق اثنين) ، أي

bin1 = [x1, x2)
bin2 = [x2, x3)
bin3 = [x3, x4)
etc...

ما هي الطريقة الجيدة للقيام بذلك في بيثون ، باستخدام Numpy/Scipy؟ أنا قلق فقط هنا بقيم عدد صحيح binning.

شكرا جزيلا على مساعدتك.

هل كانت مفيدة؟

المحلول

numpy.histogram() يفعل بالضبط ما تريد.

توقيع الوظيفة هو:

numpy.histogram(a, bins=10, range=None, normed=False, weights=None, new=None)

نحن مهتمون في الغالب a و bins. a هي بيانات الإدخال التي تحتاج إلى binned. bins يمكن أن يكون عددًا من الصناديق ( num_bins) ، أو يمكن أن يكون تسلسلًا من العدادات ، والتي تشير إلى حواف الحاوية (نصف مفتوحة).

import numpy
values = numpy.arange(10, dtype=int)
bins = numpy.arange(-1, 11)
freq, bins = numpy.histogram(values, bins)
# freq is now [0 1 1 1 1 1 1 1 1 1 1]
# bins is unchanged

على حد تعبير توثيق:

كل ما عدا آخر بن (Righthand-Most) هو نصف فتح. بمعنى آخر ، إذا bins هو:

[1, 2, 3, 4]

ثم الحاوية الأولى هي [1, 2) (بما في ذلك 1 ، ولكن باستثناء 2) والثاني [2, 3). الحاوية الأخيرة ، ومع ذلك ، هو [3, 4], ، أيّ يشمل 4.

تعديل: تريد معرفة الفهرس في صناديق كل عنصر. لهذا ، يمكنك استخدام numpy.digitize(). إذا كانت صناديقك ستكون جزءًا لا يتجزأ ، فيمكنك استخدامها numpy.bincount() أيضًا.

>>> values = numpy.random.randint(0, 20, 10)
>>> values
array([17, 14,  9,  7,  6,  9, 19,  4,  2, 19])
>>> bins = numpy.linspace(-1, 21, 23)
>>> bins
array([ -1.,   0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,
        10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.,  20.,
        21.])
>>> pos = numpy.digitize(values, bins)
>>> pos
array([19, 16, 11,  9,  8, 11, 21,  6,  4, 21])

نظرًا لأن الفاصل الزمني مفتوح على الحد الأعلى ، فإن المؤشرات صحيحة:

>>> (bins[pos-1] == values).all()
True
>>> import sys
>>> for n in range(len(values)):
...     sys.stdout.write("%g <= %g < %g\n"
...             %(bins[pos[n]-1], values[n], bins[pos[n]]))
17 <= 17 < 18
14 <= 14 < 15
9 <= 9 < 10
7 <= 7 < 8
6 <= 6 < 7
9 <= 9 < 10
19 <= 19 < 20
4 <= 4 < 5
2 <= 2 < 3
19 <= 19 < 20

نصائح أخرى

هذا واضح ومباشر إلى حد ما في Numpy باستخدام البث-مثال على ذلك أدناه هو أربعة أسطر من التعليمات البرمجية (لا تحسب أول سطرين لإنشاء صناديق ونقاط البيانات ، والتي سيتم توفيرها بالطبع عادة.)

import numpy as NP
# just creating 5 bins at random, each bin expressed as (x, y, z) although, this code
# is not limited by bin number or bin dimension
bins = NP.random.random_integers(10, 99, 15).reshape(5, 3) 
# creating 30 random data points
data = NP.random.random_integers(10, 99, 90).reshape(30, 3)
# for each data point i want the nearest bin, but before i can generate a distance
# matrix, i need to 'conform' the array dimensions
# 'broadcasting' is an excellent and concise way to do this
bins = bins[:, NP.newaxis, :]
data2 = data[NP.newaxis, :, :]
# now i can calculate the distance matrix
dist_matrix = NP.sqrt(NP.sum((data - bins)**2, axis=-1)) 
bin_assignments = NP.argmin(dist_matrix, axis=0)

"bin_assignments" عبارة عن مجموعة 1D من المؤشرات التي تتكون من قيم عدد صحيح من 0 إلى 4 ، تقابل الصناديق الخمسة-تخصيصات BIN لكل نقطة من النقاط الأصلية الثلاثين في مصفوفة "البيانات" أعلاه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top