Created
February 22, 2019 09:13
-
-
Save echasnovski/a8760e5b9cc96e78b558269bf99f934d to your computer and use it in GitHub Desktop.
Updated version of https://gist.github.com/andrewheiss/29057150cc6466f0f4d9c39236c19aa6 . It has three main changes: 1) Model variables are swapped for convenience, 2) Adding tangent line wrapped into function with extra functionality, 3) Plot is done for a new model with swapped variables and then coordinates are flipped.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(tidyverse) | |
library(Deriv) | |
library(scales) | |
# Here we change variable names: x is "Work effort", y is "Wage per hour" | |
response_curve <- function(x) 60*x^4 + 5*x + 6 | |
response_deriv <- Deriv(response_curve) | |
# Function for tangent line becomes very simple. For more information, see: | |
# https://en.wikipedia.org/wiki/Tangent#More_rigorous_description | |
response_tangent <- function(x, effort) { | |
response_curve(effort) + response_deriv(effort) * (x - effort) | |
} | |
add_tangent <- function(effort, x_width = 0.25, y_width = 15) { | |
# Compute the x limits which will be used to plot tangent line. It is computed | |
# as minimum of simmetrical intervals (with `effort` in the middle) which | |
# give the input plotting width along x and y axis. | |
half_plot_width_x <- 0.5 * x_width | |
# This is computed from the following equation: | |
# `abs(g(effort + d) - g(effort)) = 0.5 * y_width` (here `g` is | |
# `response_tangent` and `d` is what we're looking) | |
half_plot_width_y <- 0.5 * y_width / abs(response_deriv(effort)) | |
half_plot_width <- min(half_plot_width_x, half_plot_width_y) | |
x_lim <- effort + half_plot_width * c(-1, 1) | |
# Return a `stat_function()` output wrapped in the list so that we can use it | |
# as "normal" 'ggplot2' layer function | |
list( | |
stat_function( | |
fun = response_tangent, args = list(effort = effort), | |
color = "darkred", size = 1, xlim = x_lim | |
) | |
) | |
} | |
response_curve_points <- tibble(x = seq(0, 1, 0.01)) %>% | |
mutate(y = response_curve(x)) | |
ggplot(data = tibble(x = c(0, 1)), aes(x = x)) + | |
# Add polynomial curve | |
geom_line(data = response_curve_points, aes(x = x, y = y), | |
size = 0.5, color = "grey30") + | |
# Add tangent lines | |
add_tangent(effort = 0.5) + | |
add_tangent(effort = 0.25) + | |
add_tangent(effort = 0.8) + | |
# Add dots at tangent points | |
annotate(geom = "point", x = 0.5, y = response_curve(0.5)) + | |
annotate(geom = "point", x = 0.25, y = response_curve(0.25)) + | |
annotate(geom = "point", x = 0.8, y = response_curve(0.8)) + | |
# Labels and scale stuff | |
labs(x = "Work effort from employee", y = "Wage per hour") + | |
scale_x_continuous(labels = percent_format(accuracy = 1), expand = c(0, 0)) + | |
scale_y_continuous(labels = dollar, expand = c(0, 0)) + | |
# The main trick: plot of inverse function is made by straightforward | |
# coordinate flipping | |
coord_flip(xlim = c(0, 1), ylim = c(0, 50)) + | |
theme_minimal() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment