R data.table fread не может читать столбцы неправильной длины, когда строки большего размера не появляются в начале файла

#r #data.table

#r #data.table

Вопрос:

Я хочу прочитать файл CSV с помощью data.table функции fread . Файл CSV содержит большое количество записей с 9 столбцами, а затем большое количество записей с 10 столбцами. Использование аргумента fill=TRUE не решает проблему. Вот несколько примеров данных, которые демонстрируют мою проблему:

 library(data.table)
short <- rep("1,1,1", 1000)
long <- rep("1,1,1,2", 1000)
write(c(short, long), "shortLong.csv")
write(c(long, short), "longShort.csv")
  

Когда я читаю в файле, который имеет короткие длины столбцов, а затем длинные длины столбцов, я получаю эту ошибку:

 fread("shortLong.csv", fill=TRUE)
Error in fread("shortLong.csv", fill = TRUE) : 
  Expecting 3 cols, but line 1001 contains text after processing all cols. Try again with fill=TRUE. Another reason could be that fread's logic in distinguishing one or more fields having embedded sep=',' and/or (unescaped) 'n' characters within unbalanced unescaped quotes has failed. If quote='' doesn't help, please file an issue to figure out if the logic could be improved
  

Однако, когда я читаю файл с длинной длиной столбца, а затем с короткой длиной столбца, он считывает файл без проблем и заполняет недостающие значения в коротких столбцах с помощью NA , что я и хочу:

 fread("longShort.csv", fill=TRUE)
      V1 V2 V3 V4
   1:  1  1  1  2
   2:  1  1  1  2
   3:  1  1  1  2
   4:  1  1  1  2
   5:  1  1  1  2
  ---            
1996:  1  1  1 NA
1997:  1  1  1 NA
1998:  1  1  1 NA
1999:  1  1  1 NA
2000:  1  1  1 NA
  

Эта ошибка, по-видимому, вызвана большим количеством коротких столбцов перед длинными столбцами, так как при смешивании коротких и длинных столбцов проблем не возникло:

 mixed <- rep(c("1,1,1", "1,1,1,2"), 1000)
write(mixed, "mixed.csv")
fread("mixed.csv", fill=TRUE)
      V1 V2 V3 V4
   1:  1  1  1 NA
   2:  1  1  1  2
   3:  1  1  1 NA
   4:  1  1  1  2
   5:  1  1  1 NA
  ---            
1996:  1  1  1  2
1997:  1  1  1 NA
1998:  1  1  1  2
1999:  1  1  1 NA
2000:  1  1  1  2
  

Я подозреваю, что это различие в поведении может быть связано с тем, что fread просматривает столбцы заранее, но не просматривает весь файл и устанавливает максимальный номер столбца на основе самого длинного из просмотренных (однако я не очень знаком с внутренней работой функции).

Есть ли какой-либо способ правильно прочитать мои данные с помощью fread ? Я думаю, что, вероятно, я мог бы собрать какое-нибудь хакерское решение и обойти fread , но мне нравится производительность, и я не хочу резко замедлять свой код. Спасибо!

Комментарии:

1. К сожалению, я в Windows. Я надеюсь, что хотел бы иметь возможность решить эту проблему без необходимости изменять базовый файл вообще (в настоящее время я вручную вводил и добавлял одну из длинных строк в начало, что работает, но не то, что я бы предпочел)

Ответ №1:

Обратите внимание, что то, что у вас есть, не является файлом CSV, поскольку у него нет заголовка. Если мы добавим заголовок, это сработает. Сначала используйте fread для чтения в виде одного поля в строке, задающего вектор символов Lines . Исходя из этого, вычислите максимальное количество полей n . Наконец, перечитайте Lines после добавления к нему заголовка.

 Lines <- fread("shortLong.csv", sep = "")[[1]]
n <- max(count.fields(textConnection(Lines), sep = ","))
fread(text = c(toString(1:n), Lines), header = TRUE, fill = TRUE)
  

Комментарии:

1. Спасибо за ответ! Первая строка выдала мне эту ошибку: Error in fread("shortLong.csv", sep = "") : 'sep' must be 'auto' or a single character

2. Обновите data.table до последней версии или используйте какой-либо символ, который не отображается в файле.

3. В качестве аргумента в первой строке необходимо указать header=FALSE , иначе первая строка будет интерпретирована как имя столбца, а конечная таблица будет короче на 1 строку