Извлечение нескольких подматриц в Python
Я пытаюсь извлечь несколько подматриц, если моя разреженная матрица имеет несколько областей ненулевых значений.
например, Скажем, у меня есть следующая матрица:
x = np.array([0,0,0,0,0,0],
[0,1,1,0,0,0],
[0,1,1,0,0,1],
[0,0,0,0,1,1],
[0,0,0,0,1,0])
тогда мне нужно иметь возможность извлекать области с ненулевыми значениями, т. е.
x_1 = [[1,1]
[1,1]]
и
x_2 = [[0,1],
[1,1],
[1,0]]
Я использую np.где () найти индексы ненулевых значений и вернуть область только для одной подматрицы, но как я могу распространить это на все возможные субрегионы в моей разреженной матрице?
спасибо!
2 ответов
процедура:
- удалить ведущие и конечные строки и столбцы со всеми нулями. (Не средние)
- найти все пустые строки и столбцы и разделить матрицу на эти индексы. Это создает список матриц
- для каждой вновь созданной матрицы повторите процедуру рекурсивно до тех пор, пока дальнейшее расщепление не станет возможным
код:
def delrc(arr):
while True: # delete leading rows with all zeros
if np.all(arr[0]==0):
arr=np.delete(arr,0,axis=0)
else: break
while True: # delete trailing rows with all zeros
if np.all(arr[-1]==0):
arr=np.delete(arr,-1,axis=0)
else: break
while True: # delete leading cols with all zeros
if np.all(arr[:,0]==0):
arr=np.delete(arr,0,axis=1)
else: break
while True: # delete trailing cols with all zeros
if np.all(arr[:,-1]==0):
arr=np.delete(arr,-1,axis=1)
else: break
return arr
def rcsplit(arr):
if np.all(arr==0): return [] # if all zeros return
global res
arr = delrc(arr) # delete leading/trailing rows/cols with all zeros
print arr
indr = np.where(np.all(arr==0,axis=1))[0]
indc = np.where(np.all(arr==0,axis=0))[0]
if not indr and not indc: # If no further split possible return
res.append(arr)
return
arr=np.delete(arr,indr,axis=0) #delete empty rows in between non empty rows
arr=np.delete(arr,indc,axis=1) #delete empty cols in between non empty cols
arr=np.split(arr,indc,axis=1) # split on empty (all zeros) cols
print arr
arr2=[]
for i in arr:
z=delrc(i)
arr2.extend(np.split(z,indr,axis=0)) # split on empty (all zeros) rows
for i in arr2:
rcsplit(np.array(i)) # recursive split again no further splitting is possible
if __name__=="__main__":
import numpy as np
res = []
arr = np.array([[0,0,0,0,0,0],
[0,1,1,0,0,0],
[0,1,1,0,0,1],
[0,0,0,0,1,1],
[0,0,0,0,1,0]])
rcsplit(arr)
for i in res: print i
для этого можно использовать встроенные модули.
from scipy.ndimage.measurements import find_objects, label
from scipy.ndimage import generate_binary_structure as gbs
import numpy as np
# create array
x = np.array([[0,0,0,0,0,0],
[0,1,1,0,0,0],
[0,1,1,0,0,1],
[0,0,0,0,1,1],
[0,0,0,0,1,0]])
# define labeling structure to inlcude adjacent (including diagonal) cells
struc = gbs(2,2)
# generate array of labeled sections labels
x2, numlabels = label(x,struc)
# pull out first group of "ones"
xy1 = find_objects(x2==1)[0]
# pull out second group of "ones"
xy2 = find_objects(x2==2)[0]
теперь тест:
>>> x[xy1]
array([[1, 1],
[1, 1]])
>>> x[xy2]
array([[0, 1],
[1, 1],
[1, 0]])
вуаля! Если вы хотите вытащить все подразделы, вы можете перебирать их, что говорит вам, сколько разных групп у вас есть в массиве.