Как мне повторно вставить удаленные элементы массива в правильное положение?

#python #arrays #numpy

Вопрос:

Мне нужно повторно вставить ранее удаленные элементы в массив. В данном случае мне нужно минимизировать функцию потерь по набору параметров после исправления их подмножества. Минимизатор принимает только оставшееся незафиксированное подмножество, но мне нужно передать весь набор параметров функции, которая должна быть сведена к минимуму.

Я думал об использовании np.delete с индексом элементов для исключения, а затем использовать np.insert, чтобы отменить его с той же логикой, но следующее НЕ работает, поскольку np.insert и np.delete не симметричны в том, как они работают:

 import numpy as np pars = np.array([0,10,20,30,40,50]) exclude = [1,3] # index of elements to exclude  parsSubset = np.delete(pars,exclude) excludedPars = pars[exclude] parsRecreated = np.insert(parsSubset,exclude,excludedPars) print(parsRecreated)  

вывод такого кода является [ 0 10 20 40 30 50]

Я включаю свое решение ниже, но мне интересно, есть ли более элегантное решение, которого мне не хватает

Комментарии:

1. массивы действительно «ненавидят», когда элементы удаляются … может быть, вам нужен список?

2. Хотя я ненавижу списки 🙂 … проблема здесь в том, что np.delete не работает «последовательно», как np.insert, то есть удаляет все элементы сразу.

3. не повезло. Если вам предлагают решение, но вы решаете, что вам не нравится структура, которую оно использует …

4. как будет выглядеть код со списками?

Ответ №1:

Вот мое решение, создающее маску и использующее ее для повторной вставки:

 import numpy as np pars = np.array([0,10,20,30,40,50]) exclude = [1,3] # index of elements to exclude mask = np.array([True] * pars.size) mask[exclude] = False  parsSubset = pars[mask]  parsRecreated = np.zeros(pars.size) parsRecreated[mask] = parsSubset parsRecreated[~mask] = pars[~mask] print(parsRecreated)  

Ответ №2:

 In [24]: pars = np.array([0,10,20,30,40,50])  ...: exclude = [1,3] # index of elements to exclude  ...:   ...: parsSubset = np.delete(pars,exclude) In [25]: pars Out[25]: array([ 0, 10, 20, 30, 40, 50]) In [26]: parsSubset Out[26]: array([ 0, 20, 40, 50]) In [27]: np.insert(parsSubset,exclude,100) Out[27]: array([ 0, 100, 20, 40, 100, 50])  

delete удаляет эти элементы из pars :

 In [33]: pars[exclude] Out[33]: array([10, 30])  

insert добавляет элементы перед этими элементами в parsSubset :

 In [34]: parsSubset[exclude] Out[34]: array([20, 50])  

insert работает по отношению к текущему массиву, а не к целевому массиву. Внутренне он учитывает , что как только элемент будет вставлен ранее 20 , точка вставки гнезда будет смещена. На самом деле в его коде есть строка

 indices[order]  = np.arange(numnew)  

Мы можем компенсировать это нашим собственным вычитанием:

 In [36]: np.insert(parsSubset,exclude-np.arange(2),100) Out[36]: array([ 0, 100, 20, 100, 40, 50])  

Внутренне delete и insert являются сложными, поскольку они могут работать с различными размерами и различными видами входных данных (скалярными, срезами, последовательностями). Но в таких последовательностях и то, и другое работает с маской так же, как и вы. В вашем решении нет ничего плохого, и, вполне возможно, оно быстрее (без общих накладных расходов).

Комментарии:

1. Спасибо, мне нравится решение np.arange, которое должно обобщать np.arange(len(exclude)) то, что я пропустил. Вы меняете компактность на читабельность, я думаю, напишите мое решение