Reputation: 3
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.
Upvotes: 0
Views: 941
Reputation: 457
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 v.v. 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 v.v.
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.
Upvotes: 1