2017-01-27 2 views
2

У меня есть одномерный массив или список, содержащий целые числа, например. x = [0, 2, 4, 7, 8, 12, 15, 23, 28, 39].Функция, которая находит различие между элементами 1D массива/списка, например. x [n] -x [n-1], x [n-2] -x [n-1], где n - размер массива/списка

Я хочу иметь функцию, которая выполняет следующее: Возвращает список/массив, хранящий

x[9]-x[8], x[8]-x[7], x[7]-x[6], ......., x[1]-x[0] 

В этом примере я должен получить список/массив дает [11, 5, 8, 3, 4 , 1, 3, 2, 2].

мне нужна эта функция, выполняемая в цикле в то время, когда для каждого цикла размер списка/массива x растет 1.

Как сделать это в Python или Numpy?

В отличие от this other question, этот вопрос ищет разницу между элементами от конца списка/массива до начала: этот вопрос математически отличается от другого вопроса.

+0

Возможный дубликат [Python - Различия между элементами списка] (http://stackoverflow.com/questions/2400840/python-differences-between-elements-of- a-list) –

ответ

3
In [1084]: x = [0, 2, 4, 7, 8, 12, 15, 23, 28, 39] 

numpy.diff делает этот вид различия легко

In [1085]: np.diff(x) 
Out[1085]: array([ 2, 2, 3, 1, 4, 3, 8, 5, 11]) 

заказ неправильно, но может быть легко изменен с [::-1] (который работает со списками и массивами):

In [1086]: np.diff(x)[::-1] 
Out[1086]: array([11, 5, 8, 3, 4, 1, 3, 2, 2]) 
In [1087]: np.diff(x[::-1]) 
Out[1087]: array([-11, -5, -8, -3, -4, -1, -3, -2, -2]) 

Вы упоминаете делая этот расчет при добавлении в список. Давайте попробуем, что строить новый список, итеративно из x:

In [1088]: y=[]; dy=[] 
In [1089]: for i in x: 
     ...:  if y: # not empty 
     ...:   dy.insert(0, i-y[-1]) 
     ...:  y.append(i) 

In [1090]: y 
Out[1090]: [0, 2, 4, 7, 8, 12, 15, 23, 28, 39] 
In [1091]: dy 
Out[1091]: [11, 5, 8, 3, 4, 1, 3, 2, 2] 

Список Append быстрее, чем массив конкатенации (np.append всего лишь прикрытие для этого). Поэтому, если вы уже делаете цикл, имеет смысл придерживаться списков.

Один из нескольких способов сделать разницу со списками:

In [1093]: [i-j for i,j in zip(x[1:],x[:-1])] 
Out[1093]: [2, 2, 3, 1, 4, 3, 8, 5, 11] 

Это проще добавить разворот списка после, а не выяснить, как переписать zip условия.

np.diff(a) просто:

In [1094]: xa=np.array(x) 
In [1095]: xa[1:]-xa[:-1] 
Out[1095]: array([ 2, 2, 3, 1, 4, 3, 8, 5, 11]) 
+0

Спасибо, что предоставили очень полный ответ. :) Я принял это как ответ на мой вопрос, поскольку общие методы являются краткими, всеобъемлющими и хорошо объясненными. Благодарим за упоминание разницы между list.append и конкатенацией массива. Для полноты и для людей, которые не знакомы с numpy, я добавляю здесь, что решение numpy легко преобразуется обратно в список python, добавляя '.tolist()' в конец массива numpy. –

2

Вы должны применить функцию diff к перевернутому списку и изменить знак.

import numpy as np 

x = [0, 2, 4, 7, 8, 12, 15, 23, 28, 39] 
y = np.asarray(x) 
z = -np.diff(y[::-1]) 
print(z) 

Выход:

[11 5 8 3 4 1 3 2 2] 
+1

Упрощение: 'np.diff (x) [:: - 1]' или напрямую: '(x [1:] - x [: - 1]) [:: - 1]' – Benjamin

+0

@Benjamin Ваше первое уравнение работает, а второе привело к этой ошибке 'TypeError: неподдерживаемый тип операндов для -: 'list' и 'list'.' –

+0

Спасибо, что поделились вашим подходом. :) –

0

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

from itertools import islice 

def window(seq, n=2): 
    "Returns a sliding window (of width n) over data from the iterable" 
    " s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...     " 
    it = iter(seq) 
    result = tuple(islice(it, n)) 
    if len(result) == n: 
     yield result  
    for elem in it: 
     result = result[1:] + (elem,) 
     yield result 

def sliding_differences(l): 
    for a, b in window(reversed(l)): 
     yield a-b 

x = [0, 2, 4, 7, 8, 12, 15, 23, 28, 39] 
print(list(sliding_differences(x))) 

Выходы:

[11, 5, 8, 3, 4, 1, 3, 2, 2] 
+0

Спасибо, что нашли время, чтобы поделиться своим подходом. :) –

3

с использованием срезов обозначения с нормальным списком

>>> x = [0, 2, 4, 7, 8, 12, 15, 23, 28, 39] 
>>> [ a-b for a,b in zip(x[::-1],x[-2::-1]) ] 
[11, 5, 8, 3, 4, 1, 3, 2, 2] 
>>> 

, чтобы избежать ненужных копий, функции, которые дают пары могут быть сделаны, чтобы помочь этому

>>> def pairwise(iterable): 
     it = iter(iterable) 
     a = next(it) 
     for b in it: 
      yield a,b 
      a = b 


>>> [ a-b for a,b in pairwise(reversed(x))] 
[11, 5, 8, 3, 4, 1, 3, 2, 2] 
>>> 
+0

Спасибо, что поделились этим питоническим подходом. :) –

1

Использование numpy, yo у может сделать что-то вроде этого:

def f(x): 
    x = np.array(x) 
    y = np.copy(x) 
    return y[:-1] - x[1:] 

В этой функции вы преобразовать список й в Numpy массива, а затем скопировать этот массив у. y[:-1] - это весь массив, исключающий последний элемент, а x[1:] - это весь массив, исключающий первый элемент. Вычитание этих двух массивов даст желаемый результат.

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

+0

Спасибо, что поделились своим подходом. :) –

Смежные вопросы