#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))
то, что я пропустил. Вы меняете компактность на читабельность, я думаю, напишите мое решение