Функция Numpy для поиска индексов для перекрывающихся векторов

#python #numpy

#python #numpy

Вопрос:

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

Проблема лучше всего описывается простым кодом (ниже). У меня есть два набора данных (x1, y1) и (x2, y2), где каждый x и y — это сотни элементов. Мне нужно усечь их все, чтобы домены были одинаковыми (т.Е. x1 = x2), а y1 представляет соответствующий диапазон для перехода к новому x1, y2 также усекается для перехода к новому x2.

 # x1 and y1 are abscissa and ordinate from some measurement.
x1 = array([1,2,3,4,5,6,7,8,9,10])
y1 = x1**2 # I'm just making some numbers for the ordinate.

# x2 and y2 are abscissa and ordinate from a different measurement, 
# but not over the same exact range.
x2 = array([5,6,7,8,9,10,11,12,13])
y2 = sqrt(x2) # And some more numbers that aren't the same.

# And I need to do some math on just the portion where the two measurements overlap.
x3 = array([5,6,7,8,9,10])
y3 = y1[4:10]   y2[:6]

# Is there a simple function that would give me these indices, 
# or do I have to do loops and compare values?
print x1[4:10]
print x2[:6]


# ------------ THE FOLLOWING IS WHAT I WANT TO REPLACE -------------


# Doing loops is really clumsy...

# Check which vector starts lower.
if x1[0] <= x2[0]:
    # Loop through it until you find an index that matches the start of the other.
    for i in range(len(x1)):
        # Here is is.
        if x1[i] == x2[0]:
            # Note the offsets for the new starts of both vectors.
            x1off = i
            x2off = 0
            break
else:
    for i in range(len(x2)):
        if x2[i] == x1[0]:
            x1off = 0
            x2off = i
            break

# Cutoff the beginnings of the vectors as appropriate.
x1 = x1[x1off:]
y1 = y1[x1off:]
x2 = x2[x2off:]
y2 = y2[x2off:]

# Now make the lengths of the vectors be the same.
# See which is longer.
if len(x1) > len(x2):
    # Cut off the longer one to be the same length as the shorter.
    x1 = x1[:len(x2)]
    y1 = y1[:len(x2)]
elif len(x2) > len(x1):
    x2 = x2[:len(x1)]
    y2 = y2[:len(x1)]

# OK, now the domains and ranges for the two (x,y) sets are identical.    
print x1, y1
print x2, y2
  

Спасибо!

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

1. numpy.in1d(x1,x2) ? я не уверен, о чем вы спрашиваете или как эти вещи перекрываются? но этот код даст вам [5,6,7,8,9,10]

2. Это дает мне вектор True и False. Затем мне нужно вернуться к первому вектору, чтобы найти первое значение true и установить его в качестве моего смещения, а затем найти то же самое место во втором векторе.

3. ошибка см. Ответ (это, вероятно, лучшее решение)… Я думаю, это было бы x1[numpy.in1d(x1,x2)]

4. В вашем примере y3 не зависит от y1 or y2 , так зачем вам нужны подмножества y1 and y2 ? Или это y3 = x1[4:10]**2 sqrt(x2[:6]) действительно должно быть что-то вроде y3 = y1[4:10]**2 sqrt(y2[:6]) ?

5. Если быть точным, x1 и x2 — это температуры. y1 и y2 — это значения, измеренные при этих температурах. Мне нужно добавить y1 к y2, где температуры одинаковы. Я обновлю пример, чтобы было понятнее.

Ответ №1:

Для простого пересечения вы можете использовать np.intersect1d :

 In [20]: x1 = array([1,2,3,4,5,6,7,8,9,10])

In [21]: x2 = array([5,6,7,8,9,10,11,12,13])

In [22]: x3 = np.intersect1d(x1, x2)

In [23]: x3
Out[23]: array([ 5,  6,  7,  8,  9, 10])
  

Но, похоже, вам нужно что-то другое. Как предложил @JoranBeasley в комментарии, вы можете использовать np.in1d , но вам нужно использовать его дважды:

Вот данные:

 In [57]: x1
Out[57]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

In [58]: y1
Out[58]: array([  1,   4,   9,  16,  25,  36,  49,  64,  81, 100])

In [59]: x2
Out[59]: array([ 5,  6,  7,  8,  9, 10, 11, 12, 13])

In [60]: y2
Out[60]: 
array([ 2.23606798,  2.44948974,  2.64575131,  2.82842712,  3.        ,
        3.16227766,  3.31662479,  3.46410162,  3.60555128])
  

Получить подмножество данных (x1, y1):

 In [61]: mask1 = np.in1d(x1, x2)

In [62]: xx1 = x1[mask1]

In [63]: yy1 = y1[mask1]

In [64]: xx1, yy1
Out[64]: (array([ 5,  6,  7,  8,  9, 10]), array([ 25,  36,  49,  64,  81, 100]))
  

Получите подмножество данных (x2, y2). Обратите внимание, что порядок аргументов np.in1d теперь x2, x1 :

 In [65]: mask2 = np.in1d(x2, x1)

In [66]: xx2 = x2[mask2]

In [67]: yy2 = y2[mask2]

In [68]: xx2, yy2
Out[68]: 
(array([ 5,  6,  7,  8,  9, 10]),
 array([ 2.23606798,  2.44948974,  2.64575131,  2.82842712,  3.        ,
         3.16227766]))
  

Нам действительно не нужно было формировать xx2 , потому что это будет то же самое, что xx1 . Теперь мы можем работать с yy1 и yy2 . Например.:

 In [69]: yy1   yy2
Out[69]: 
array([  27.23606798,   38.44948974,   51.64575131,   66.82842712,
         84.        ,  103.16227766])
  

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

1. Не совсем. Он устанавливает диапазон для двух x-векторов одинаковым, но он не дает мне того же для y-векторов, которые идут с ним. Я добавил циклы в вопрос, чтобы сделать это более явным.

2. Замечательно! Спасибо!