FInd все пересечения xy графика точек данных с numpy?

Я анализирую данные по циклическим испытаниям на растяжение. В качестве входных данных используются огромные списки значений x и y. Чтобы описать, если материал затвердевает или смягчается, мне нужно получить синий наклон каждого цикла цикла.

Тест на растяжку

скат

Получение нижней точки склона – детский фестиваль, но верхний – вот вызов.

соревнование

Я сделал этот подход до сих пор, вырезая петли с несколькими точками ниже локального максимума каждого цикла и делая красные линии из жесткого количества точек. Апроксимация красных линий производится poly1d(polyfit(x1,x2,1)) а fsolve используется для получения точки пересечения. Однако он работает не всегда правильно, потому что распределение точек не всегда одинаково.

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

Желаемый вывод – это список с приблизительными координатами точек пересечения – если вы хотите играть, вот данные для кривой (0, [[xvals], [yvals]]). Тез можно легко прочитать с помощью

 import csv import sys csv. field_size_limit(sys.maxsize) csvfile = 'data.csv' tc_data = {} for key, val in csv.reader(open(csvfile, "r")): tc_data[key] = val for key in tc_data: tc = eval(tc_data[key]) x = tc[0] y = tc[1] 

2 Solutions collect form web for “FInd все пересечения xy графика точек данных с numpy?”

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

Я собираюсь сделать себе легкие данные, кусочек вытянутой циклоиды , и я собираюсь найти места, где координата y-координат меняется от возрастающего к уменьшению аналогично здесь :

 a, b = 1, 2 phi = np.linspace(3, 10, 100) x = a*phi - b*np.sin(phi) y = a - b*np.cos(phi) y_growth_flips = np.where(np.diff(np.diff(y) > 0))[0] + 1 plt.plot(x, y, 'rx') plt.plot(x[y_growth_flips], y[y_growth_flips], 'bo') plt.axis([2, 12, -1.5, 3.5]) plt.show() 

введите описание изображения здесь

Если у вас есть два сегмента, один из которых находится от точки P0 до P1 , а другой – от точки Q0 до Q1 , вы можете найти их точку пересечения, решая векторное уравнение P0 + s*(P1-P0) = Q0 + t*(Q1-Q0) , и оба сегмента действительно пересекаются, если оба s и t находятся в [0, 1] . Попробуйте это для всех сегментов:

 x_down = x[y_growth_flips[0]:y_growth_flips[1]+1] y_down = y[y_growth_flips[0]:y_growth_flips[1]+1] x_up = x[y_growth_flips[1]:y_growth_flips[2]+1] y_up = y[y_growth_flips[1]:y_growth_flips[2]+1] def find_intersect(x_down, y_down, x_up, y_up): for j in xrange(len(x_down)-1): p0 = np.array([x_down[j], y_down[j]]) p1 = np.array([x_down[j+1], y_down[j+1]]) for k in xrange(len(x_up)-1): q0 = np.array([x_up[k], y_up[k]]) q1 = np.array([x_up[k+1], y_up[k+1]]) params = np.linalg.solve(np.column_stack((p1-p0, q0-q1)), q0-p0) if np.all((params >= 0) & (params <= 1)): return p0 + params[0]*(p1 - p0) >>> find_intersect(x_down, y_down, x_up, y_up) array([ 6.28302264, 1.63658676]) crossing_point = find_intersect(x_down, y_down, x_up, y_up) plt.plot(crossing_point[0], crossing_point[1], 'ro') plt.show() 

введите описание изображения здесь

В моей системе это может обрабатывать около 20 пересечений в секунду, что не является сверхбыстрой, но, вероятно, достаточно для анализа графиков время от времени. Возможно, вы сможете ускорить процесс векторизации решения линейных систем 2×2:

 def find_intersect_vec(x_down, y_down, x_up, y_up): p = np.column_stack((x_down, y_down)) q = np.column_stack((x_up, y_up)) p0, p1, q0, q1 = p[:-1], p[1:], q[:-1], q[1:] rhs = q0 - p0[:, np.newaxis, :] mat = np.empty((len(p0), len(q0), 2, 2)) mat[..., 0] = (p1 - p0)[:, np.newaxis] mat[..., 1] = q0 - q1 mat_inv = -mat.copy() mat_inv[..., 0, 0] = mat[..., 1, 1] mat_inv[..., 1, 1] = mat[..., 0, 0] det = mat[..., 0, 0] * mat[..., 1, 1] - mat[..., 0, 1] * mat[..., 1, 0] mat_inv /= det[..., np.newaxis, np.newaxis] import numpy.core.umath_tests as ut params = ut.matrix_multiply(mat_inv, rhs[..., np.newaxis]) intersection = np.all((params >= 0) & (params <= 1), axis=(-1, -2)) p0_s = params[intersection, 0, :] * mat[intersection, :, 0] return p0_s + p0[np.where(intersection)[0]] 

Да, это грязно, но он работает, и делает это в 100 раз быстрее:

 find_intersect(x_down, y_down, x_up, y_up) Out[67]: array([ 6.28302264, 1.63658676]) find_intersect_vec(x_down, y_down, x_up, y_up) Out[68]: array([[ 6.28302264, 1.63658676]]) %timeit find_intersect(x_down, y_down, x_up, y_up) 10 loops, best of 3: 66.1 ms per loop %timeit find_intersect_vec(x_down, y_down, x_up, y_up) 1000 loops, best of 3: 375 us per loop 

Вы можете сделать это очень просто, используя функцию interp1d из scipy для повторной выборки y-значений всех ваших строк с одинаковыми значениями x.

http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html

  • Гаус-Лежандр с интервалами -x -> бесконечность: адаптивный алгоритм для эффективного преобразования весов и узлов
  • Закрытие файла после использования np.load (с помощью Spyder)
  • Python / Pandas / Numpy - прямой расчет количества рабочих дней между двумя датами, исключая праздники
  • График рассеяния со строковыми координатами X и Y
  • Возможная оптимизация для расчета квадратичного евклидова расстояния
  • Минимальные комплексные номера минимальных квадратов
  • Использование Numpy на разных платформах
  • Лучшие практики чтения и работы с fortran упорядоченными массивами с numpy
  • Python - лучший язык программирования в мире.