2017-09-14 6 views
1

J'ai besoin de lire plusieurs fichiers dans R, d'effectuer un nettoyage, puis de les combiner en une seule trame de données. Les fichiers commencent tous essentiellement comme ceci:R Importer des fichiers avec un nombre différent de lignes initiales à ignorer

=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2016.07.11 09:47:35 =~=~=~=~=~=~=~=~=~=~=~= 
up 
Upload #18 
Reader: S1 Site: AA 
--------- upload 18 start --------- 
Type,Date,Time,Duration,Type,Tag ID,Ant,Count,Gap 
E,2016-07-05,11:45:44.17,"upload 17 complete" 
D,2016-07-05,11:46:24.69,00:00:00.87,HA,900_226000745055,A2,8,1102 
D,2016-07-05,11:46:43.23,00:00:01.12,HA,900_226000745055,A2,10,143 

La ligne avec les en-têtes de colonnes est "Type,Date,Time,Duration,Type,Tag ID,Ant,Count,Gap". Les données devraient avoir 9 colonnes. Le problème est que le nombre de lignes au-dessus de la chaîne d'en-tête est différent pour chaque fichier, donc je ne peux pas simplement utiliser skip = 5. J'ai aussi besoin de lignes commençant par "D,", tout le reste est des messages, pas des données.

Quelle est la meilleure façon de lire dans mes fichiers, en m'assurant que j'ai 9 colonnes et en sautant toutes les ordures?
J'utilise la fonction read_csv du package readr() car elle a généré le moins de problèmes de mise en forme. Mais, je suis ouvert à toutes les nouvelles idées, y compris un moyen de lire en quelques lignes qui commencent par "D,". J'ai joué avec en utilisant read.table et skip = grep("Type," readLines(i)), mais il ne semble pas trouver la chaîne d'en-tête correctement. Voici mon code de base:

dataFiles <- Sys.glob("*.*") 
datalist <- list() 
for (i in dataFiles) { 
d01 <- read_csv(i, col_names = F, na = "NA", skip = 35) 
# do clean-up stuff 
datalist[[i]] <- d 
} 
+0

est la valeur 'd' dans la colonne' type' cohérente? –

+0

Pouvez-vous retravailler votre question avec des données reproductibles afin que d'autres puissent la tester? En principe, vous êtes sur la bonne voie car c'est un problème qui peut être résolu en lisant un sous-ensemble de vos données (utilisez le paramètre 'n_max' dans' read_csv') comme données temporaires et en utilisant un grep pour stocker l'index pour le nombre approprié de lignes à ignorer pour chaque fichier de données. – dshkol

+0

Oui @ D.sen, 'D' est toujours dans la colonne' Type'. – notacodr

Répondre

1

Une autre solution R de base est la suivante: Vous avez lu dans le fichier par des lignes, obtenir les indices de lignes, qui commencent par « D » et la ligne d'en-tête. Après, vous divisez simplement ces lignes par "," et mettez-le dans un data.frame et affectez-lui les noms de la rangée d'en-tête.

lines <- readLines(i) 
dataRows <- grep("^D,", lines) 

names <- unlist(strsplit(lines[grep("Type,", lines)], split = ",")) 

data <- as.data.frame(matrix(unlist(strsplit(lines[dataRows], ",")), nrow = length(dataRows), byrow=T)) 
names(data) <- names 

Sortie:

Type  Date  Time Duration Type   Tag ID Ant Count Gap 
1  D 2016-07-05 11:46:24.69 00:00:00.87 HA 900_226000745055 A2  8 1102 
2  D 2016-07-05 11:46:43.23 00:00:01.12 HA 900_226000745055 A2 10 143 
+0

C'était la solution la plus propre et la plus facile à cause de problèmes de formatage inattendus. Merci à bmosov01 et D.sen pour leurs options utiles. – notacodr

1

Si votre ligne d'en-tête commence toujours par le mot Type, vous pouvez simplement omettre l'option skip de votre lecture initiale, puis retirez toutes les lignes avant la ligne d'en-tête. Voici un code pour vous aider à démarrer (non testé):

dataFiles <- Sys.glob("*.*") 
datalist <- list() 
for (i in dataFiles) { 
d01 <- read_csv(i, col_names = F, na = "NA") 
headerRow <- which(d01[,1] == 'Type') 
d01 <- d01[headerRow+1,] # This keeps all rows after the header row. 
# do clean-up stuff 
datalist[[i]] <- d 
} 

Si vous voulez garder l'en-tête, vous pouvez utiliser:

for (i in dataFiles) { 
d01 <- read_csv(i, col_names = F, na = "NA") 
headerRow <- which(d01[,1] == 'Type') 
d01 <- d01[headerRow+1,] # This keeps all rows after the header row. 
header <- d01[headerRow,] # Get names from header row. 
setNames(d01, header) # Assign names. 
# do clean-up stuff 
datalist[[i]] <- d 
} 
1

Vous pouvez utiliser une fonction personnalisée à boucle sur chaque fichier et filtrer uniquement ceux qui commencent par D dans la colonne type et lier tous ensemble à la fin. Déposez le bind_rows si vous les souhaitez en tant que listes séparées.

load_data <-function(path) { 
    require(dplyr) 
    setwd(path) 
    files <- dir() 
    read_files <- function(x) { 
    data_file <- read.csv(paste(path, "/", x, ".csv", sep = ""), stringsAsFactors = FALSE, na.strings=c("","NA")) 
    row.number <- grep("^Type$", data_file[,1]) 
    colnames(data_file) <- data_file[row.number,] 
    data_file <- data_file[-c(1:row.number+1),] 
    data_file <- data_file %>% 
     filter(grepl("^D", Type)) 
    return(data_file) 
    } 
    data <- lapply(files, read_files) 
} 

list_of_file <- bind_rows(load_data("YOUR_FOLDER_PATH"))