मेरे पास लंबाई 'एन' के बूलियन सरणी का एक बड़ा नमूना (एम) है। तो 2^एन अद्वितीय बूलियन सरणी संभव हैं। मैं जानना चाहता हूं कि कितने सरणी एक दूसरे के डुप्लीकेट हैं और हिस्टोग्राम बनाते हैं।

एक संभावना प्रत्येक अद्वितीय सरणी के लिए एक अद्वितीय पूर्णांक (a[0] + a[1]*2 + a[3]*4 + ...+a[N]*2^(N-1)) बनाना है और उस पूर्णांक का हिस्टोग्राम।

लेकिन यह ओ (एम * एन) होने जा रहा है। इसे करने का बेहतरीन तरीका क्या है?

1
PyariBilli 27 नवम्बर 2021, 09:32
यह आपके आउटपुट पर बहुत कुछ निर्भर करता है। 2^N संयोजनों को संग्रहीत करने से N के बड़े मानों के लिए आपकी मेमोरी तेजी से बर्न होती है। इस मामले में np.histogram का बेहतर उपयोग करें। उनमें से केवल एक छोटा सा हिस्सा हो सकता है जो arr में हो। इस मामले में आपको 2^N आइटम के साथ काम करने और np.bincount का उपयोग करने की आवश्यकता नहीं है। (a[0] + a[1]*2 + a[3]*4 + ...+a[N]*2^(N-1) और numpy.ravel_multi_index वास्तव में इसे अपने मूल में करने से बेहतर कोई तरीका नहीं है। लेकिन अगर आपको कुछ और भी अच्छा लगता है, तो numexpr आज़माएं
 – 
mathfux
27 नवम्बर 2021, 12:47

2 जवाब

सबसे बढ़िया उत्तर

numpy.ravel_multi_index आपके लिए यह करने में सक्षम है :

arr = np.array([[True, True, True], 
              [True, False, True], 
              [True, False, True], 
              [False, False, False], 
              [True, False, True]], dtype=int)
nums = np.ravel_multi_index(arr.T, (2,) * arr.shape[1])
>>> nums
array([7, 5, 5, 0, 5], dtype=int64)

और चूंकि आपको हिस्टोग्राम की आवश्यकता है, उपयोग करें

>>> np.histogram(nums, bins=np.arange(2**arr.shape[1]+1))
(array([1, 0, 0, 0, 0, 3, 0, 1], dtype=int64), 
 array([0, 1, 2, 3, 4, 5, 6, 7, 8]))

एक अन्य विकल्प np.unique का उपयोग करना है:

>>> np.unique(arr, return_counts=True, axis=0)
(array([[0, 0, 0],
        [1, 0, 1],
        [1, 1, 1]]),
 array([1, 3, 1], dtype=int64))
1
mathfux 27 नवम्बर 2021, 12:25

वेक्टरकृत संचालन के साथ, एक कुंजी का निर्माण a[0] + a[1]x2 + a[3]x4 + ...+a[N]*2^(N-1) की तुलना में कहीं अधिक तेज है। मुझे लगता है कि यह कोई बेहतर समाधान नहीं है ... किसी भी मामले में आपको प्रत्येक मान को लगभग एक बार "पढ़ने" की आवश्यकता होती है, और इसके लिए MxN चरण की आवश्यकता होती है।

N = 3
M = 5
sample = [
    np.array([True, True, True]),
    np.array([True, False, True]),
    np.array([True, False, True]),
    np.array([False, False, False]),
    np.array([True, False, True]),
]

multipliers = [2<<i for i in range(N-2, -1, -1)]+[1]

buckets = {}
buck2vec = {}
for s in sample:
    key = sum(s*multipliers)
    if key not in buckets:
        buckets[key] = 0
        buck2vec[key] = s
    buckets[key]+=1
    
for key in buckets:
    print(f"{buck2vec[key]} -> {buckets[key]} occurency")

परिणाम:

[False False False] -> 1 occurency
[ True False  True] -> 3 occurency
[ True  True  True] -> 1 occurency
-1
Massimo Rebuglio 27 नवम्बर 2021, 11:28