Могу ли я увеличить массив, сохранив исходные значения неизменными?

--EDIT: Следуя комментарию Жюльена, я сделал минимальный воспроизводимый пример! Это в конце исходного поста :) --

У меня есть код на Python, который помогает мне найти точки пересечения двух кривых; каждый раз f(frequency) равен одному из тангенсов (или котангенсов). Я сохраняю те значения, которые соответствуют режимам, доступным для данной частоты. Я перебираю несколько частот, чтобы знать, какие моды на каких частотах распространяются.

Для каждой частоты (или пульсации) в моем цикле for я нахожу точки пересечения с помощью программы Intersection, которая возвращает позиции x и y в массиве. Мне нужны только значения x, поэтому я храню их в массиве с именем X_inter. Я сохраняю каждый X_inter в более крупный массив под названием arr_KX для облегчения дальнейших манипуляций.

Следовательно, строки arr_KX соответствуют заданной частоте, а столбцы соответствуют заданному режиму (первый столбец соответствует 0-му режиму и т. д.).

Я не могу знать, какой будет самый большой режим и, следовательно, сколько столбцов должно быть в моем массиве, пока я не завершу цикл if.

Проблема в том, что для более низких частот у меня будет меньше мод, чем для более высоких частот. Как вы можете видеть в следующем коде, когда я попытаюсь изменить размер arr_KX, я потеряю всю предыдущую информацию.

В идеальном случае должно произойти следующее: если первая частота имеет 2 режима, а вторая частота — 4, то arr_KX показывает:

arr_KX = [[mode 1 of f1, mode 2 of f1, nan , nan ] , [ mode 1 of f2, mode 2 of f2, mode 3 of f2, mode 4 of f2]]

Или более читабельно:

arr_KX = [[m1,m2,nan,nan],[m1,m2,m3,m4]]

import numpy as np
import matplotlib.pyplot as plt
import Intersection as inter
np.seterr(all='ignore')
plt.clf()

height, width, lenght = 500e-6, 500e-6, 100e-6 
d = height/2
c0 = 3e8 
n_core = 5.2 
n_cladding = 1.
FntSze = 15 

"""
Solve this equations
"""
def cot(angle):
    return np.cos(angle)/np.sin(angle)

def TE_LHS_sym(var1):
    return np.tan(var1*d)

def TE_LHS_antisym(var2):
    return -cot(var2*d)

def TE_RHS(var3,pulsation_):
    return ((pulsation_**2*d**2*
             (n_core**2-n_cladding**2)/(c0**2*var3**2*d**2))-1)**(0.5)

start, end, Nx, NN = 100e9, 1000e9 + 1, 1001 ,21 
##Start and end of pulsation range, with NN the number of frequencies we work with and Nx the number of kx generated

f_range = np.linspace(start,end,NN)
w_range = f_range*2*np.pi 
k = np.linspace(0,4*np.pi,Nx)/d 

tol = 40. ##To limit the float points at discontinuity of tangents/cotangents

y_tan = TE_LHS_sym(k) ##Draw tan(kx*d)
y_tan[y_tan > tol] = np.nan ##Limits the aberrations at discontinuity
y_tan[y_tan < -tol] = np.nan

y_cot = TE_LHS_antisym(k) ##Draw cot(kx*d)
y_cot[y_cot > tol] = np.nan
y_cot[y_cot < -tol] = np.nan

init=0
size = 0

##PlOTTING
plt.figure(1)
plt.plot(k*d,y_tan,label='tan($k_{x0}d$)' )
plt.plot(k*d,y_cot)#,label='-cot($k_{x0}d$)')

for init,omega in enumerate(w_range): #Loop for pulsations, starting at max and ending at min 
        y_RHS = TE_RHS(k,omega) #Draws RHS, intersaction points with tan/cot will give kx_mode
        y_RHS[y_RHS > tol] = np.nan
        plt.plot(k*d,y_RHS,marker='',label='RHS at $f$ = '+ str(round(omega*1e-9/(2*np.pi),2)) + ' GHz')
       
        ##Find intersection points between tan/cot, they will give kx_mode for a given w
        x_inter_tan,y_inter_tan = inter.intersection(k, y_tan, k, y_RHS)
        x_inter_cot,y_inter_cot = inter.intersection(k, y_cot, k, y_RHS) 
        plt.plot(x_inter_cot*d, y_inter_cot, '+k') ##Draws inter points cot//RHS
        plt.plot(x_inter_tan*d, y_inter_tan, '+k') ##Draws inter points tan//RHS
        
        plt.xlabel("$k_{x}d$ (in $rad.m^{-1}$)",fontsize=FntSze)
        plt.ylabel("",fontsize=FntSze)
        
        X_inter = np.sort(np.concatenate([x_inter_cot.copy(),x_inter_tan.copy()])*d) #Gives kx_m*d for a w
        KX_inter = X_inter/d
        if KX_inter.shape[0] > size :    #In order to know how many columns we need 
            size = KX_inter.shape[0]     
            arr_KX = np.zeros((NN,size)) #Create matrix NN*size == w_n*kx_modes
        bb = KX_inter.resize(size)       #Higher w_m have higher kx_modes, this sets them up in the same shape
        arr_KX[int(init),:] = KX_inter #Matrix w_n*kx_modes appends line at w_n of the kx_modes

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

Я не могу точно вспомнить, что я сделал, поскольку прошли недели с тех пор, как я остановился на своем обходном пути, но я попробовал столько «решений», сколько смог найти в Google. Либо с numpy, либо с базовыми командами Python проблема все равно сохранится или возникнет новая.

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

Итак, я бы:

arr_KX =[[mode1 of f1,mode2 of f1,mode1 of f2,mode2 of 2],[mode3 of f2, mode 4 of f2, nan, nan]]

РЕДАКТИРОВАТЬ Вот минимальный воспроизводимый пример:

import numpy as np
from numpy.random import default_rng

NN = [2,2,4,6,6]
size = 0
init = 0
for n in NN:
    KX_inter = default_rng().random((n)) #shape (n,)
    print(KX_inter)
    if KX_inter.shape[0] > size :
        size = KX_inter.shape[0]          #In order to know how many columns we need 
        arr_KX = np.zeros((len(NN),size)) #Create matrix Nx*size == w_n*kx_modes
    bb = KX_inter.resize(size)            #Higher w_m have higher kx_modes, this sets them up in the same shape
    arr_KX[int(init),:] = KX_inter
    
    init = init + 1
print(arr_KX)

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

Столько слов, а я так и не понял проблемы. Пожалуйста, отбросьте ненужное и перейдите к сути с помощью упрощенного минимально воспроизводимого примера.

Julien 23.04.2024 12:10

Не совсем разбираясь в проблеме, я предполагаю, что если вы не знаете размер массива, numpy aray, вероятно, не является правильной структурой, и вы, возможно, захотите придерживаться собственных списков?

Julien 23.04.2024 12:13

Вы действительно не хотите пытаться расширять существующие массивы numpy, вы можете просмотреть этот ТАК-вопрос/ответ, который описывает его более подробно. Не используйте массивы numpy, если вы хотите продолжать расширять/изменять их размер.

Karan Shishoo 23.04.2024 12:18

@Julien Я добавил минимальный воспроизводимый пример, так легче понять? Кроме того, я не могу использовать собственный список, потому что у меня возникла проблема, о которой я упоминаю в конце исходного сообщения.

Óscar 23.04.2024 14:12

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

Óscar 23.04.2024 14:16

Вы можете создать структуру данных, используя списки, а затем преобразовать ее в массив numpy, поскольку в этот момент вы будете знать размер.

John Coleman 23.04.2024 15:24

Спасибо @JohnColeman за ваш ответ. Знаешь, как я мог бы продолжать это делать? Я не очень хорошо владею Python, и в последний раз, когда я пытался использовать списки, у меня возникла проблема, которую я описал в конце моего исходного поста.

Óscar 23.04.2024 16:03

Где ты это описываешь? Я не вижу упоминания о списках в вопросе. Обязательно избегайте этой проблемы

Barmar 23.04.2024 17:27

Большое спасибо @Barmar! Завтра утром я обновлю исходный вопрос, я нашел способ сделать то, что пытался сделать в конце концов. Я использовал списки, чтобы решить эту проблему, jeje

Óscar 23.04.2024 18:03

После обновления вопроса опубликуйте решение в ответе ниже, а не в вопросе.

Barmar 23.04.2024 18:05

Готово @Barmar, надеюсь, я сделал это правильно. Спасибо еще раз за помощь!

Óscar 25.04.2024 18:58
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
11
107
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы решить эту проблему, мне пришлось сделать циклы. Исходный вариант, в котором я нахожу точки пересечения, но на этот раз я добавляю их в пустой список, а не в массив. Я также ищу самый длинный размер своих отдельных списков.

    X_inter = np.sort(np.concatenate([x_inter_cot.copy(),x_inter_tan.copy()])*d) 
    KX_inter_ = X_inter/d
    
    KX_inter = list(KX_inter_)
    KX_list.append(KX_inter)
    if len(KX_inter) > size:
        size = len(KX_inter)

Теперь, когда они сгруппированы внутри «KX_list», я запускаю еще один цикл, чтобы добавить необходимый «np.nan» в каждый отдельный список. Затем я конвертирую их в np.array.

i = 0
for r in KX_list:
    s = len(r)
    arr0 = [ np.nan for _ in range (size-s)]
    KX_list[i].extend(arr0)
    i += 1
arr_KX = np.array(KX_list)

Вот простой пример, который можно попробовать на своих консолях:

fruit = [[1,2],[2,3,3,4,2],[1,2,3]]
size = 0
for r in fruit :
    if size < len(r):
        size = len(r)
it = 0
for r in fruit :
    s = len(r)
    arr0 = [np.nan]*(size-s)
    print(arr0)
    fruit[it].extend(arr0)
    it = it+1
arr_fruit = np.array(fruit)
print(arr_fruit)

Другие вопросы по теме