2010-06-16 5 views
3

Le logiciel que j'utilise génère des fichiers journaux avec un nombre variable de lignes d'informations récapitulatives suivies de nombreuses données délimitées par des tabulations. J'essaye d'écrire une fonction qui lira les données de ces dossiers de notation dans une trame de données en ignorant les informations de résumé. Les informations de résumé ne contient jamais un onglet, donc la fonction suivante fonctionne:Comment ignorer des lignes supplémentaires avant l'en-tête d'un fichier délimité délimité par des tabulations dans R

read.parameters <- function(file.name, ...){ 
    lines <- scan(file.name, what="character", sep="\n") 
    first.line <- min(grep("\\t", lines)) 
    return(read.delim(file.name, skip=first.line-1, ...)) 
} 

Cependant, ces fichiers journaux sont assez grandes, et la lecture si le fichier est deux fois très lent. Sûrement il y a un meilleur moyen?

Edité à ajouter:

Marek a suggéré d'utiliser un objet textConnection. La façon dont il a suggéré dans la réponse échoue sur un gros fichier, mais les travaux suivants:

read.parameters <- function(file.name, ...){ 
    conn = file(file.name, "r") 
    on.exit(close(conn)) 
    repeat{ 
    line = readLines(conn, 1) 
    if (length(grep("\\t", line))) { 
     pushBack(line, conn) 
     break}} 
    df <- read.delim(conn, ...) 
    return(df)} 

Edité à nouveau: Merci Marek pour améliorer encore la fonction ci-dessus.

+1

Pour fermer la connexion en toute sécurité, vous pouvez utiliser la fonction 'on.exit'. Juste après 'conn = file (...)' ajouter une ligne 'on.exit (close (conn))'. Ensuite, lorsqu'une fonction termine une tâche (normalement ou avec une erreur), la connexion sera fermée. Sinon, lorsque vous avez une erreur quelque part entre 'file' et' close', la connexion sera ouverte. – Marek

+0

Merci, bonne technique. Je l'ai mis à jour. –

Répondre

1

Vous n'avez pas besoin de lire deux fois. Utilisez textConnection lors du premier résultat.

read.parameters <- function(file.name, ...){ 
    lines <- scan(file.name, what="character", sep="\n") # you got "tmp.log" here, i suppose file.name should be 
    first.line <- min(grep("\\t", lines)) 
    return(read.delim(textConnection(lines), skip=first.line-1, ...)) 
} 
+0

J'ai corrigé la faute de frappe. Merci pour la suggestion d'utiliser textConnection, bien que la fonction que vous lui avez donnée ne fonctionne pas. Je pense que je dois d'abord faire le textConnection, puis lancer l'analyse, puis utiliser pushBack pour rembobiner le fichier. –

+0

Étrange. Je l'ai testé et travaille pour mes fausses données. Vous avez un message d'erreur ou des résultats vides? – Marek

+0

Exemple: 'cat (c (" ds "," sdds "," sddfsd "," a \ tb \ tc "," 1 \ t2 \ t3 "," 1 \ t2 \ t3 "), file =" test. txt ", sep =" \ n ")' then 'read.parameters (" test.txt ")' renvoie 'data.frame' avec 3 colonnes et 2 lignes. – Marek

0

Si vous pouvez être sûr que les informations d'en-tête ne seront pas plus de N lignes, par ex. N = 200, puis essayez:

scan (..., nlines = N)

De cette façon, vous ne relisez plus de N lignes.

+0

C'est une approche décente, mais je ne peux pas vraiment garantir quoi que ce soit au sujet de la taille de l'en-tête. Je suis assez satisfait de ma fonction en utilisant un pointeur de fichier. –

Questions connexes