Подсписки Shift и Zero-Pad вызывают ошибку выполнения оперы/трансляции, которую я не понимаю

Я пытаюсь сделать что-то простое, однако я не понимаю полученную ошибку. Я пробовал гуглить операнды и транслировать (python говорит, что это то, что я делаю, и я делаю это неправильно), но это мне не помогло. Я тоже не смог найти ответ на SO, но, возможно, я использую неправильные условия поиска.

У меня есть список из 64 подсписков, в которых 64 записи. Я хочу создать новый список, в котором каждый подсписок имеет свои записи, перемещенные в одну сторону (вперед или назад, не имеет значения), затем конец обрезается, а начало дополняется нулями, поэтому в нем все еще есть 64 записи. Я думал, что знаю, как это сделать, но мое решение не работает, и я не понимаю ошибки. Пишет, что я веду трансляцию и что я делаю это неправильно. Однако я только что сделал несколько списков (которые предназначены только для циклов, верно?) и соединил их.

Цель:

1 2 3 4 5           1 2 3 4 5
1 2 3 4 5           0 1 2 3 4
1 2 3 4 5  becomes  0 0 1 2 3
1 2 3 4 5           0 0 0 1 2
1 2 3 4 5           0 0 0 0 1

Моя попытка:

result = [ [[0 for hh in range(ii)]+originallist[0][jj][0+ii:] for ii in range(64)] for jj in range(64)]

(дополнительный [0] за исходным списком присутствует, потому что списки, которые я описал выше, сами по себе являются подсписками одного материнского списка, но в этом примере я рассматриваю только один такой список)

Результат:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-51-5261c3ba129a> in <module>()
----> 1 result = [ [[0 for hh in range(ii)]+originallist[0][jj][0+ii:] for ii in range(64)] for jj in range(64)]

<ipython-input-51-5261c3ba129a> in <listcomp>(.0)
----> 1 result = [ [[0 for hh in range(ii)]+originallist[0][jj][0+ii:] for ii in range(64)] for jj in range(64)]

<ipython-input-51-5261c3ba129a> in <listcomp>(.0)
----> 1 result = [ [[0 for hh in range(ii)]+originallist[0][jj][0+ii:] for ii in range(64)] for jj in range(64)]

ValueError: operands could not be broadcast together with shapes (0) (64) 

person Leo    schedule 17.10.2013    source источник
comment
Это не синтаксическая ошибка, это ошибка времени выполнения.   -  person Martijn Pieters    schedule 17.10.2013
comment
Связанный; Операнды Numpy не могли транслироваться вместе с формой   -  person Martijn Pieters    schedule 17.10.2013
comment
Вероятно, я бы не стал делать для этого понимание списка, так как я нахожу это немного сложным для понимания. Я думаю, что создание новой переменной той же формы, что и originallist, а затем выполнение циклов было бы более понятным, хотя, вероятно, есть более умный способ решить проблему.   -  person Jblasco    schedule 17.10.2013
comment
@MartijnPieters Спасибо за исправление и ссылку.   -  person Leo    schedule 17.10.2013


Ответы (3)


Пример без цикла

>>> a = np.arange(1,6)
>>> a
array([1, 2, 3, 4, 5])

Теперь у нас есть все значения, и нам нужно замостить. Возможно, лучше всего использовать np.tile, но здесь мы можем использовать широковещательную передачу для демонстрации.

>>> b = np.ones(5,dtype=np.int)
>>> c = a*b[:,None]    #Broadcasting the two together
>>> c
array([[1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5]])

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

>>> c = c - np.arange(5)[:,None]
>>> c[c<0]=0
>>> c
array([[1, 2, 3, 4, 5],
       [0, 1, 2, 3, 4],
       [0, 0, 1, 2, 3],
       [0, 0, 0, 1, 2],
       [0, 0, 0, 0, 1]])

Это, по общему признанию, ограниченный пример. Если вы можете опубликовать пример originallist, это можно улучшить.

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

>>> range(0)
[]
>>> [] + np.arange(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (0) (3)

Я думаю, вы хотите сделать это:

>>> [] + np.arange(3).tolist()
[0, 1, 2]
person Daniel    schedule 17.10.2013
comment
Ах, так вот что идет не так! Я могу использовать tolist() в своем коде, и, думаю, это сработает. - person Leo; 17.10.2013

следующее должно делать то, что вам нужно?

l1 = [[1,2,3],[4,5,6],[7,8,9]]
l2 = []
for i,l in enumerate(l1):
    t=[]

    for j in range(len(l)):
        if(j<i):
            t.append(0)
        else:
            t.append(l[j-i])
    l2.append(t)
print l2
# gives: [[1, 2, 3], [0, 4, 5], [0, 0, 7]]

что вы хотите сделать, это написать этот материал как oneliner? Лично я предпочитаю, чтобы это выглядело так, так как это показывает, как это работает, в то время как oneliners могут быть понятны вам в тот момент, когда вы их программируете, но если вы оглянетесь на них через месяц, вам придется снова выяснять, как он работает так, что делает то, что вы хотите, а если вы разделите его на несколько строк, это будет гораздо более понятно

person usethedeathstar    schedule 17.10.2013
comment
Да, это то, что я хочу сделать. Спасибо за Ваш ответ. Если не придет ответ, отвечающий на все мои вопросы, я приму ваши. Я тоже надеялся понять, что пошло не так. Мне не обязательно нужен oneliner, просто понимание настолько интуитивное. Я просто говорю, что мне нужен список и пишу в нем то, что я хочу иметь в нем, и все. Не нужно думать ни о чем сложном или делать какие-то лишние переменные. - person Leo; 17.10.2013

Еще одно решение, быстрый однострочный:

>>> l1 = [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
>>> [([0]*pos)+l[:len(l1)-pos] for pos, l in enumerate(l1)]
[[1, 2, 3, 4, 5], [0, 1, 2, 3, 4], [0, 0, 1, 2, 3], [0, 0, 0, 1, 2], [0, 0, 0, 0, 1]]
person barmaley    schedule 17.10.2013
comment
Отлично, я еще не знаю, как использовать for a, b in c с этой запятой. Также рассмотрим enumerate, это позволяет пропустить там слой. Как я это сделал после того, как Ophion показал мне, что я сделал неправильно, было так: result = [ [0 for hh in range(jj)]+np.ndarray.tolist(originallist[0][jj][0+jj:]) for jj in range(64)] Ваше решение короче и легче читается. Хороший! - person Leo; 17.10.2013