Как индексировать внутри массива в python для цикла?

#python #numpy #for-loop #variables

#python #numpy #для цикла #переменные

Вопрос:

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

У меня есть два массива:

     S = [[4.21287783e-03 7.83625813e-03 1.42038926e-02 ... 3.15416197e-03
      1.37110355e-03 9.45473448e-04]
     [1.94774282e-03 1.36746081e-03 1.23485391e-03 ... 6.21054272e-04
      5.31808587e-04 1.78796272e-04]
     [1.20601337e-03 2.81822793e-04 6.32125664e-04 ... 2.72966598e-04
      3.88162201e-04 1.89432902e-04]
     ...
     [7.39537451e-05 1.20665168e-04 1.54863119e-04 ... 3.05247233e-04
      2.26473099e-04 1.56650857e-04]
     [9.29507556e-05 6.45091024e-05 9.84829924e-05 ... 3.07827294e-04
      2.33815251e-04 1.52187484e-04]
     [4.66322444e-05 3.16681323e-05 7.08467828e-05 ... 1.44890351e-04
      7.91870831e-05 5.80408583e-05]]

    frames = [ 1  2  3  4  5  6  7  8  9 ]
 

Я перебираю свой массив фреймов, но хочу итеративно выполнить вычисление для одного значения (индексируемого с помощью i) из массива S:

     for i in frames:
          np.log(S[:,i])
 

Но я получаю ошибку out-of-bounds (‘индекс 9 выходит за пределы оси 1 с размером 9’), потому что я индексирую до конца кадров. Я пытался:

     np.log(S[:,(i-1)])
 

что не сработало — либо потому, что мой синтаксис неправильный, либо моя логика неправильная.

Я также пробовал:

       for i in frames:
          i=i-1
          np.log(S[:,i])
 

И получите ту же ошибку out of bounds.

РЕДАКТИРОВАТЬ: я уверен, что могу вызвать S таким образом, потому что я делаю это в другом месте скрипта (и могу заменить любое целое число для i и запуска скрипта). Моя логика использования i в качестве индекса неверна.

Ответ №1:

С двумя списками, которые вы определяете (вы пишете о arrays том, но копирование-вставка вашего кода создает списки):

 In [30]: S = [23, 23.3, 34.2, 235, 23.1, 32.1, 23, 75, 4] 
    ...: frames = [1, 2, 3, 4, 5, 6, 7, 8, 9]                                        
In [31]: for i in frames: 
    ...:     print(S[:,i]) 
    ...:                                                                             
TypeError: list indices must be integers or slices, not tuple
 

Вы не можете использовать [:,i] индексацию со списками.

 In [32]: for i in frames: 
    ...:     print(S[i]) 
    ..:                                                                             
23.3
34.2
235
23.1
32.1
23
75
4
---------------------------------------------------------------------------
IndexError: list index out of range
 

При frames этом вы пропускаете первый элемент S и получаете ошибку с последним индексом. Индексация Python начинается с 0!

Даже если я создам массив numpy, ваша индексация будет неправильной:

 In [33]: arr = np.array(S)                                                           
In [34]: for i in frames: 
    ...:     print(arr[:,i]) 
    ...:                                                                             

IndexError: too many indices for array
 

arr равно 1d, shape (9,) . Вы не можете использовать [:,i]` с этим.

Вы хотите выбрать часть S (или arr ), например, первые 3 элемента?

 In [36]: arr[:3]                                                                     
Out[36]: array([23. , 23.3, 34.2])
In [37]: np.log(arr[:3])                                                             
Out[37]: array([3.13549422, 3.14845336, 3.53222564])
 

[:3] индексы a slice (как для списка, так и для массивов)

Если массив 2d, то вы можете использовать [:,i] обозначение:

 In [38]: A = arr.reshape(3,3)                                                        
In [39]: A                                                                           
Out[39]: 
array([[ 23. ,  23.3,  34.2],
       [235. ,  23.1,  32.1],
       [ 23. ,  75. ,   4. ]])
In [40]: A[:,0]                       # first column                                               
Out[40]: array([ 23., 235.,  23.])
 

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

1. Спасибо, что нашли время, чтобы пройти через это. Я действительно неправильно идентифицировал структуру данных (теперь отредактировано). И я уточнил: я хочу получить журнал только одного элемента S (проиндексированного с помощью i). Как мне избежать ошибки out of bounds?

2. Обычно индекс i создается в пределах границ. Если S имеет форму (n,) ( n элементы), frame будет все или некоторое подмножество [0...8] . Это то, что range(n) np.arange(n) делает or. Другими словами, frame создается с полным знанием массива, который он будет индексировать. Если элемент frame слишком велик, вы должны решить, что это значит — это ошибка, вы обрезаете его на максимально допустимом уровне, или он обтекается, или какая-то другая магия?

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

Ответ №2:

Вы можете удалить «9» в массиве кадров, и вы увидите результат, как показано ниже:

 23.3
34.2
235
23.1
32.1
23
75
4
 

Итак, теперь вы знаете, что индекс массива начинается с 0, а не с 1.
если вы хотите это исправить, вам нужно заменить массив frames:

 frames = [0, 1, 2, 3, 4, 5, 6, 7, 8]
 

Ответ №3:

У вас есть лишняя запятая.

Попробуйте это:

 for i in frames:
      np.log(S[:i])
 

Мой тест:

 $ python3
Python 3.7.2  (default, Feb 27 2019, 15:41:59) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> S = [23, 23.3, 34.2, 235, 23.1, 32.1, 23, 75, 4]
>>> frames = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for i in frames:
...     print(S[:i])
... 
[23]
[23, 23.3]
[23, 23.3, 34.2]
[23, 23.3, 34.2, 235]
[23, 23.3, 34.2, 235, 23.1]
[23, 23.3, 34.2, 235, 23.1, 32.1]
[23, 23.3, 34.2, 235, 23.1, 32.1, 23]
[23, 23.3, 34.2, 235, 23.1, 32.1, 23, 75]
[23, 23.3, 34.2, 235, 23.1, 32.1, 23, 75, 4]
>>> 
 

Ответ №4:

Лично я думаю, что вам не нужно использовать frames для индексации S . Вы можете попробовать этот способ:

 for i in range(S.shape[0])
    np.log(S[i])
 

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

1. ‘frames’ — это просто псевдомассив. Фактические «фреймы» представляют собой гораздо более сложный массив, составленный из переменных, определенных в другом месте скрипта. Так что, к сожалению, это не так просто, как просто посмотреть на длину S.

2. S.shape По сути, (9, ) вы используете S[:,i] (2d index) для индексации 1d массива . Я думаю, это неправильно.

3. Я не знаю, что вы имеете в виду под определенной частью массива S. Потому что, если S — это список, его часть легко вывести S . Например, первая-третья часть S S[0:3] , по крайней мере, без точки «,» .

4. Это не список, это 2D-массив.