查找数据中的陡峭斜率 [英] Find abrupt slopes in data

查看:59
本文介绍了查找数据中的陡峭斜率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有X和Y坐标的人行道表面的高分辨率垂直轮廓,我正在寻找Y的突然增加,这可能归因于绊倒危险(归类为增加6毫米).我在 pracma 中使用了 findpeaks 命令,但是它没有达到我想要的功能(或者我没有正确使用它).我需要做的是检测在指定距离X上至少增加6 mm的Y值,对于本示例来说,假设为100 mm,并记录该增加值的 Y 最大值.本质上是绊倒危险"的最高点.

I have a high-resolution vertical profile of a pavement surface with X and Y coordinates and I'm looking for abrupt increases in Y which could be attributed to a trip hazard (classed as a 6 mm increase). I'm using the findpeaks command in pracma but it's not doing what I want (or I'm not using it properly). What I need to do is detect increases in Y of at least 6 mm over a specified distance of X, let's say 100 mm for this example, and to record the maximum value of Y over the increase. Essentially the highest point of the 'trip hazard'.

这是数据( X Y 的单位是mm)

here's the data (units are mm for X and Y)

    x <- seq (0, 2080, by = 10)

y<- c(1.21, 1.67,   2.10,   2.50,   2.88,   3.24,   3.56,   3.85,   4.11,   4.33,   4.53,   4.70,   4.84,   4.94,   4.99,   4.98,   4.95,   4.95,   4.91,   4.82,   4.80,   4.95,   5.20,   5.39,   5.44,   5.44,   5.48,   5.58,   5.73,
5.93,   6.17,   6.60,   7.13,   7.45,   7.52,   7.53,   7.49,   7.11,   6.46,   6.03,   6.01,   6.16,   6.38,   6.57,   6.78,   7.05,   7.22,   7.14,   6.94,   6.82,   6.80,   6.79,   6.79,   6.86,   7.01,   7.17,   7.26,   7.26,   
7.21,   7.14,   7.13,   7.13,   7.04,   6.89,   6.72,   6.43,   5.90,   5.17,   4.42,   3.80,   3.30,   2.81,   2.38,   2.01,   1.69,   1.45,   1.29,   1.20,   1.17,   1.25,   1.44,   1.65,   1.80,   1.94,   2.11,   2.24,   2.19,   
2.04,   1.97,   2.05,   2.17,   2.29,   2.39,   2.50,   2.61,   2.70,   2.69,   2.62,   2.61,   2.71,   2.84,   2.97,   3.20,   3.50,   3.71,   3.79,   3.80,   3.77,   3.73,   3.67,   3.60,   3.52,   3.40,   3.24,   3.12,   3.10,   
3.14,   3.13,   3.06,   2.96,   2.83,   2.65,   2.32,   1.90,   1.64,   1.62, 1.66, 1.71,   1.85,   2.11,   2.30,   2.37,   2.42,   2.47,   2.53,   2.56,   2.56,   2.59,   2.83,   3.19,   3.43,   3.43,   3.33,   3.19,   2.96,   
2.64,   2.34,   2.18,   2.18,   2.22,   2.27,   2.46,   2.78,   2.96,   2.93,   2.83,   2.68,   2.43,   2.05, 1.65, 1.30,   0.98,   0.66,   0.41,   0.15,   -0.11,  -0.26,  -0.28,  -0.24,  -0.09,  0.30,   0.88,   1.51,
2.06,   2.56,   3.06,   3.49,   3.65,   3.67,   3.92,   4.36,   4.83,   5.47,   6.52,   7.88,   9.30,   10.48,  11.40,  12.24,  13.03,  13.65,  14.12,  14.65,  15.24,  15.81,  16.43,  17.16,  17.97,  18.76,
19.45,  20.04,  20.59,  21.04,  21.39,  21.67,  21.86,  21.95,  21.95,  21.87)

data<- data.frame(x,y)

这是我正在使用的代码

    plot(x, y, ylim=c(0, 30), xlim = c(0, 2200), cex=0.2, type='o')
    grid()

## FROM LEFT TO RIGHT

peaks_1<-data.frame(findpeaks(data$y, minpeakheight = 6, threshold = 0, 
                              nups = 10, ndowns = 0,  minpeakdistance = 1, sortstr=F))

## FROM RIGHT TO LEFT

peaks_2<-data.frame(findpeaks(data$y, minpeakheight = 6, threshold = 0, 
          nups = 0, ndowns = 10,  minpeakdistance = 1, sortstr=F))


peaks<-rbind(peaks_1, peaks_2)

colnames(peaks)<-c("y", "X2", "X3", "X4")

peak_points<- data.frame(merge(peaks, data, by='y'))


    ## NOTE: I HAVE ROUNDED THE RAW DATA FOR THIS EXAMPLE AND SO WHEN THE DATA ARE MERGED, 
    ## IT PRODUCES THREE ADDITIONAL VALUES WHICH WE WILL MANUALLY REMOVE HERE

peak_points<- peak_points[-c(1, 2, 5),]

points(peak_points$x, peak_points$y,pch=19, cex=1,col='maroon')

右边的那个(21.95毫米)似乎是正确的,也许中间的那个(7.13毫米),但是左边的那个(7.53毫米)却不正确.有没有一种方法可以使用 nracs 命令使用 pracma (或其他任何方法)指定最小增量?

The one on the right (21.95 mm) seems correct, and maybe the one in the middle (7.13 mm), but the one on the left doesn't (7.53 mm). Is there a way I can use pracma (or anything else) to specify the minimum increase with the nups command?

推荐答案

这是一种简单的暴力手段;如果您的数据集不是太大,那就足够了.

Here's a simple brute-force approach; if your dataset isn't too big, it should be adequate.

# All the code below assumes that `data` is already sorted by x

# Flag every point within the range of the trip hazard
data$trip_hazard = F

# Iterate over every pair of points
for(i in 1:(nrow(data) - 1)) {
  for(j in (i + 1):nrow(data)) {
    # Get the x-coordinates of the points
    x1 = data$x[i]
    x2 = data$x[j]
    # If the points are no more than 100 mm apart, check whether there's a trip
    # hazard between them
    if(x2 - x1 <= 100) {
      # Get the y-coordinates of the points
      y1 = data$y[i]
      y2 = data$y[j]
      # If there's a rise or fall of at least 6 mm, we have a trip hazard; flag
      # all the points in the range accordingly
      if(abs(y2 - y1) >= 6) {
        data$trip_hazard[i:j] = T
      }
    }
    # If the points are more than 100 mm apart, we don't need to keep checking
    # points that are even further apart
    else {
      break
    }
  }
}

# Get the maximum y-value within each trip hazard
library(dplyr)
library(tidyr)
data = data %>%
  mutate(range_id = ifelse(trip_hazard != coalesce(lag(trip_hazard),
                                                   !trip_hazard),
                           x, NA)) %>%
  fill(range_id) %>%
  group_by(range_id) %>%
  mutate(peak = trip_hazard & y == max(y)) %>%
  ungroup() %>%
  dplyr::select(-range_id)

# Plot the sidewalk (repeated from question)
plot(x, y, ylim = c(0, 30), xlim = c(0, 2200), cex = 0.2, type = "o")
# Plot the trip hazards in red
points(data$x[data$trip_hazard], data$y[data$trip_hazard],
       lwd = 4, col = "red", type = "l")
# Plot the highest point within each trip hazard
points(data$x[data$peak], data$y[data$peak], pch = 19, cex = 2, col = "red")

这篇关于查找数据中的陡峭斜率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆