Computação reproduzível em R. Como separar código e dados?

Muitas vezes, são necessários cálculos periódicos e a preparação de um relatório consolidado sobre dados auto-suficientes. Essa. de acordo com os dados armazenados como arquivos. Podem ser dados coletados de fontes abertas, vários documentos e tabelas do Excel, downloads de sistemas corporativos. Os dados brutos podem ocupar vários megabytes ou vários gigabytes. Os dados podem ser despersonalizados ou conter informações confidenciais. No caso em que o código de cálculo é colocado no repositório e o trabalho é realizado por mais de uma pessoa em mais de um computador, surge o problema de manter a consistência do código e dos dados. Ao mesmo tempo, ainda é necessário garantir a conformidade com diferentes direitos de acesso ao código e dados. O que fazer?


É uma continuação de publicações anteriores .


O RStudio agora está desenvolvendo ativamente um pacote pinspara resolver esse problema. Infelizmente, as soluções de back-end usadas são um tanto impopulares e caras de usar na vastidão do nosso país. AWS, Azure, Google cloud ... para cada um que você paga, pelo armazenamento e pelo tráfego. O AWS4 pinsainda não suporta autenticação , portanto, a nuvem Yandex também fica à margem, embora não seja gratuita.


Por outro lado, as equipes de analistas que trabalham em tarefas específicas geralmente são pequenas (não mais que 5 a 10 pessoas). Muitos usam o Google drive, One drive, etc., em formato pago ou gratuito. Por que não aproveitar os recursos já adquiridos? Abaixo está um dos possíveis fluxos de trabalho.


Plano geral


  1. Os cálculos devem ser realizados localmente na máquina, o que significa que a máquina deve ter uma réplica real de todos os dados necessários para o cálculo.
  2. O código deve estar sob controle de versão. Os dados não devem cair de forma alguma (volume potencial e confidencialidade). Armazenaremos a réplica de dados em uma pasta separada no projeto (incluindo-a .gitignore) ou em um diretório externo relativo ao projeto.
  3. O mestre de dados será armazenado pelo Google Drive. Nós colocamos os direitos para acessar diretórios nele.

Continua sendo o caso dos pequenos. É necessário implementar a funcionalidade de sincronização da réplica de dados local com a nuvem. Autorização e autenticação são fornecidas pelo google.


Abaixo está o código.


library(googledrive)
library(memoise)
#    google disk
drive_user()
updateGdCache(here::here("data/"), cloud_folder = "XXX___jZnIW3jdkbdxK0iazx7t63Dc")

Função para sincronização de cache
updateGdCache <- function(local_folder, cloud_folder){
  #     
  cache_fname <- "gdrive_sig.Rds"
  # 0.  memoise     
  getGdriveFolder <- memoise(function(gdrive_folder){
    drive_ls(as_id(gdrive_folder), recursive = FALSE)
  })

  # 1.        
  cloud_gdrive_sig <- purrr::possibly(getGdriveFolder, NULL)(cloud_folder)
  #          ,     
  if(is.null(cloud_gdrive_sig)) {
    message("Some Google Drive issues happened. Can't update cache")
    return()
  }
  # 2.       
  fdir <- if(fs::is_dir(local_folder)) local_folder else fs::path_dir(local_folder)

  # 3.       
  local_files <- fs::dir_ls(fdir, recurse = FALSE) %>%
    fs::path_file()

  # 4.        
  local_gdrive_sig <- purrr::possibly(readRDS, NULL, quiet = TRUE)(fs::path(fdir, cache_fname))
  if(is.null(local_gdrive_sig)){
    #    ,   ,     
    #  ,   
    local_gdrive_sig <- cloud_gdrive_sig %>%
      dplyr::filter(row_number() == -1)
  }
  #         
  local_gdrive_sig <- local_gdrive_sig %>%
    dplyr::filter(name %in% local_files)

  # 5.      ,    ,   
  #  ,       
  reconcile_tbl <- cloud_gdrive_sig %>%
    dplyr::rename(drive_resource_cloud = drive_resource) %>%
    dplyr::left_join(local_gdrive_sig, by = c("name", "id")) %>%
    tidyr::hoist(drive_resource_cloud, cloud_modified_time = "modifiedTime") %>%
    tidyr::hoist(drive_resource, local_modified_time = "modifiedTime") %>%
    # TODO:   ,       
    #       = NA
    dplyr::mutate(not_in_sync = is.na(local_modified_time) | cloud_modified_time != local_modified_time)

  # 6.    
  syncFile <- function(fpath, id){
    res <- purrr::possibly(drive_download, otherwise = NULL)(as_id(id), path = fpath, overwrite = TRUE, verbose = TRUE)
    ifelse(is.null(res), FALSE, TRUE)
  }
  #  ,        ,   
  sync_gdrive_sig <- reconcile_tbl %>%
    dplyr::filter(not_in_sync == TRUE) %>%
    dplyr::mutate(fpath = fs::path(fdir, name)) %>%
    dplyr::mutate(sync_status = purrr::map2_lgl(fpath, id, syncFile)) %>%
    dplyr::select(name, id, sync_status)

  # 7.      ,   
  #   
  cloud_gdrive_sig %>%
    #   
    dplyr::anti_join(dplyr::filter(sync_gdrive_sig, sync_status == FALSE), by = c("name", "id")) %>%
    saveRDS(fs::path(fdir, cache_fname))
}

Especifique o identificador da pasta no Google Drive como o caminho, você pode acessá-lo na barra de endereços do navegador. O identificador permanecerá inalterado, mesmo que a pasta seja movida na unidade.



Simples, compacto, conveniente e gratuito.


Par de comentários


  1. Há problemas com a codificação para a gargleversão 0.4.0. É necessário carregar a versão dev. Mais detalhes aqui .
  2. Há problemas com a autorização no servidor RStudio “Não é possível autorizar a partir do servidor RStudio nº 79 {Fechado}” , mas as idéias para uma solução alternativa podem ser encontradas aqui .

Publicação anterior - “Programação e árvore de Natal, elas podem ser combinadas?” .

Source: https://habr.com/ru/post/undefined/


All Articles