R: pobranie pliku CSV z jedną uszkodzoną linijką

2-lut-2020

Instrukcje dostępne w języku R (ale też w innych), po cichu zakładają, że dane na jakich pracują są czyste. Pisząc czyste, mam na myśli o ustalonej strukturze. Niestety, może  się zdarzyć, że jedna linijka znajdująca się gdzieś pośrodku jest… uszkodzona. Pobranie całego pliku kończy się wtedy błedem. Oto przykład:

> cars <- fread(
+ input ='https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data',
+ header = F,
+ sep = ' ',
+ na.strings = '?',
+ fill = T)
 [0%] Downloaded 0 bytes...
Warning message:
In fread(input = "https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data", :
 Stopped early on line 293. Expected 12 fields but found 13. Consider fill=TRUE and comment.char=. 
First discarded non-empty line: <<18.5 8 360.0 150.0 3940. 13.0 79 1 "chrysler lebaron town @ country (sw)">>

Gdyby takie dane były dostarczane przez np. inny dział firmy, najprościej byłoby się z nimi skontaktować i zwrócić uwagę na nieprawidłowo utworzony plik. Jeśli jednak takiej możliwości nie ma… można próbować obejść problem.

Propozycja nr 1 – opuśćmy uszkodzoną linijkę

Skorzystamy z parametrów nrow (ile wierszy pobrać) oraz skip (ile opuścić). Aby pobrać pierwsze 292 wiersze uruchom

cars <- fread(
 input ='https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data',
 header = F,
 sep = ' ',
 na.strings = '?',
 fill = T,
 nrow=292)

A  żeby pobrać od 294 linijki:

cars <- fread(
 input ='https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data',
 header = F,
 sep = ' ',
 na.strings = '?',
 fill = T,
 skip=293)

Gdyby przyszło Ci do głowy sprawdzenie takiej niepoprawnej linijki, możesz pobrać tylko ją:

cars <- fread(
 input ='https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data',
 header = F,
 sep = ' ',
 na.strings = '?',
 fill = T,
 skip=292, nrow=1)

Jeśli dokładniej przyjrzeć się tej linijce stanie się jasne, że chodzi tam o to, że jeden z separatorów jest tabulatorem zamiast spacją. I tak dochodzimy do

Porpozycji nr 2 – pobranie pliku tekstowego i jego oczyszczenie

Zaczynamy od pobrania danych do zmiennej lokalnej, ale sam plik jest czytany po prostu jako tekst, bez żadnej interpretacji:

x <- readLines("https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data")

Mając tekst w zmiennej, można go oczyścić. Będzie to polegało na zamianie tabulatora na spację. Zaraz potem, oczyszczony tekst można zapisać lokalnie:

x <- gsub("\t", " ", x)
writeLines(x,'c:/temp/x,csv')

A mając lokalny plik, można go wczytać korzystając z oryginalnego polecenia fread:

fread(
 input ='c:/temp/x,csv',
 header = F,
 sep = ' ',
 na.strings = '?',
 fill = T)

 

Komentarze są wyłączone

Autor: Rafał Kraik