Используйте numpy where в многомерном массиве - PullRequest
0 голосов
/ 27 мая 2020

У меня есть многомерный массив, подобный приведенному ниже, и я пытаюсь удалить строки, заканчивающиеся * (звездочками), чтобы я мог преобразовать его в массив с плавающей запятой.

    array1 = np.column_stack((a, b, c, d)) 
    array1 = np.array([
       ['*0.70*', '21.59', '4.37', '21.70'],
       ['2.15', '21.42', '5.63', '22.33'],
       ['*8.00*', '21.17', '5.11', '22.40'],
       ['2.36', '22.88', '*2.54*', '*20.95*'],
       ['2.07', '22.64', '6.68', '22.26']
       ])

Есть ли у нас способ np.where указать координату в массиве значений, выделенных звездочками, а не только индекс, чтобы я мог удалить всю строку?

Таким образом, идеальный результат будет примерно таким: K

fil1 = np.where(np.char.endswith(array1, "*") == True)

print(fil1) 
(0,0), (0,2), (2, 3), (3, 3)

Ответы [ 3 ]

1 голос
/ 27 мая 2020

np.where возвращает 1 массив на измерение. Если вы хотите узнать индексы строк, содержащих звезды, просто выполните:

starred_rows = np.unique(np.where(np.char.endswith(array1, "*") == True)[0])

Чтобы получить пары индексов, вы можете использовать zip:

np.array(list(zip(*np.where(np.char.endswith(array1, "*") == True))))
0 голосов
/ 27 мая 2020
In [81]: array1 = np.array([ 
    ...:        ['*0.70*', '21.59', '4.37', '21.70'], 
    ...:        ['2.15', '21.42', '5.63', '22.33'], 
    ...:        ['*8.00*', '21.17', '5.11', '22.40'], 
    ...:        ['2.36', '22.88', '*2.54*', '*20.95*'], 
    ...:        ['2.07', '22.64', '6.68', '22.26'] 
    ...:        ])                                                                       

Тест char возвращает логический массив:

In [84]: mask = np.char.endswith(array1,"*")                                             
In [85]: mask                                                                            
Out[85]: 
array([[ True, False, False, False],
       [False, False, False, False],
       [ True, False, False, False],
       [False, False,  True,  True],
       [False, False, False, False]])

np.nonzero (он же np.where) находит координаты значений True, по одному массиву на измерение:

In [86]: np.nonzero(mask)                                                                
Out[86]: (array([0, 2, 3, 3]), array([0, 0, 2, 3]))

Если вы хотите удалить строки, можно использовать первый массив (дубликат 3 явно не беспокоит delete):

In [88]: np.delete(array1, np.nonzero(mask)[0], 0)                                       
Out[88]: 
array([['2.15', '21.42', '5.63', '22.33'],
       ['2.07', '22.64', '6.68', '22.26']], dtype='<U7')

Но мы также можем найти строки с любым True с:

In [89]: mask.any(axis=1)                                                                
Out[89]: array([ True, False,  True,  True, False])

и используйте его для выбора этих строк (логическая индексация массива)

In [91]: array1[mask.any(axis=1)]                                                        
Out[91]: 
array([['*0.70*', '21.59', '4.37', '21.70'],
       ['*8.00*', '21.17', '5.11', '22.40'],
       ['2.36', '22.88', '*2.54*', '*20.95*']], dtype='<U7')

или выберите их not:

In [92]: array1[~mask.any(axis=1)]                                                       
Out[92]: 
array([['2.15', '21.42', '5.63', '22.33'],
       ['2.07', '22.64', '6.68', '22.26']], dtype='<U7')

np.nonzero(Out[89]) - это (array([0, 2, 3]),), желаемые строки удаления.

В других ответах использовалась версия Python списка транспонирования; numpy's собственная транспонирование также работает:

In [93]: np.argwhere(mask)                                                               
Out[93]: 
array([[0, 0],
       [2, 0],
       [3, 2],
       [3, 3]])
In [94]: np.transpose(np.nonzero(mask))                                                  
Out[94]: 
array([[0, 0],
       [2, 0],
       [3, 2],
       [3, 3]])

Для удаления строк это транспонирование не более полезно, чем where.

0 голосов
/ 27 мая 2020

Чтобы получить упомянутый выше идеальный вывод, вам нужно использовать zip

fil1 = list(zip(*np.where(np.char.endswith(array1, "*") == True)))
print(fil1)  
[(0, 0), (2, 0), (3, 2), (3, 3)] //result

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

fil1 = list(set(np.where(np.char.endswith(array1, "*") == True)[0]))
print(fil1)
[0, 2, 3]  // result
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...