简体   繁体   中英

How to find inflection points in a Kernel density plot in R?

I am trying to find the x-values of the inflection points in the curve of a Kernel density plot that I computed with the density() function.

I found the following answered question helpful in finding the turning points:

How to find all the turning points on a kernel density curve when window width varies .

So I would think there must be a way to fnd the x-values of the inflection points, too. Would be great if somene has a tipp.

By definition, an inflection point is the point where the second derivative of the function equals zero. In the practice, this means that an inflection point will be a point where the slope passes from increasing to decreasing, or vv Using this definition, I came with this approximate and non-automatic approach: Let's say that you have a dataframe, that I will call all , which contains the x-values in the first column, and the result of the density computation in the second one. From this dataframe, we can calculate the slope of two consecutive points like this:

slopes <- vector()
for(i in (2:nrow(all))){
  x1 <- all[i-1, 1]
  x2 <- all[i, 1]
  y1 <- all[i-1, 2]
  y2 <- all[i, 2]
  slope_i <- (y2-y1)/(x2-x1)
  slopes <- append(slopes, slope_i)
}

By the definition of inflection point, we can now calculate if, from one point to another, the slope gets larger or smaller:

increment <- vector()
for(j in 2:length(slopes)){
  increment_j <- slopes[j] - slopes[j-1]
  increment <- append(increment, increment_j)
}

The inflection points will be those points were this increment passes from positive to negative, or vv

Now, let's separate these increments in positive and negative:

pos <- which(increment>0)
neg <- which(increment<0

Now, whenever there is a jump in these pos or neg vectors, it means we have an inflection point. So, once again:

steps_p <- vector()
for(k in 2:length(pos)){
  steps_k <- pos[k] - pos[k-1]
  steps_p <- append(steps_p, steps_k)
}
steps_n <- vector()
for(k in 2:length(neg)){
  steps_k <- neg[k] - neg[k-1]
  steps_n <- append(steps_n, steps_k)
}

Now, just ask R:

which(steps_p>1)
which(steps_n>1)

This are the indices of your inflection points, now just go to your original dataframe and ask for the x value:

all[pos[which(steps_p>1)],1]
all[neg[which(steps_n>1)],1]

Take in mind that the x value will be close to exact, but not quite, as during every loop we lose one index, but it will still be a very close solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM