Apresentação

Algumas análises são extremamente demoradas para rodar, mas um trabalho reprodutível computacionamente requer que estas análises rodem repetidamente, porém isso pode custar muitas horas, ou até mesmo dias para rodar algumas rotinas. Uma solução para otimizar a sequência de trabalho é o pacote {targets}

{targets}

O pacote {targets} possibilita otimizar a sequência de trabalho (pipeline) por organizar esta sequência e identificar ações na pipeline que devem ou não devem ser realizadas.

Exemplo

Para ilustrar o uso do pacote targets vamos utilizar um exemplo contido na própria documentação do pacote.

Neste exemplo vamos analisar a relação entre quantidade de ozônio e temperatura em um conjunto de dados presentes no próprio R base chamado airquality. Para tanto precisamos seguir uma sequência de análise de dados, que, basicamente, consiste em:

  1. Ler e manipular a tabela de dados

  2. Rodar um modelo relacionando ozônio e temperatura

  3. Gerar resultados gráficos (figuras) para o modelo ajustado

A base de dados pode ser lida da seguinte forma

data(airquality)
airquality

Imagine que estes dados estão organizados em um diretório local inicializado a partir de um .Rproject e ele apresenta a seguinte estrutura:

  • Uma pasta data contendo os dados

  • Uma pasta R contendo:

    • script com a leitura e transformação dos dados
    • script com o modelo
    • script com funções para plotar os resultados do modelo ajustado

Esta seria uma pasta organizada, tal como vimos durante as aulas. Porém, para que o pacote targets funciona precisamos transformar esta estrutura de acordo com um pipeline targets, que por sua vez necessita da seguinte estrutura:

Neste diretório precisamos transformar a sequência apresentada anteriormente em uma sequência de funções. Portanto os scripts na pasta R serão transformados em funções que serão colocadas dentro da pasta R, com o nome de functions.R, e que apresentará a seguinte forma:

Veja que a mesma sequência de análise está agora representada como funções, naquilo que chamamos de uma pipeline function. Este formato é necessário pois apenas assim o targets irá funcionar.

Uma vez organizado assim, devemos utilizar uma função do pacote targets para gerar um workflow do tipo target. Isso será feito da seguinte maneira:

targets::use_targets()

Isso criará um documento na raiz do seu projeto denominado _targets.R, como ilustrado na figura abaixo, que representa um diretório que segue um workflow do targets

O documento criado informará a sequência do workflow de análise que o pacote targets deve seguir. Após editar o documento para este exemplo ele ficará da seguinte forma

# _targets.R file
library(targets)
source("R/functions.R")
tar_option_set(packages = c("readr", "dplyr", "ggplot2"))
list(
  tar_target(file, "data.csv", format = "file"),
  tar_target(data, get_data(file)),
  tar_target(model, fit_model(data)),
  tar_target(plot, plot_model(model, data))
)

Neste exemplo o arquivo apresenta os seguintes componentes:

  • As funções necessárias para rodar o workflow

  • os pacotes necessários

  • uma lista que indica a sequência que o workflow deve obedecer

Para rodar o workflow via targets usamos a seguinte função

targets::tar_make()

A sequência do workflow vai iniciar e o tempo decorrido vai aparecer no console

Visualizando o workflow

Uma das vantagens do target é que podemos visualizar a sequência do workflow e se ele está atualizado ou não. Para isso usamos a seguinte função

targets::tar_visnetwork()

Esta função vai produzir um gráfico como mostrado nesta figura

Podemos também acessar o output do workflow

Identificando mudanças no workflow

Uma das maiores potencialidades do targets é identificar de maneira eficiente partes do workflow que precisam ser rodadas novamente após realizarmos mudanças na nossa pipeline. Por exemplo, vamos supor que modificamos apenas um parâmetro que afeta a estética do plot final dos resultados do modelo. Não necessitamos rodar tudo de novo, apenas a figura resultante do modelo. O targets identifica onde esta modificação foi feita e aponta a parte do workflow que precisa ser rodado novamente. Podemos identificar isso através da função tar_viznetwork() que vai gerar a seguinte figura (dado a situação descrita acima)

A identificação do local exato de mudança do workflow é possível graças ao target, evitando que tenhamos que rodar todo o workflow do início ao fim, prática que é chamada de loop Sisypheano

LS0tCnRpdGxlOiAnUGlwZWxpbmVzIGNvbSB0YXJnZXRzJwphdXRob3I6ICJHYWJyaWVsIE5ha2FtdXJhIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogaHRtbF9kb2N1bWVudAotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQpgYGAKCmBgYHtyIGtsaXBweSwgZWNobz1GQUxTRSwgaW5jbHVkZT1UUlVFfQprbGlwcHk6OmtsaXBweSgpCmBgYAoKIyBBcHJlc2VudGHDp8OjbwoKQWxndW1hcyBhbsOhbGlzZXMgc8OjbyBleHRyZW1hbWVudGUgZGVtb3JhZGFzIHBhcmEgcm9kYXIsIG1hcyB1bSB0cmFiYWxobyByZXByb2R1dMOtdmVsIGNvbXB1dGFjaW9uYW1lbnRlIHJlcXVlciBxdWUgZXN0YXMgYW7DoWxpc2VzIHJvZGVtIHJlcGV0aWRhbWVudGUsIHBvcsOpbSBpc3NvIHBvZGUgY3VzdGFyIG11aXRhcyBob3Jhcywgb3UgYXTDqSBtZXNtbyBkaWFzIHBhcmEgcm9kYXIgYWxndW1hcyByb3RpbmFzLiBVbWEgc29sdcOnw6NvIHBhcmEgb3RpbWl6YXIgYSBzZXF1w6puY2lhIGRlIHRyYWJhbGhvIMOpIG8gcGFjb3RlIGB7dGFyZ2V0c31gCgoKIyBge3RhcmdldHN9YAoKTyBwYWNvdGUgYHt0YXJnZXRzfWAgcG9zc2liaWxpdGEgb3RpbWl6YXIgYSBzZXF1w6puY2lhIGRlIHRyYWJhbGhvIChwaXBlbGluZSkgcG9yIG9yZ2FuaXphciBlc3RhIHNlcXXDqm5jaWEgZSBpZGVudGlmaWNhciBhw6fDtWVzIG5hIHBpcGVsaW5lIHF1ZSBkZXZlbSBvdSBuw6NvIGRldmVtIHNlciByZWFsaXphZGFzLgoKIyMgRXhlbXBsbwoKUGFyYSBpbHVzdHJhciBvIHVzbyBkbyBwYWNvdGUgdGFyZ2V0cyB2YW1vcyB1dGlsaXphciB1bSBleGVtcGxvIGNvbnRpZG8gbmEgcHLDs3ByaWEgW2RvY3VtZW50YcOnw6NvIGRvIHBhY290ZV0oaHR0cHM6Ly9ib29rcy5yb3BlbnNjaS5vcmcvdGFyZ2V0cy8pLgoKTmVzdGUgZXhlbXBsbyB2YW1vcyBhbmFsaXNhciBhIHJlbGHDp8OjbyBlbnRyZSBxdWFudGlkYWRlIGRlIG96w7RuaW8gZSB0ZW1wZXJhdHVyYSBlbSB1bSBjb25qdW50byBkZSBkYWRvcyBwcmVzZW50ZXMgbm8gcHLDs3ByaW8gUiBiYXNlIGNoYW1hZG8gYGFpcnF1YWxpdHlgLiBQYXJhIHRhbnRvIHByZWNpc2Ftb3Mgc2VndWlyIHVtYSBzZXF1w6puY2lhIGRlIGFuw6FsaXNlIGRlIGRhZG9zLCBxdWUsIGJhc2ljYW1lbnRlLCBjb25zaXN0ZSBlbToKCjEuICBMZXIgZSBtYW5pcHVsYXIgYSB0YWJlbGEgZGUgZGFkb3MKCjIuIFJvZGFyIHVtIG1vZGVsbyByZWxhY2lvbmFuZG8gb3rDtG5pbyBlIHRlbXBlcmF0dXJhCgozLiBHZXJhciByZXN1bHRhZG9zIGdyw6FmaWNvcyAoZmlndXJhcykgcGFyYSBvIG1vZGVsbyBhanVzdGFkbwoKQSBiYXNlIGRlIGRhZG9zIHBvZGUgc2VyIGxpZGEgZGEgc2VndWludGUgZm9ybWEKCmBgYHtyIGV2YWw9RkFMU0UsZWNobz1UUlVFfQpkYXRhKGFpcnF1YWxpdHkpCmFpcnF1YWxpdHkKYGBgCgpJbWFnaW5lIHF1ZSBlc3RlcyBkYWRvcyBlc3TDo28gb3JnYW5pemFkb3MgZW0gdW0gZGlyZXTDs3JpbyBsb2NhbCBpbmljaWFsaXphZG8gYSBwYXJ0aXIgZGUgdW0gLlJwcm9qZWN0IGUgZWxlIGFwcmVzZW50YSBhIHNlZ3VpbnRlIGVzdHJ1dHVyYToKCi0gVW1hIHBhc3RhIGBkYXRhYCBjb250ZW5kbyBvcyBkYWRvcwoKLSBVbWEgcGFzdGEgUiBjb250ZW5kbzoKICAgICsgc2NyaXB0IGNvbSBhIGxlaXR1cmEgZSB0cmFuc2Zvcm1hw6fDo28gZG9zIGRhZG9zCiAgICArIHNjcmlwdCBjb20gbyBtb2RlbG8KICAgICsgc2NyaXB0IGNvbSBmdW7Dp8O1ZXMgcGFyYSBwbG90YXIgb3MgcmVzdWx0YWRvcyBkbyBtb2RlbG8gYWp1c3RhZG8gCiAgICAKRXN0YSBzZXJpYSB1bWEgcGFzdGEgb3JnYW5pemFkYSwgdGFsIGNvbW8gdmltb3MgZHVyYW50ZSBhcyBhdWxhcy4gUG9yw6ltLCBwYXJhIHF1ZSBvIHBhY290ZSB0YXJnZXRzIGZ1bmNpb25hIHByZWNpc2Ftb3MgdHJhbnNmb3JtYXIgZXN0YSBlc3RydXR1cmEgZGUgYWNvcmRvIGNvbSB1bSBwaXBlbGluZSB0YXJnZXRzLCBxdWUgcG9yIHN1YSB2ZXogbmVjZXNzaXRhIGRhIHNlZ3VpbnRlIGVzdHJ1dHVyYToKCmBgYHtyIGVjaG89RkFMU0UsZXZhbD1UUlVFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiZmlncy9kaXJfdGFyZ2V0cy5wbmciKQpgYGAKCk5lc3RlIGRpcmV0w7NyaW8gcHJlY2lzYW1vcyB0cmFuc2Zvcm1hciBhIHNlcXXDqm5jaWEgYXByZXNlbnRhZGEgYW50ZXJpb3JtZW50ZSBlbSB1bWEgc2VxdcOqbmNpYSBkZSBmdW7Dp8O1ZXMuIFBvcnRhbnRvIG9zIHNjcmlwdHMgbmEgcGFzdGEgUiBzZXLDo28gdHJhbnNmb3JtYWRvcyBlbSBmdW7Dp8O1ZXMgcXVlIHNlcsOjbyBjb2xvY2FkYXMgZGVudHJvIGRhIHBhc3RhIFIsIGNvbSBvIG5vbWUgZGUgYGZ1bmN0aW9ucy5SYCwgZSBxdWUgYXByZXNlbnRhcsOhIGEgc2VndWludGUgZm9ybWE6CgpgYGB7ciBlY2hvPUZBTFNFLGV2YWw9VFJVRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3MvcGlwZWxpbmUtdGFyZ2V0LnBuZyIpCmBgYAoKVmVqYSBxdWUgYSBtZXNtYSBzZXF1w6puY2lhIGRlIGFuw6FsaXNlIGVzdMOhIGFnb3JhIHJlcHJlc2VudGFkYSBjb21vIGZ1bsOnw7VlcywgbmFxdWlsbyBxdWUgY2hhbWFtb3MgZGUgdW1hICpwaXBlbGluZSBmdW5jdGlvbiouIEVzdGUgZm9ybWF0byDDqSBuZWNlc3PDoXJpbyBwb2lzIGFwZW5hcyBhc3NpbSBvIHRhcmdldHMgaXLDoSBmdW5jaW9uYXIuCgpVbWEgdmV6IG9yZ2FuaXphZG8gYXNzaW0sIGRldmVtb3MgdXRpbGl6YXIgdW1hIGZ1bsOnw6NvIGRvIHBhY290ZSB0YXJnZXRzIHBhcmEgZ2VyYXIgdW0gd29ya2Zsb3cgZG8gdGlwbyB0YXJnZXQuIElzc28gc2Vyw6EgZmVpdG8gZGEgc2VndWludGUgbWFuZWlyYToKCmBgYHtyIGVjaG89VFJVRSxldmFsPUZBTFNFfQp0YXJnZXRzOjp1c2VfdGFyZ2V0cygpCmBgYAoKSXNzbyBjcmlhcsOhIHVtIGRvY3VtZW50byBuYSByYWl6IGRvIHNldSBwcm9qZXRvIGRlbm9taW5hZG8gYF90YXJnZXRzLlJgLCBjb21vIGlsdXN0cmFkbyBuYSBmaWd1cmEgYWJhaXhvLCBxdWUgcmVwcmVzZW50YSB1bSBkaXJldMOzcmlvIHF1ZSBzZWd1ZSB1bSB3b3JrZmxvdyBkbyB0YXJnZXRzCgpgYGB7ciBlY2hvPUZBTFNFLGV2YWw9VFJVRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3MvdGFyZ2V0X3RhcmdldC1maWxlLnBuZyIpCmBgYAoKTyBkb2N1bWVudG8gY3JpYWRvIGluZm9ybWFyw6EgYSBzZXF1w6puY2lhIGRvIHdvcmtmbG93IGRlIGFuw6FsaXNlIHF1ZSBvIHBhY290ZSB0YXJnZXRzIGRldmUgc2VndWlyLiBBcMOzcyBlZGl0YXIgbyBkb2N1bWVudG8gcGFyYSBlc3RlIGV4ZW1wbG8gZWxlIGZpY2Fyw6EgZGEgc2VndWludGUgZm9ybWEKCmBgYHtyIGVjaG89VFJVRSxldmFsPUZBTFNFfQojIF90YXJnZXRzLlIgZmlsZQpsaWJyYXJ5KHRhcmdldHMpCnNvdXJjZSgiUi9mdW5jdGlvbnMuUiIpCnRhcl9vcHRpb25fc2V0KHBhY2thZ2VzID0gYygicmVhZHIiLCAiZHBseXIiLCAiZ2dwbG90MiIpKQpsaXN0KAogIHRhcl90YXJnZXQoZmlsZSwgImRhdGEuY3N2IiwgZm9ybWF0ID0gImZpbGUiKSwKICB0YXJfdGFyZ2V0KGRhdGEsIGdldF9kYXRhKGZpbGUpKSwKICB0YXJfdGFyZ2V0KG1vZGVsLCBmaXRfbW9kZWwoZGF0YSkpLAogIHRhcl90YXJnZXQocGxvdCwgcGxvdF9tb2RlbChtb2RlbCwgZGF0YSkpCikKYGBgCgpOZXN0ZSBleGVtcGxvIG8gYXJxdWl2byBhcHJlc2VudGEgb3Mgc2VndWludGVzIGNvbXBvbmVudGVzOiAKCi0gQXMgZnVuw6fDtWVzIG5lY2Vzc8OhcmlhcyBwYXJhIHJvZGFyIG8gd29ya2Zsb3cKCi0gb3MgcGFjb3RlcyBuZWNlc3PDoXJpb3MKCi0gdW1hIGxpc3RhIHF1ZSBpbmRpY2EgYSBzZXF1w6puY2lhIHF1ZSBvIHdvcmtmbG93IGRldmUgb2JlZGVjZXIKCgpQYXJhIHJvZGFyIG8gd29ya2Zsb3cgdmlhIHRhcmdldHMgdXNhbW9zIGEgc2VndWludGUgZnVuw6fDo28KCmBgYHtyIGVjaG89VFJVRSxldmFsPUZBTFNFfQp0YXJnZXRzOjp0YXJfbWFrZSgpCmBgYAoKQSBzZXF1w6puY2lhIGRvIHdvcmtmbG93IHZhaSBpbmljaWFyIGUgbyB0ZW1wbyBkZWNvcnJpZG8gdmFpIGFwYXJlY2VyIG5vIGNvbnNvbGUKCmBgYHtyIGVjaG89RkFMU0UsZXZhbD1UUlVFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiZmlncy90YXJnZXRfcnVuLnBuZyIpCmBgYAoKIyMjIFZpc3VhbGl6YW5kbyBvIHdvcmtmbG93CgpVbWEgZGFzIHZhbnRhZ2VucyBkbyB0YXJnZXQgw6kgcXVlIHBvZGVtb3MgdmlzdWFsaXphciBhIHNlcXXDqm5jaWEgZG8gd29ya2Zsb3cgZSBzZSBlbGUgZXN0w6EgYXR1YWxpemFkbyBvdSBuw6NvLiBQYXJhIGlzc28gdXNhbW9zIGEgc2VndWludGUgZnVuw6fDo28KCmBgYHtyIGVjaG89VFJVRSxldmFsPUZBTFNFfQp0YXJnZXRzOjp0YXJfdmlzbmV0d29yaygpCmBgYAoKRXN0YSBmdW7Dp8OjbyB2YWkgcHJvZHV6aXIgdW0gZ3LDoWZpY28gY29tbyBtb3N0cmFkbyBuZXN0YSBmaWd1cmEKCmBgYHtyIGVjaG89RkFMU0UsZXZhbD1UUlVFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiZmlncy90YXJnZXRfdml6LnBuZyIpCmBgYAoKUG9kZW1vcyB0YW1iw6ltIGFjZXNzYXIgbyBvdXRwdXQgZG8gd29ya2Zsb3cKCmBgYHtyIGVjaG89RkFMU0UsZXZhbD1UUlVFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiZmlncy90YXJnZXRfdml6XzIucG5nIikKYGBgCgojIyMgSWRlbnRpZmljYW5kbyBtdWRhbsOnYXMgbm8gd29ya2Zsb3cKClVtYSBkYXMgbWFpb3JlcyBwb3RlbmNpYWxpZGFkZXMgZG8gdGFyZ2V0cyDDqSBpZGVudGlmaWNhciBkZSBtYW5laXJhIGVmaWNpZW50ZSBwYXJ0ZXMgZG8gd29ya2Zsb3cgcXVlIHByZWNpc2FtIHNlciByb2RhZGFzIG5vdmFtZW50ZSBhcMOzcyByZWFsaXphcm1vcyBtdWRhbsOnYXMgbmEgbm9zc2EgcGlwZWxpbmUuIFBvciBleGVtcGxvLCB2YW1vcyBzdXBvciBxdWUgbW9kaWZpY2Ftb3MgYXBlbmFzIHVtIHBhcsOibWV0cm8gcXVlIGFmZXRhIGEgZXN0w6l0aWNhIGRvIHBsb3QgZmluYWwgZG9zIHJlc3VsdGFkb3MgZG8gbW9kZWxvLiBOw6NvIG5lY2Vzc2l0YW1vcyByb2RhciB0dWRvIGRlIG5vdm8sIGFwZW5hcyBhIGZpZ3VyYSByZXN1bHRhbnRlIGRvIG1vZGVsby4gTyB0YXJnZXRzIGlkZW50aWZpY2Egb25kZSBlc3RhIG1vZGlmaWNhw6fDo28gZm9pIGZlaXRhIGUgYXBvbnRhIGEgcGFydGUgZG8gd29ya2Zsb3cgcXVlIHByZWNpc2Egc2VyIHJvZGFkbyBub3ZhbWVudGUuIFBvZGVtb3MgaWRlbnRpZmljYXIgaXNzbyBhdHJhdsOpcyBkYSBmdW7Dp8OjbyBgdGFyX3Zpem5ldHdvcmsoKWAgcXVlIHZhaSBnZXJhciBhIHNlZ3VpbnRlIGZpZ3VyYSAoZGFkbyBhIHNpdHVhw6fDo28gZGVzY3JpdGEgYWNpbWEpCgpgYGB7ciBlY2hvPUZBTFNFLGV2YWw9VFJVRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3MvdGFyZ2V0X211ZGFuY2EucG5nIikKYGBgCgpBIGlkZW50aWZpY2HDp8OjbyBkbyBsb2NhbCBleGF0byBkZSBtdWRhbsOnYSBkbyB3b3JrZmxvdyDDqSBwb3Nzw612ZWwgZ3Jhw6dhcyBhbyB0YXJnZXQsIGV2aXRhbmRvIHF1ZSB0ZW5oYW1vcyBxdWUgcm9kYXIgdG9kbyBvIHdvcmtmbG93IGRvIGluw61jaW8gYW8gZmltLCBwcsOhdGljYSBxdWUgw6kgY2hhbWFkYSBkZSBbbG9vcCBTaXN5cGhlYW5vXShodHRwczovL3d3dy53b3JsZGhpc3Rvcnkub3JnL3Npc3lwaHVzLykKCmBgYHtyIGVjaG89RkFMU0UsZXZhbD1UUlVFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiZmlncy9TaXN5cGh1cy5qcGVnIikKYGBgCgo=