2015-01-24 8 views
0

У меня есть довольно большой 3-мерный массив numpy (2000,2500,32), который мне нужно манипулировать. Некоторые строки плохо, поэтому мне нужно будет удалить несколько строк. Для того, чтобы определить, какие строки «плохо» Я с помощью следующей функцииУдаление строк из многомерного массива numpy

def badDetect(x): 
    for i in xrange(10,19): 
    ptp = np.ptp(x[i*100:(i+1)*100]) 
    if ptp < 0.01: 
     return True 
    return False 

, который отмечает, как плохо любую последовательность 2000, которая имеет диапазон значений 100 с пика до пикового значения меньше, чем 0,01. Если это так, я хочу удалить эту последовательность из 2000 значений (которые могут быть выбраны из numpy с помощью [:, x, y]) Удаление Numpy, кажется, принимает индексы, но только для 2-мерных массивов.

+0

Просьба уточнить: каков критерий для этих строк считаться плохим? Также «строки» в трехмерном контексте не имеют большого смысла. Вы имеете в виду последнюю ось, поэтому «строки» из 32 элементов? –

+0

Я добавил функцию для обнаружения «плохой», а также уточнил, что я имею в виду строки из 2000 значений. Спасибо заранее за ваш интерес! – tix3

+0

Информация, которую вы добавили о том, что должна делать ваша программа, не соответствует фактическому алгоритму: 'x [i * 100: (i + 1) * 100]' будет принимать (для первой итерации 'i') значения 'x [1000: 1100]'. Поэтому он даже не начинается с нуля. Вы уверены, что это было у вас в голове? –

ответ

0

Вам обязательно нужно будет изменить свой входной массив, потому что вырезание «строк» ​​из 3D-куба оставляет структуру, которая не может быть правильно решена.

Как у нас нет данных, я буду использовать другой пример первым, чтобы объяснить, как это работает возможное решение:

>>> import numpy as np 
>>> from numpy.lib.stride_tricks import as_strided 
>>> 
>>> threshold = 18 
>>> a = np.arange(5*3*2).reshape(5,3,2) # your dataset of 2000x2500x32 
>>> # Taint the data: 
... a[0,0,0] = 5 
>>> a[a==22]=20 
>>> print(a) 
[[[ 5 1] 
    [ 2 3] 
    [ 4 5]] 

[[ 6 7] 
    [ 8 9] 
    [10 11]] 

[[12 13] 
    [14 15] 
    [16 17]] 

[[18 19] 
    [20 21] 
    [20 23]] 

[[24 25] 
    [26 27] 
    [28 29]]] 
>>> a2 = a.reshape(-1, np.prod(a.shape[1:])) 
>>> print(a2) # Will prove to be much easier to work with! 
[[ 5 1 2 3 4 5] 
[ 6 7 8 9 10 11] 
[12 13 14 15 16 17] 
[18 19 20 21 20 23] 
[24 25 26 27 28 29]] 

Как вы можете видеть, из приведенного выше представления, то это уже становится намного теперь яснее, из каких окон вы хотите вычислить пиковое значение. И вам понадобится эта форма, если вы собираетесь удалить «строки» (теперь они были преобразованы в столбцы) из этой структуры данных, чего вы не могли бы сделать в трех измерениях!

>>> isize = a.itemsize # More generic, in case you have another dtype 
>>> slice_size = 4 # How big each continuous slice is over which the Peak2Peak value is calculated 
>>> slices = as_strided(a2, 
...  shape=(a2.shape[0] + 1 - slice_size, slice_size, a2.shape[1]), 
...  strides=(isize*a2.shape[1], isize*a2.shape[1], isize)) 
>>> print(slices) 
[[[ 5 1 2 3 4 5] 
    [ 6 7 8 9 10 11] 
    [12 13 14 15 16 17] 
    [18 19 20 21 20 23]] 

[[ 6 7 8 9 10 11] 
    [12 13 14 15 16 17] 
    [18 19 20 21 20 23] 
    [24 25 26 27 28 29]]] 

Так я принял, в качестве примера, размер окна из 4-х элементов: Если пик с пиковым значением в пределах любого из этих кусочков 4 элементов (в набор данных, так что каждый столбец) меньше определенный порог, Я хочу исключить его. Это можно сделать следующим образом:

>>> mask = np.all(slices.ptp(axis=1) >= threshold, axis=0) # These are the ones that are of interest 
>>> print(a2[:,mask]) 
[[ 1 2 3 5] 
[ 7 8 9 11] 
[13 14 15 17] 
[19 20 21 23] 
[25 26 27 29]] 

Теперь вы можете ясно видеть, что испорченные данные были удалены. Но помните, вы не могли просто удалить эти данные из 3D-массива (но тогда вы могли бы замаскировать его).

Очевидно, что вы должны будете установить threshold к .01 в вашем сценарии использования, и slice_size к 100.

Опасайтесь, в то время как форма as_strided является чрезвычайно эффективной с точки зрения памяти, вычисляя пиковые значения этого массива и сохраняя этот результат, требующий достаточного объема памяти в вашем случае: 1901x (2500x32) в сценарии полного случая, поэтому, когда вы не игнорируете первые 1000 ломтиков. В вашем случае, когда вы заинтересованы только в срезах от 1000:1900, вы бы добавить, что в коде следующим образом:

mask = np.all(slices[1000:1900,:,:].ptp(axis=1) >= threshold, axis=0) 

И что бы уменьшить объем памяти, необходимый для хранения этой маски «только» 900x (2500x32) (любого типа данных, который вы использовали).

Смежные вопросы