जाँच करें कि एक सुन्न सरणी की अपनी सभी सीमाओं पर 0 है [बंद]


13

यह जांचने का सबसे तेज़ तरीका क्या होगा कि एक बहुआयामी संख्यात्मक सरणी के सभी तरफ 0 हों।

तो, एक सरल 2D उदाहरण के लिए, मेरे पास है:

x = np.random.rand(5, 5)
assert np.sum(x[0:,  0]) == 0
assert np.sum(x[0,  0:]) == 0
assert np.sum(x[0:, -1]) == 0
assert np.sum(x[-1, 0:]) == 0

हालांकि यह 2 डी मामलों के लिए ठीक है, उच्च आयामों के लिए लेखन थोड़ा थकाऊ है और मैं सोच रहा था कि क्या कुछ चतुर सुन्न चाल है जो मैं इसे कुशल बनाने के लिए उपयोग कर सकता हूं और अधिक बनाए रखने योग्य भी।


8
np.all (x[:, 0] == 0)योग से अधिक सुरक्षित नहीं होगा ? योग परीक्षण केवल तभी सही होता है जब सभी संख्याएं सकारात्मक होती हैं।
डेमी-ल्यून


1
@ डेमी-लूम बनाता है। मेरे मामले में, सब कुछ होगा> = 0 लेकिन आपकी टिप्पणी की सराहना की जाती है :)
लुका

1
3 डी मामले में, क्या आपको घन के चेहरे (उनमें से छह) या किनारों (उनमें से 12 हैं) का मतलब है?
Riccardo Bucco

@ रिकाडार्कोबुको हाँ, 6 चेहरे। लेकिन मेरा मुद्दा यह है कि यह 3 से अधिक आयाम जा सकता है।
लुका

जवाबों:


7

यहाँ आप इसे कैसे कर सकते हैं:

assert(all(np.all(np.take(x, index, axis=axis) == 0)
           for axis in range(x.ndim)
           for index in (0, -1)))

np.take "फैंसी" अनुक्रमण के रूप में एक ही बात करता है।


1
@ लुका: प्रलेखन यह स्पष्ट नहीं करता है, लेकिन numpy.takeएक प्रतिलिपि बनाता है। यह एक दृश्य के आधार पर कोड से भी बदतर प्रदर्शन करने का कारण हो सकता है। (यह सुनिश्चित करने के लिए समय की आवश्यकता होगी - NumPy देखने की दक्षता कभी-कभी अजीब होती है।)
user2357112

1
@RiccardoBucco: len(x.shape)अधिक सरल रूप में लिखा जा सकता है x.ndim
user2357112

1
@ user2357112supportsMonica धन्यवाद, मैंने इसे तय किया :)
रिकार्डो

5
इसके अलावा, एक सूची समझ का उपयोग allशॉर्ट-सर्किटिंग से बचाता है। आप जेनरेटर एक्सप्रेशन का उपयोग करने के लिए कोष्ठक को हटा सकते हैं, allजैसे ही सिंगल numpy.allकॉल रिटर्न देता है False
user2357112

1
@ user2357112supportsMonica सच !!
रिकार्डो बुको

5

यहां एक जवाब है कि वास्तव में आपके द्वारा रुचि रखने वाले सरणी के हिस्सों की जांच की जाती है, और पूरे सरणी के आकार का मुखौटा बनाने में समय बर्बाद नहीं होता है। पायथन-स्तरीय लूप है, लेकिन यह छोटा है, सरणी के आकार के बजाय आयामों की संख्या के लिए आनुपातिक है।

def all_borders_zero(array):
    if not array.ndim:
        raise ValueError("0-dimensional arrays not supported")
    for dim in range(array.ndim):
        view = numpy.moveaxis(array, dim, 0)
        if not (view[0] == 0).all():
            return False
        if not (view[-1] == 0).all():
            return False
    return True

क्या ऐसी कोई परिस्थितियां हैं, जिनके not (view[0] == 0).all()समकक्ष नहीं है view[0].any()?
पॉल पैंजर

@PaulPanzer: मुझे लगता है कि view[0].any()यह भी काम करेगा। मैं पूरी तरह से दो विकल्पों में शामिल कास्टिंग और बफरिंग की दक्षता के निहितार्थ के बारे में सुनिश्चित नहीं हूं - view[0].any()सैद्धांतिक रूप से तेजी से लागू किया जा सकता है, लेकिन मैंने पहले अजीब परिणाम देखे हैं, और मुझे पूरी तरह से बफरिंग शामिल नहीं है।
user2357112

मुझे लगता view[0].view(bool).any()है कि उच्च गति समाधान होगा।
पॉल पैंजर

@PaPPanzer: argmaxवास्तव anyमें बूलियन दृश्य को हरा सकता है । यह सामान अजीब हो जाता है।
user2357112

(इसके अलावा, चाहे argmaxया any, एक बूलियन दृश्य का उपयोग करने का मतलब है कि नकारात्मक शून्य को नियमित शून्य के रूप में असमान संभालना।)
user2357112 मोनिका

2

मैंने सरणी को फिर से आकार दिया और फिर इसके माध्यम से पुनरावृत्त किया। दुर्भाग्य से, मेरा उत्तर मानता है कि आपके पास कम से कम तीन आयाम हैं और सामान्य मैट्रिक्स के लिए त्रुटि होगी, आपको 1 और 2 आयामी आकार के सरणियों के लिए एक विशेष खंड जोड़ना होगा। इसके अलावा, यह धीमा होगा इसलिए बेहतर समाधान होने की संभावना है।

x = np.array(
        [
            [
                [0 , 1, 1, 0],
                [0 , 2, 3, 0],
                [0 , 4, 5, 0]
            ],
            [
                [0 , 6, 7, 0],
                [0 , 7, 8, 0],
                [0 , 9, 5, 0]
            ]
        ])

xx = np.array(
        [
            [
                [0 , 0, 0, 0],
                [0 , 2, 3, 0],
                [0 , 0, 0, 0]
            ],
            [
                [0 , 0, 0, 0],
                [0 , 7, 8, 0],
                [0 , 0, 0, 0]
            ]
        ])

def check_edges(x):

    idx = x.shape
    chunk = np.prod(idx[:-2])
    x = x.reshape((chunk*idx[-2], idx[-1]))
    for block in range(chunk):
        z = x[block*idx[-2]:(block+1)*idx[-2], :]
        if not np.all(z[:, 0] == 0):
            return False
        if not np.all(z[:, -1] == 0):
            return False
        if not np.all(z[0, :] == 0):
            return False
        if not np.all(z[-1, :] == 0):
            return False

    return True

जो उत्पादन करेगा

>>> False
>>> True

मूल रूप से मैं एक दूसरे के ऊपर सभी आयामों को ढेर करता हूं और फिर उनके किनारों की जांच करने के लिए उनके माध्यम से देखता हूं।


यह सरणी के गलत हिस्सों की जांच करता है। 3-आयामी सरणी के लिए, हम पूरे सरणी के चेहरों की जांच करना चाहते हैं, न कि प्रत्येक 2-आयामी सबरे के किनारों को।
user2357112

आह, यह अधिक समझ में आता है। मैंने गलत समझा
lilileczek

1

शायद दीर्घवृत्त ऑपरेटर वह है जो आप खोज रहे हैं, जो कई आयामों के लिए काम करेगा:

import numpy as np

# data
x = np.random.rand(2, 5, 5)
x[..., 0:, 0] = 0
x[..., 0, 0:] = 0
x[..., 0:, -1] = 0
x[..., -1, 0:] = 0

test = np.all(
    [
        np.all(x[..., 0:, 0] == 0),
        np.all(x[..., 0, 0:] == 0),
        np.all(x[..., 0:, -1] == 0),
        np.all(x[..., -1, 0:] == 0),
    ]
)

print(test)

इससे सभी चेहरे पर रंग नहीं चढ़ेगा। उदाहरण के लिए, इसे (4, 4, 4) घन के साथ आज़माएँ।
लुका

मुझे यकीन नहीं है कि आप चेहरे को रंगने से क्या मतलब है, लेकिन यह काम करता है अगर आप x (4, 4, 4)
बनाते हैं

1

आप sliceकाम पूरा करने के लिए बूलियन मास्किंग का उपयोग कर सकते हैं :

def get_borders(arr):
    s=tuple(slice(1,i-1) for i in a.shape)
    mask = np.ones(arr.shape, dtype=bool)
    mask[s] = False
    return(arr[mask])

यह फ़ंक्शन पहले सरणी के "कोर" को ट्यूपल में आकार देता है s, और फिर एक मुखौटा बनाता है जो Trueकेवल सीमा बिंदुओं के लिए दिखाता है । बूलियन इंडेक्सिंग तब सीमा बिंदुओं को वितरित करता है।

कार्य उदाहरण:

a = np.arange(16).reshape((4,4))

print(a)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

borders = get_borders(a)
print(borders)
array([ 0,  1,  2,  3,  4,  7,  8, 11, 12, 13, 14, 15])

फिर, np.all(borders==0)आपको वांछित जानकारी देगा।


नोट: यह एक आयामी सरणियों के लिए टूट जाता है, हालांकि मैं उन लोगों को एक किनारे का मामला मानता हूं। आप शायद सवाल में सिर्फ दो बिंदुओं की जाँच कर रहे हैं


यह समय सीमा के बजाय सरणी में तत्वों की कुल संख्या के लिए आनुपातिक लगता है। इसके अलावा, एक आयामी सरणियों एक अप्रासंगिक बढ़त का मामला नहीं हैं।
user2357112

1
इसके अलावा, np.arange(15)15 शामिल नहीं है
user2357112

मैं मानता हूं कि "अप्रासंगिक" एक मजबूत शब्द है, हालांकि मुझे लगता है कि आप 1 डी सरणी के लिए दो संबंधित बिंदुओं की जांच कर रहे हैं। 15 एक टाइपो है, अच्छी पकड़ है
लुकास थेलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.