R: Чтение в подмножестве строк и преобразование его в обычный формат (предпочтителен метод data.table). - PullRequest
2 голосов
/ 10 марта 2019

У меня есть файл, который содержит более ста миллионов строк и разбросан по всему полю. В полях есть дополнительные разделители табуляции. Мне нужно прочитать проблемные строки в R, игнорируя остальные из-за большого размера файла.

Пример txt файла с дополнительными разделителями в некоторых строках:

text_file <-"My\tname\tis\tAlpha\nMy\tname\tis\t\t\tBravo\nMy\tname\tis\tCharlie\nMy\tname\tis\t\t\tDelta\nMy\tname\tis\tEcho"

Первое, что я попробовал, было использование функции 'readLines', однако, хотя я могу указать строку для остановки на ней, она все равно будет читать все остальное до этой точки, которая все еще может быть слишком большой

readLines(textConnection(text_file), n = 4)

[1] "My\tname\tis\tAlpha"     "My\tname\tis\t\t\tBravo" "My\tname\tis\tCharlie"   "My\tname\tis\t\t\tDelta"

Затем я понял, что мог бы также использовать другие функции импорта набора данных, если бы указывал разделитель, который, вероятно, никогда не появится. Функция «fread» из пакета data.table была бы идеальной для этого, поскольку это самый быстрый способ иметь дело с большими наборами данных, такими как мой, однако, когда я попробовал это сделать, данные были в формате, с которым я не мог по-настоящему работать дальше:

library(data.table)
library(stringi)

lines <- fread(text_file, sep = NULL, header = FALSE, skip = 1, nrows = 3)

> lines
                        V1
1: My\tname\tis\t\t\tBravo
2:   My\tname\tis\tCharlie
3: My\tname\tis\t\t\tDelta

> invalid_delimiter_rows <- which(stri_count_regex(lines, "\\t") != 3)
Warning message:
In stri_count_regex(lines, "\\t") :
  argument is not an atomic vector; coercing

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

> class(lines)

[1] "data.table" "data.frame"

> as.character(lines)

[1] "c(\"My\\tname\\tis\\t\\t\\tBravo\", \"My\\tname\\tis\\tCharlie\", \"My\\tname\\tis\\t\\t\\tDelta\")"

1 Ответ

1 голос
/ 11 марта 2019

Давайте повторим процесс до fread() import:

# your example string
text_file <-"My\tname\tis\tAlpha\nMy\tname\tis\t\t\tBravo\nMy\tname\tis\tCharlie\nMy\tname\tis\t\t\tDelta\nMy\tname\tis\tEcho"

# import
library(data.table)
lines <- fread(text_file, sep = NULL, header = FALSE, skip = 1, nrows = 5)
lines
                        V1
1: My\tname\tis\t\t\tBravo
2:   My\tname\tis\tCharlie
3: My\tname\tis\t\t\tDelta
4:      My\tname\tis\tEcho

При попытке

as.character(lines)
[1] "c(\"My\\tname\\tis\\t\\t\\tBravo\", \"My\\tname\\tis\\tCharlie\", \"My\\tname\\tis\\t\\t\\tDelta\", \"My\\tname\\tis\\tEcho\")"

он преобразует все символы data.table, поэтому каждый столбец будет объединеннымвектор.См. Ниже:

as.character(data.table(lines$V1, lines$V1))
[1] "c(\"My\\tname\\tis\\t\\t\\tBravo\", \"My\\tname\\tis\\tCharlie\", \"My\\tname\\tis\\t\\t\\tDelta\", \"My\\tname\\tis\\tEcho\")"
[2] "c(\"My\\tname\\tis\\t\\t\\tBravo\", \"My\\tname\\tis\\tCharlie\", \"My\\tname\\tis\\t\\t\\tDelta\", \"My\\tname\\tis\\tEcho\")"

Что вам нужно, так это извлечь просто lines$V1, который уже является символьным вектором.

lines$V1
[1] "My\tname\tis\t\t\tBravo" "My\tname\tis\tCharlie"   "My\tname\tis\t\t\tDelta" "My\tname\tis\tEcho"     
...