I am trying to obtain the upper convex hull, in R, of a set of points relating to productivity data. I expect it to be a function with decreasing returns to scale, with the input being worker hours and output being a measure of work done. I would like the upper convex hull because this would allow me to get the efficiency frontier.
I have searched and found the method chull in R, but this gives the set of points in the whole envelope and not just the upper hull points. Is there a way to automatically select the upper hull points in R?
As an example, we can find the upper hull of a points generated in a circle
library(ggplot2)
# Generate random uniformly spaced points in the square space between (0,0) and (1,1)
x <- runif(10000, min = 0, max = 1)
y <- runif(10000, min = 0, max = 1)
df <- tibble(x,y)
# Filter out the points that don't lie inside a circle of radius 1
df %>% filter(!(x^2 y^2>1)) -> df
# Plot all the points in the above dataframe
ggplot(df, aes(x=x, y=y)) geom_point()
# Compute the convex hull of the above points
newdf <- df[chull(df$x, df$y),]
# Plot the convex hull
ggplot(newdf, aes(x=x, y=y)) geom_point()
The convex hull looks like this
In this example, upper hull should give me just the curved part of the circle and not the axes
CodePudding user response:
Here is an approach using the method of cutting the x-axis into small chunks, and then calculate mean(x) and max(y) for each chunk... Tou can inceals/decrease the number of chunks, to get a smoother (or more detailed) line.
library(tidyverse)
df %>%
mutate(bin = cut(x, 10)) %>% # !! <-- increase/decrease value
group_by(bin) %>%
summarise(max_y = max(y, na.rm = TRUE),
x_max_y = mean(x, na.rm = TRUE)) %>%
ggplot(aes(x = x_max_y, y = max_y)) geom_point()
with n = 50 bins
CodePudding user response:
In this precise case, you can select point that are above the line 1 - x
.
plot(newdf[newdf$y > 1 - newdf$x, ])
Another way to approximate the upper convex hull is to change your initial filtering method to only get values between 1 and e.g. 0.995, and then get the convex hull:
df <- with(df, df[(x^2 y^2 < 1 & x^2 y^2 > 0.995),])
plot(df[chull(df$x, df$y),])