knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%",
  dev = "ragg_png",
  dpi = 300
)

econagent

Lifecycle: experimental

econagent provides utility functions and composite goods in economics.

Installation

You can install the development version of econagent from GitHub with:

# install.packages("devtools")
devtools::install_github("UchidaMizuki/econagent")

Examples for utility functions

library(econagent)
library(tidyverse)

Calibrate utility functions

# Sample data
prices <- c(4, 2)
income <- 12

quantity_x <- 2
quantity_y <- util_2goods_budget(prices, income)(quantity_x)
quantities <- c(quantity_x, quantity_y)
cobb_douglas <- util_cobb_douglas() |> 
  util_calibrate(prices, quantities)
cobb_douglas
leontief <- util_leontief() |> 
  util_calibrate(prices, quantities)
leontief
ces_minus_1_5 <- util_ces(substitution = -1.5) |> 
  util_calibrate(prices, quantities)
ces_minus_1_5

Indifference curve and budget line for two goods

util_2goods_indifference(cobb_douglas, cobb_douglas(quantities))(1:6)
util_2goods_budget(prices, income)(1:6)

Sample plots

# You need to install dev version of geomtextpath
# - https://github.com/AllanCameron/geomtextpath/issues/114
library(geomtextpath)

theme_set(theme_bw())

limits <- c(0, max(income / prices))
stat_indifference <- function(f, utility,
                              label = pillar::obj_sum(f) |> 
                                # https://github.com/AllanCameron/geomtextpath/issues/75
                                str_replace_all("-", "\u2212"),
                              ...) {
  fun <- util_2goods_indifference(f, utility, otherwise = 1e6)
  if (is.null(label)) {
    stat_function(fun = fun,
                  xlim = limits,
                  ...)
  } else {
    stat_function(geom = "textpath",
                  fun = fun,
                  label = label,
                  hjust = 1,
                  xlim = limits,
                  ...) 
  }
}
stat_2goods_budget <- function(prices, income, 
                               label = "Budget line",
                               ...) {
  xlim <- c(0, income / prices[1])
  fun <- util_2goods_budget(prices, income)
  if (is.null(label)) {
    stat_function(fun = fun,
                  xlim = xlim,
                  ...)
  } else {
    stat_function(geom = "textpath",
                  fun = fun,
                  label = label,
                  hjust = 0.2,
                  xlim = xlim,
                  ...)
  }
}
geom_point_quantities <- function(quantities, ...) {
  geom_point(aes(quantities[[1]], quantities[[2]]),
             ...)
}
ggplot() +
  geom_hline(yintercept = 0,
             color = "dimgray") +
  geom_vline(xintercept = 0,
             color = "dimgray") +
  stat_indifference(cobb_douglas, cobb_douglas(quantities),
                    color = "red4") +
  stat_indifference(leontief, leontief(quantities),
                    n = 201,
                    color = "red4") +
  stat_indifference(ces_minus_1_5, ces_minus_1_5(quantities),
                    color = "red4") +
  stat_2goods_budget(prices, income,
                     color = "blue4") +
  geom_point_quantities(quantities,
                        color = "blue4",
                        size = 2) +
  scale_x_continuous("Quantity of good X") +
  scale_y_continuous("Quantity of good Y") +
  tune::coord_obs_pred(xlim = limits,
                       ylim = limits)
ces_0_75 <- util_ces(substitution = 0.75) |> 
  util_calibrate(prices, quantities)
get_data_2goods_utility <- function(f) {
  f |> 
    purrr::map(
      \(f) {
        expand_grid(quantity_x = seq(0, limits[[2]], length.out = 100),
                    quantity_y = seq(0, limits[[2]], length.out = 100)) |>
          rowwise() |> 
          mutate(utility = f(c(quantity_x, quantity_y))) |> 
          ungroup()
      }
    ) |> 
    set_names(map_chr(f, pillar::obj_sum)) |> 
    bind_rows(.id = "utility_type") |> 
    mutate(across(utility_type, as_factor))
}
get_data_2goods_utility(c(leontief, ces_minus_1_5, cobb_douglas, ces_0_75)) |> 
  ggplot(aes(quantity_x, quantity_y)) +
  geom_contour_filled(aes(z = utility),
                      binwidth = 4) +
  stat_2goods_budget(prices, income,
                     color = "white") +
  geom_point_quantities(quantities,
                        color = "white") +
  scale_x_continuous("Quantity of good X") +
  scale_y_continuous("Quantity of good Y") +
  scale_fill_viridis_d("Utility") +
  facet_wrap(~ utility_type,
             ncol = 2) +
  tune::coord_obs_pred()

Marginal utility for two goods

# Total utility
util_2goods_utility(cobb_douglas, quantities[[2]])(1:6)
# Marginal utility
util_2goods_utility(cobb_douglas, quantities[[2]], gradient = TRUE)(1:6)

Sample plots

library(patchwork)

stat_utility <- function(f, 
                         gradient = FALSE,
                         label = pillar::obj_sum(f) |> 
                           # https://github.com/AllanCameron/geomtextpath/issues/75
                           str_replace_all("-", "\u2212"),
                         ...) {
  if (gradient) {
    fun <- util_2goods_utility(f, quantities[[2]], gradient = TRUE)
  } else {
    fun <- util_2goods_utility(f, quantities[[2]])
  }
  if (is.null(label)) {
    stat_function(fun = fun,
                  xlim = limits,
                  ...)
  } else {
    stat_function(geom = "textpath",
                  fun = fun,
                  label = label,
                  hjust = 1,
                  xlim = limits,
                  ...) 
  }
}

color <- RColorBrewer::brewer.pal(4, "Dark2")
plot_total_utility <- ggplot() +
  stat_utility(leontief,
               color = color[[1]]) +
  stat_utility(ces_minus_1_5,
               color = color[[2]]) +
  stat_utility(cobb_douglas,
               color = color[[3]]) +
  scale_x_continuous("Quantity of good X",
                     limits = c(1e-3, NA)) +
  scale_y_continuous("Total utility")
plot_marginal_utility <- ggplot() +
  stat_utility(leontief,
               gradient = TRUE,
               n = 201,
               color = color[[1]]) +
  stat_utility(ces_minus_1_5,
               gradient = TRUE,
               color = color[[2]]) +
  stat_utility(cobb_douglas,
               gradient = TRUE,
               color = color[[3]]) +
  scale_x_continuous("Quantity of good X",
                     limits = c(1e-3, NA)) +
  scale_y_continuous("Marginal utility of good X")

plot_total_utility + plot_marginal_utility
get_data_2goods_utility(c(leontief, ces_minus_1_5, cobb_douglas, ces_0_75)) |> 
  ggplot(aes(quantity_x, quantity_y)) +
  geom_contour_filled(aes(z = utility),
                      binwidth = 4) +
  geom_hline(yintercept = quantities[[2]],
             color = "white",
             linetype = "dashed") +
  scale_x_continuous("Quantity of good X") +
  scale_y_continuous("Quantity of good Y") +
  scale_fill_viridis_d("Utility") +
  facet_wrap(~ utility_type,
             ncol = 2) +
  tune::coord_obs_pred()

Price effect for two goods

prices_new <- c(2, 2)

# Price effect
quantities_new <- util_demand(cobb_douglas, prices_new,
                              income = income)
quantities_new
# Substitution effect
quantities_substitution <- util_demand(cobb_douglas, prices_new,
                                       utility = cobb_douglas(quantities))
quantities_substitution
# Income effect
quantities_new - quantities_substitution

Sample plots

geom_text_quantities <- function(quantities,
                                 label = str_c("(", 
                                               scales::label_number(accuracy = 1e-2)(quantities[[1]]), 
                                               ", ", 
                                               scales::label_number(accuracy = 1e-2)(quantities[[2]]), 
                                               ")"),
                                 hjust = -0.2,
                                 ...) {
  geom_text(aes(quantities[[1]], quantities[[2]]),
            label = label,
            hjust = hjust,
            ...)
}

ggplot() +
  geom_hline(yintercept = 0,
             color = "dimgray") +
  geom_vline(xintercept = 0,
             color = "dimgray") +
  stat_indifference(cobb_douglas, cobb_douglas(quantities),
                    color = "red4") +
  stat_indifference(cobb_douglas, cobb_douglas(quantities_new),
                    label = NULL,
                    color = "red4") +
  stat_2goods_budget(prices, income,
                     color = "blue4") +
  stat_2goods_budget(prices_new, income,
                     label = NULL,
                     color = "blue4") +
  stat_2goods_budget(prices_new, sum(prices_new * quantities_substitution),
                     label = NULL,
                     linetype = "dashed",
                     color = "blue4") +
  geom_point_quantities(quantities,
                        color = "blue4") +
  geom_point_quantities(quantities_new,
                        color = "blue4") +
  geom_point_quantities(quantities_substitution,
                        color = "blue4") +
  geom_text_quantities(quantities,
                       color = "blue4") +
  geom_text_quantities(quantities_new,
                       color = "blue4") +
  geom_text_quantities(quantities_substitution,
                       color = "blue4") +
  scale_x_continuous("Quantity of good X") +
  scale_y_continuous("Quantity of good Y") +
  tune::coord_obs_pred(xlim = limits,
                       ylim = limits)

Examples for composite goods



UchidaMizuki/econgoods documentation built on Oct. 23, 2024, 8:10 a.m.