Apply a function varying between categories in R

Asked

Viewed 60 times

2

I need to calculate the elasticity - price of demand of a specific product (percentage variation of the quantity demanded divided by the percentage variation of the price). For that I made the following equation:

elasticidade = numeric(length(teste))
for(i in 2:nrow(teste)){
elasticidade[i] = ((media_vendas[i]-media_vendas[i-1])/(media_vendas[i]+media_vendas[i-1])/2)/((preço[i]-preço[i-1])/(preço[i]+preço)/2)

In which media_vendas is the average quantity of units sold at such a price, and preço is the unit price on the day.

However, I would like to apply this equation by grouping the days of the week and price, that is to say, calculate the elasticity between the observations for each day of the week for each price:

    dados %>% select(DiaSemana, preço, vendas) %>% 
  group_by(DiaSemana, preço) %>%
  summarise(n = n(), 
            media_vendas = mean(vendas)) %>%
  mutate(elasticidade = ((media_vendas[2]-media_vendas[1])/(media_vendas[2]+media_vendas[1])/2)/((preço[2]-preço[1])/(preço[2]+preço[1])/2), by = DiaSemana)

Putting with the for within the mutate or so, both do not rotate.

  DiaSemana  preço          n media_vendas
       <chr> <chr>      <int>        <dbl>
     1 qua   1.55           7        166. 
     2 qua   1.69          18        123. 
     3 qua   1.99           6        103. 
     4 qua   2.59           2         99.5
     5 qui   1.55           8        204  
     6 qui   1.69          16        130. 
     7 qui   1.99           7        109. 
     8 seg   1.55           7        127. 
     9 seg   1.69          17        152. 
    10 seg   1.99           6         86.2
    11 seg   2.59           1        106  
    12 sex   1.55           7        193. 
    13 sex   1.69          15        182. 
    14 sex   1.99           7        111. 
    15 ter   1.55           7        134. 
    16 ter   1.69          19        135. 
    17 ter   1.99           5         91.8
    18 ter   2.59           2         90.5

For example, calculate the elasticity from the sales average of the fourth price 1.69 less the sales average of the fourth price 1.55. The average sales of the fourth price 1.99 less the average sales of the fourth price 1.69, ... And do it for every day of the week.

  • 2

    Hello Leonardo, welcome to the OS in Portuguese. Read the instructions on how to ask good questions on the site. In particular, see this topic on how to provide a sample of your data in R: https://answall.com/questions/264168/quais-as-principais-fun%C3%A7%C3%b5es-to-create-an-example-m%C3%adnimo-reproduce%C3%advel-em-r

1 answer

1

A function is first defined to calculate elasticity through the linear model. To calculate differences, each vector must have at least two elements, if they do not have the result is undetermined (NA) with a message.

elasticidade <- function(preco, quant){
  nome_preco <- deparse(substitute(preco))
  if(length(preco) < 2){
    msg <- paste(sQuote(nome_preco), "tem menos de dois elementos, o cálculo não pode ser efetuado.")
    message(msg)
    NA
  } else {
    preco.bar <- mean(preco, na.rm = TRUE)
    quant.bar <- mean(quant, na.rm = TRUE)
    fit <- lm(quant ~ preco)
    coef(fit)[2] * preco.bar/quant.bar
  }
}

Now, apply the above function in a pipe dplyr, grouping by day of the week. I added an unsolicited column to the question, Elastico, that can take the values

  1. "não" - elasticity less than 1;
  2. "sim" - elasticity greater than 1;
  3. "unitário" - elasticity equal to 1.

To not get this column just remove the lines from the mutate and finish the pipe right on the line of summarise.

library(dplyr)

dados %>%
  group_by(DiaSemana) %>%
  summarise(Elasticidade = elasticidade(preço, media_vendas), .groups = 'keep') %>%
  mutate(Elastico = sign(abs(Elasticidade) - 1) + 2,
         Elastico = c("Não", "Unitário", "Sim")[Elastico])
## A tibble: 5 x 3
## Groups:   DiaSemana [5]
#  DiaSemana Elasticidade Elastico
#  <chr>            <dbl> <chr>   
#1 qua             -0.823 Não     
#2 qui             -2.28  Sim     
#3 seg             -0.556 Não     
#4 sex             -2.09  Sim     
#5 ter             -0.797 Não     

Browser other questions tagged

You are not signed in. Login or sign up in order to post.