AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79280949
Accepted
denis
denis
Asked: 2024-12-14 23:59:33 +0800 CST2024-12-14 23:59:33 +0800 CST 2024-12-14 23:59:33 +0800 CST

Entre muitas subpastas, encontre CSVs começando com uma determinada string e dentro de ZIPs ou não, e mescle-os enquanto adiciona seus nomes em uma nova coluna com R

  • 772

Em uma pasta ( path = "D:/DataLogs/), tenho várias subpastas. Dentro dessas subpastas, gostaria de recuperar todos os csv começando apenas com "QCLog" e mesclá-los ( rbind) em um único data.frame, enquanto crio uma primeira coluna nova incluindo o caminho/nome completo desses csv QCLog.

As duas dificuldades são:

  1. Em algumas subpastas, pode haver arquivos csv (começando com QCLog ou não) diretamente acessíveis e outros localizados em vários arquivos zip (exemplos dentro dos retângulos verdes abaixo).
  2. Todos os CSVs têm o mesmo número de colunas (n=66) e os mesmos cabeçalhos. No entanto, alguns cabeçalhos contêm acentos ou símbolos, quase todas as segundas colunas (uma em cada duas) têm exatamente o mesmo nome de cabeçalho e algumas colunas estão vazias (sem NAs).

Isso é viável?
Obrigado pela ajuda

insira a descrição da imagem aqui

  • 3 3 respostas
  • 108 Views

3 respostas

  • Voted
  1. Best Answer
    denis
    2024-12-15T23:30:40+08:002024-12-15T23:30:40+08:00

    O código a seguir, embora um pouco longo, funciona bem e rápido:

    library(tidyverse)
    library(data.table)
    
    # paths
    main_path <- "D:/DataLogs/" # target directory
    zip_path <- "D:/DataLogs/Zip_files/" # subfolder where the zips will be unzipped
    
    # specific string of csv file name
    str_csv <- "QCLog"
    
    # list csv
    csv_nozip_list <- list.files(main_path, paste0(str_csv, ".*\\.csv"), recursive = TRUE, full.names = TRUE) # list of QCLog csv that ARE NOT within zip
    zip_list <- list.files(main_path, "\\.zip", recursive = TRUE, full.names = TRUE) # list of all csv -including QCLog- that ARE within zip
    unzip_files <- lapply(zip_list, unzip, exdir = zip_path) # unzip all CSV in the zip_path subfolder
    csv_zip_list <- list.files(zip_path, paste0(str_csv, ".*\\.csv"), recursive = TRUE, full.names = TRUE) # list only QCLog that have been decompressed in zip_path
    
    # read matching files while adding a new filename column
    csv_nozip_read <- lapply(csv_nozip_list, function(x) {data.table(fread(x), "filename" = x)})
    csv_zip_read <- lapply(csv_zip_list, function(x) {data.table(fread(x), "filename" = x)})
    
    # rbind lists
    csv_nozip_rbind <- data.table::rbindlist(csv_nozip_read)
    csv_zip_rbind <- data.table::rbindlist(csv_zip_read)
    
    # rbind selected csv
    dat <- rbind(csv_nozip_rbind, csv_zip_rbind) |>
      distinct() |> # if needed
      relocate(filename)
    
    • 1
  2. Rui Barradas
    2024-12-15T01:10:39+08:002024-12-15T01:10:39+08:00

    Algo como o seguinte pode funcionar. Não testado.

    # function to unzip the csv files 
    # first get the csv filenames, then extract them to a temp directory
    # return one data.frame only
    read_csv_in_zip_file <- function(filename, tmpdir) {
      csv_files <- unzip(filename, list = TRUE)[["Name"]]
      i <- grep("QCLog.*\\.csv", csv_files)
      fls <- unzip(filename, files = csv_files[i], exdir = tmpdir)
      df_list <- lapply(fls, read.csv)
      res <- Map(\(x, f) {
        x$filename <- basename(f)
        x
      }, df_list, fls)
      res <- do.call(rbind, res)
      row.names(res) <- NULL
      res
    }
    
    # where to put the unziped files
    tmp_dir <- tempdir()
    
    path <- "D:/DataLogs"
    pattern <- "QCLog.*\\.csv|\\.zip"
    fls <- list.files(path = path, pattern = pattern, full.names = TRUE, recursive = TRUE)
    
    df_list <- lapply(fls, \(f) {
      if(grep("\\.zip", f)) {
        read_csv_in_zip_file(f, tmp_dir)
      } else {
        res <- read.csv(f)
        res$filename <- f
        res
      }
    })
    
    # one data.frame only
    df_all <- do.call(rbind, df_list)
    
    # final clean up
    unlink(tmp_dir, recursive = TRUE)
    # rm(df_list)
    
    • 0
  3. G. Grothendieck
    2024-12-15T22:18:42+08:002024-12-15T22:18:42+08:00

    Com base nas afirmações da questão, assumimos que cada arquivo csv

    • tem um caminho de D:/datalogs/*/QCLog*.csvou
    • está em um arquivo zip com o mesmo caminho, exceto por ter extensão .zip e os nomes dos arquivos também começam com QCLog

    e que todos os arquivos csv têm as mesmas colunas e cabeçalhos. Se estes não forem satisfeitos, pode ou não funcionar. Se não, você pode modificar o código com base no que você realmente tem usando seu conhecimento do que você realmente tem ou pode editar os arquivos para colocá-los no formato declarado na pergunta.

    Se isso funciona vai depender do que você realmente tem, mas sua heurística geralmente funciona e é curta. Se estiver ok ter os nomes das linhas identificando a fonte em vez de uma coluna separada, então podemos omitir as duas últimas linhas.

    library(rio)
    library(tools)
    
    root <- "D:/datalogs/*"
    csv_files <- Sys.glob(file.path(root, "QCLog*.csv"))
    zip_files <- Sys.glob(file.path(root, "*.zip"))
    L <- c(import_list(csv_files), import_list(zip_files))
    L <- L[ grep("QCLog.*csv", names(L)) ]
    dat <- do.call("rbind", L)
    
    dat$id <- file_path_sans_ext(rownames(dat))
    rownames(dat) <- NULL
    

    Atualizar

    Código adicionado para garantir que somente QCLog...csvarquivos sejam usados ​​em dat.

    • 0

relate perguntas

  • Adicionar número de série para atividade de cópia ao blob

  • A fonte dinâmica do empacotador duplica artefatos

  • Selecione linhas por grupo com 1s consecutivos

  • Lista de chamada de API de gráfico subscritoSkus estados Privilégios insuficientes enquanto os privilégios são concedidos

  • Função para criar DFs separados com base no valor da coluna

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve