estimativas_raw = read_projectdata()
glimpse(estimativas_raw)
## Rows: 12,299
## Columns: 17
## $ TaskNumber <chr> "1735", "1742", "1971", "2134", "2251", "2283", …
## $ Summary <chr> "Flag RI on SCM Message Summary screen using met…
## $ Priority <dbl> 1, 1, 2, 5, 10, 1, 5, 5, 6, 5, 2, 1, 3, 1, 1, 8,…
## $ RaisedByID <chr> "58", "58", "7", "50", "46", "13", "13", "13", "…
## $ AssignedToID <chr> "58", "42", "58", "42", "13", "13", "13", "58", …
## $ AuthorisedByID <chr> "6", "6", "6", "6", "6", "58", "6", "6", "6", "5…
## $ StatusCode <chr> "FINISHED", "FINISHED", "FINISHED", "FINISHED", …
## $ ProjectCode <chr> "PC2", "PC2", "PC2", "PC2", "PC2", "PC9", "PC2",…
## $ ProjectBreakdownCode <chr> "PBC42", "PBC21", "PBC75", "PBC42", "PBC21", "PB…
## $ Category <chr> "Development", "Development", "Operational", "De…
## $ SubCategory <chr> "Enhancement", "Enhancement", "In House Support"…
## $ HoursEstimate <dbl> 14.00, 7.00, 0.70, 0.70, 3.50, 7.00, 7.00, 7.00,…
## $ HoursActual <dbl> 1.75, 7.00, 0.70, 0.70, 3.50, 7.00, 7.00, 7.00, …
## $ DeveloperID <chr> "58", "42", "58", "42", "13", "13", "43", "58", …
## $ DeveloperHoursActual <dbl> 1.75, 7.00, 0.70, 0.70, 3.50, 7.00, 7.00, 7.00, …
## $ TaskPerformance <dbl> 12.25, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,…
## $ DeveloperPerformance <dbl> 12.25, 0.00, 0.00, 0.00, 0.00, 0.00, NA, 0.00, 0…
estimativas_raw %>%
select(ProjectCode, TaskNumber, HoursEstimate, HoursActual) %>%
skimr::skim()
| Name | Piped data |
| Number of rows | 12299 |
| Number of columns | 4 |
| _______________________ | |
| Column type frequency: | |
| character | 2 |
| numeric | 2 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| ProjectCode | 0 | 1 | 3 | 4 | 0 | 20 | 0 |
| TaskNumber | 0 | 1 | 4 | 5 | 0 | 10266 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| HoursEstimate | 0 | 1 | 10.15 | 28.84 | 0.01 | 1 | 3 | 7.0 | 910.00 | ▇▁▁▁▁ |
| HoursActual | 0 | 1 | 13.18 | 68.72 | 0.01 | 1 | 3 | 8.5 | 2490.16 | ▇▁▁▁▁ |
Temos 20 projetos, com 12299 estimativas_raw. Não há apenas uma estimativa por tarefa, já que há apenas 10266 valores distintos de TaskNumber.
estimativas_raw %>%
group_by(TaskNumber) %>%
mutate(estimativas = n()) %>%
filter(estimativas > 1) %>%
count(TaskNumber, sort = T)
## # A tibble: 1,384 x 2
## # Groups: TaskNumber [1,384]
## TaskNumber n
## <chr> <int>
## 1 10605 8
## 2 6889 8
## 3 10089 7
## 4 10974 7
## 5 11056 7
## 6 11270 7
## 7 13124 7
## 8 13190 7
## 9 13253 7
## 10 3812 7
## # … with 1,374 more rows
Para nossa análise, usaremos uma estimativa por task. Caso haja mais de uma usaremos a média das estimativas_raw:
estimativas = estimativas_raw %>%
group_by(ProjectCode, TaskNumber, Category, Priority, Summary) %>%
summarise(
HoursEstimate = mean(HoursEstimate),
HoursActual = mean(HoursActual),
DeveloperPerformance = mean(DeveloperPerformance)
) %>%
ungroup()
por_time = estimativas_raw %>%
group_by(ProjectCode) %>%
summarise(devs = NROW(unique(DeveloperID)),
erro_medio_abs = mean(abs(HoursEstimate - HoursActual)),
estimativas = n())
Antes de tudo, para entender a relação entre variáveis é necessário saber que para fazer essa avaliação existem técnicas visuais, que utilizam gráficos e visualizações, e técnicas que analisam correlação entre variáveis, como as que avaliam métricas de associação ou equações de regressão.
Dito isso, podemos decompor a pergunta em duas: a primeira deseja observar a relação entre horas estimadas e horas reais, sem levar em conta as categorias de tarefa, e a segunda procura observar a mesma relação, mas considerando essa relação para cada uma das categorias. Assim, podemos tentar captar as relações existentes por meio das técnicas mencionadas anteriormente e conseguir construir as respostas necessárias.
Realizando uma avaliação visual, inicialmente podemos construir um scatterplot e tentar visualizar alguma relação entre HoursEstimate e HoursActual. Plotando no gráfico abaixo temos:
estimativas %>%
ggplot(aes(HoursEstimate, HoursActual)) +
geom_point(alpha = 0.4) +
labs(title = "Relação entre estimativas e horas reais", x = "Horas estimadas", y = "Horas reais") +
theme(plot.title = element_text(hjust = 0.5))
Pelo que é visto acima, é difícil perceber uma relação linear pois há uma grande concentração de pontos na faixa inicial de valores. Além disso, percebe-se que existem valores considerados outliers para as duas variáveis, pois são muito diferentes do restante dos dados, sendo esses os valores HoursEstimate > 500 e HoursActual > 1000. De modo a resolver isso, vamos filtrar os outliers. Para a próxima visualização, uma solução possível é realizar uma transformação na escala dos dois eixos do gráfico, tentando visualizar alguma relação não linear entre log(x) e log(y).
estimativas <- estimativas %>%
filter(HoursEstimate < 500 & HoursActual < 1000)
estimativas %>%
ggplot(aes(HoursEstimate, HoursActual)) +
geom_point(alpha = 0.4) +
scale_x_log10() +
scale_y_log10() +
labs(title = "Relação entre estimativas e horas reais", x = "log(Horas estimadas)", y = "log(Horas reais)") +
theme(plot.title = element_text(hjust = 0.5))
Observando esse segundo gráfico fica mais claro a presença de alguma relação entre as duas variáveis, sobretudo ao nos atentarmos nas principais características que compõem uma relação. O formato é próximo do linear - mesmo sabendo que não há relação linear já que as escalas foram transformadas, e possívelmente é uma relação não tão forte e que é positiva. Para verificar essa hipótese, podemos fazer uso das outras técnicas descritas previamente e analisar a correlação por meio de alguma métrica de associação. Assim, para essa relação calcularemos alguns dos coeficientes de correlação mais conhecidos: Pearson, Spearman e Kendall.
estimativas %>%
summarise(pearson = cor(HoursEstimate, HoursActual, method = "pearson"),
spearman = cor(HoursEstimate, HoursActual, method = "spearman"),
kendall = cor(HoursEstimate, HoursActual, method = "kendall"))
## # A tibble: 1 x 3
## pearson spearman kendall
## <dbl> <dbl> <dbl>
## 1 0.485 0.826 0.696
Cada uma das métricas utilizadas são mais recomendadas em diferentes cenários e, nesse caso, daremos mais ênfase nos coeficientes de Spearman e Kendall, pois ao contrário de Pearson eles são resistentes a outliers e não exigem que a relação seja linear - o que está de acordo com o cenário caracterizado pelas visualizações acima.
De acordo com o valor obtido pela métrica de Spearman essa é uma correlação forte, pois está dentro de um intervalo próximo de 0,7 e 0,9. O mesmo pode ser dito do resultado obtido pelo coeficiente de Kendall, que é definida por um intervalo igual ao da métrica anterior, assim ela também pode ser qualificada como uma correlação forte.
Então, com base no que foi visto, é possível dizer que a relação entre as horas estimadas e as horas reais, considerando a empresa como um todo, é uma relação existente e pode ser dita como forte.
Para analisar a relação considerando as diferentes categorias, realizaremos uma metodologia similar. A diferença será apenas que a realização de cada uma das fases anteriores levarão em conta os grupos definidos por cada uma das categorias existentes. As categorias são Development, Management e Operational e estão descritas no artigo que os dados foram coletados.
Então, vamos analisar um scatterplot das variáveis, para cada uma das tarefas.
estimativas %>%
ggplot(aes(HoursEstimate, HoursActual)) +
geom_point(alpha = 0.4) +
facet_grid(rows = vars(Category)) +
labs(title = "Relação entre estimativas e horas reais, por categoria", x = "Horas estimadas", y = "Horas reais") +
theme(plot.title = element_text(hjust = 0.5))
De modo similar ao que aconteceu quando os dados foram considerados como um todo, há uma grande concentração de pontos nas faixas de valores iniciais, mas as duas categorias mais acima indicam isso com menos força. Apesar disso, ainda não é possível constatar facilmente uma relação linear entre as horas estimadas e as horas reais. Aplicaremos a transformação na escala dos eixos para tentar encontrar a existência de alguma relação.
estimativas %>%
ggplot(aes(HoursEstimate, HoursActual)) +
geom_point(alpha = 0.4) +
scale_x_log10() +
scale_y_log10() +
facet_grid(rows = vars(Category)) +
labs(title = "Relação entre estimativas e horas reais, por categoria", x = "log(Horas estimadas)", y = "log(Horas reais)") +
theme(plot.title = element_text(hjust = 0.5))
Novamente, agora também é possível enxergar possíveis relações entre as variáveis, para cada uma das categorias. Todas parecem ter um formato linear, serem positivas e relativamente fortes - apenas a categoria mais acima talvez não possua uma relação muito forte. Então, analisaremos os coeficientes de correlação para verificar se as relações obtidas através das visualizações também são existentes.
estimativas %>%
group_by(Category) %>%
summarise(pearson = cor(HoursEstimate, HoursActual, method = "pearson"),
spearman = cor(HoursEstimate, HoursActual, method = "spearman"),
kendall = cor(HoursEstimate, HoursActual, method = "kendall"))
## # A tibble: 3 x 4
## Category pearson spearman kendall
## <chr> <dbl> <dbl> <dbl>
## 1 Development 0.542 0.834 0.700
## 2 Management 0.337 0.752 0.634
## 3 Operational 0.342 0.842 0.729
Com base no mesmo critério de antes, a análise não leva em conta a correlação de Pearson. Observa-se que Development e Operational tem a correlação forte para as duas métricas analisadas, enquanto Management já não possui um valor de correlação de Kendall tão grande e sua correlação é considerada moderada.
De todo modo, podemos dizer que a relação das categorias é sim forte e apenas a categoria Management tem uma correlação mais fraca e que pode ser considerada “moderadamente forte”.
Para responder essa pergunta podemos tentar entender a relação entre a quantidade de desenvolvedores em um time e a varíavel que indica o erro médio da estimativa. Por exemplo, se houver uma relação linear entre o erro e o número de devs, quanto mais profissionais em um time maior será o erro na estimativa das atividades.
Podemos testar esse raciocínio por meio de um gráfico entre os fatores/variáveis que estão sendo levados em consideração.
por_time %>%
ggplot(aes(devs, erro_medio_abs)) +
geom_point() +
labs(title = "Relação entre qtd. de devs e erro na estimativa de tarefas", x = "Número de desenvolvedores", y = "Erro médio absoluto da estimativa") +
theme(plot.title = element_text(hjust = 0.5))
Como podemos ver acima, a relação aparenta ser linear, mas o a força e o sinal da relação não são fáceis de serem compreendidos. Neste caso, como temos uma possível relação linear, podemos investigar as correlações para tentar confirmar a relação das variáveis e incluir a correlação de Pearson na análise.
por_time %>%
select(devs, erro_medio_abs) %>%
summarise(pearson = cor(devs, erro_medio_abs, method = "pearson"),
spearman = cor(devs, erro_medio_abs, method = "spearman"),
kendall = cor(devs, erro_medio_abs, method = "kendall"))
## # A tibble: 1 x 3
## pearson spearman kendall
## <dbl> <dbl> <dbl>
## 1 -0.137 0.0438 0.0324
De acordo com o que foi obtido, vemos que as três métricas produziram valores muito próximos a 0. Isso é um forte indício de que não há associação entre as variáveis e não podemos afirmar que existe uma relação. Além disso, vemos que Pearson produziu um valor negativo e as outras duas valores positivos, mostrando que há divergências entre as direções da correlação de acordo com as métricas utilizadas - o que reforça a hipótese de não haver relação entre as propriedades que estamos explorando. Então, não podemos dizer que o erro na estimativa de uma equipe aumenta à medida que ela tem mais desenvolvedores.