Как прочитать файл определенного формата в R?

Я хотел бы прочитать файл, в котором каждая строка представляет собой набор данных, содержащий дату, некоторый текст, а также числа. Пример:

Fri Dec 11 12:40:01 CET 2015    Uptime: 108491  Threads: 2  Questions: 576603  Slow queries: 10  Opens: 2238  Flush tables: 1  Open tables: 7  Queries per second avg: 5.314
Fri Dec 11 12:50:01 CET 2015    Uptime: 109090  Threads: 2  Questions: 580407  Slow queries: 10  Opens: 2253  Flush tables: 1  Open tables: 6  Queries per second avg: 5.320
Fri Dec 11 13:00:01 CET 2015    Uptime: 109690  Threads: 2  Questions: 583895  Slow queries: 10  Opens: 2268  Flush tables: 1  Open tables: 8  Queries per second avg: 5.323
Fri Dec 11 13:10:01 CET 2015    Uptime: 110290  Threads: 1  Questions: 586891  Slow queries: 10  Opens: 2279  Flush tables: 1  Open tables: 6  Queries per second avg: 5.321
Fri Dec 11 13:20:01 CET 2015    Uptime: 110890  Threads: 2  Questions: 590871  Slow queries: 10  Opens: 2292  Flush tables: 1  Open tables: 5  Queries per second avg: 5.328

Нет общего символа-разделителя (как в CSV), но формат можно описать довольно хорошо, так как можно использовать табуляции, символы и текст.

%DATESTRING%\tUptime: %uptime%  Threads: %threads%  Questions: %questions%  Slow queries: %slow%  Opens: %opens%  Flush tables: %flush%  Open tables: %otables%  Queries per second avg: %qps%

Есть ли функция, которая берет описание формата и файла и заполняет data.frame заданными данными?


person Edward    schedule 11.12.2015    source источник
comment
Мне повезло, я закинул его в Excel, поправил там, где он нужен, а затем сохранил его как csv.   -  person TBSRounder    schedule 11.12.2015
comment
@rawr тот факт, что имена столбцов включены в записи строк, нестандартен для фиксированной ширины, с которой я работал...   -  person MichaelChirico    schedule 11.12.2015
comment
@MichaelChirico да, ты прав   -  person rawr    schedule 11.12.2015
comment
@rawr все же я думаю, что этот подход работает - читайте как фиксированную ширину, а затем подмножайте имена столбцов   -  person MichaelChirico    schedule 11.12.2015


Ответы (2)


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

Начнем с загрузки данных, в данном случае из строки

raw <- 'Fri Dec 11 12:40:01 CET 2015    Uptime: 108491  Threads: 2     Questions: 576603  Slow queries: 10  Opens: 2238  Flush tables: 1  Open tables: 7  Queries per second avg: 5.314
Fri Dec 11 12:50:01 CET 2015    Uptime: 109090  Threads: 2  Questions: 580407  Slow queries: 10  Opens: 2253  Flush tables: 1  Open tables: 6  Queries per second avg: 5.320
Fri Dec 11 13:00:01 CET 2015    Uptime: 109690  Threads: 2  Questions: 583895  Slow queries: 10  Opens: 2268  Flush tables: 1  Open tables: 8  Queries per second avg: 5.323
Fri Dec 11 13:10:01 CET 2015    Uptime: 110290  Threads: 1  Questions: 586891  Slow queries: 10  Opens: 2279  Flush tables: 1  Open tables: 6  Queries per second avg: 5.321
Fri Dec 11 13:20:01 CET 2015    Uptime: 110890  Threads: 2  Questions: 590871  Slow queries: 10  Opens: 2292  Flush tables: 1  Open tables: 5  Queries per second avg: 5.328'

df <- read.csv(textConnection(raw), header=F)

Здесь я использовал read.csv, чтобы получить его как фрейм данных, но вы также можете просто использовать readLines и добавить его во фрейм самостоятельно.

Потом обрабатываем

library(tidyr)
> processed <- df %>% extract(V1,
  c("Date", "Uptime", "Threads", "Questions"),
  "(.*) *Uptime: (\\d+) *Threads: (\\d+) *Questions: (\\d+)")
> processed
                              Date Uptime Threads Questions
1 Fri Dec 11 12:40:01 CET 2015     108491       2    576603
2 Fri Dec 11 12:50:01 CET 2015     109090       2    580407
3 Fri Dec 11 13:00:01 CET 2015     109690       2    583895
4 Fri Dec 11 13:10:01 CET 2015     110290       1    586891
5 Fri Dec 11 13:20:01 CET 2015     110890       2    590871

Должно быть понятно, как извлечь отсюда остальные столбцы.

person user295691    schedule 11.12.2015

Еще два варианта:

txt <- "Fri Dec 11 12:40:01 CET 2015    Uptime: 108491  Threads: 2  Questions: 576603  Slow queries: 10  Opens: 2238  Flush tables: 1  Open tables: 7  Queries per second avg: 5.314
Fri Dec 11 12:50:01 CET 2015    Uptime: 109090  Threads: 2  Questions: 580407  Slow queries: 10  Opens: 2253  Flush tables: 1  Open tables: 6  Queries per second avg: 5.320
Fri Dec 11 13:00:01 CET 2015    Uptime: 109690  Threads: 2  Questions: 583895  Slow queries: 10  Opens: 2268  Flush tables: 1  Open tables: 8  Queries per second avg: 5.323
Fri Dec 11 13:10:01 CET 2015    Uptime: 110290  Threads: 1  Questions: 586891  Slow queries: 10  Opens: 2279  Flush tables: 1  Open tables: 6  Queries per second avg: 5.321
Fri Dec 11 13:20:01 CET 2015    Uptime: 110890  Threads: 2  Questions: 590871  Slow queries: 10  Opens: 2292  Flush tables: 1  Open tables: 5  Queries per second avg: 5.328"

## first just tack on the date label
txt <- gsub('^', 'Date: ', readLines(textConnection(txt)))

Опция 1

sp <- strsplit(txt, '\\s{2,}')
out <- lapply(sp, function(x) gsub('([\\w ]+:)\\s+(.*)$', '\\2', x, perl = TRUE))
dd <- setNames(do.call('rbind.data.frame', out),
               gsub('([\\w ]+):\\s+(.*)$', '\\1', sp[[1]], perl = TRUE))
dd[, -1] <- lapply(dd[, -1], function(x) as.numeric(as.character(x)))
dd

вариант 2: этот использует пакет yaml, но гораздо более прямолинеен и выполняет преобразование типов за вас

yml <- gsub('\\s{2,}', '\n', txt)
do.call('rbind.data.frame', lapply(yml, yaml::yaml.load))

#                    Date Uptime Threads Questions Slow queries Opens Flush tables
# 1 Fri Dec 11 12:40:01 CET 2015 108491       2    576603           10  2238            1
# 2 Fri Dec 11 12:50:01 CET 2015 109090       2    580407           10  2253            1
# 3 Fri Dec 11 13:00:01 CET 2015 109690       2    583895           10  2268            1
# 4 Fri Dec 11 13:10:01 CET 2015 110290       1    586891           10  2279            1
# 5 Fri Dec 11 13:20:01 CET 2015 110890       2    590871           10  2292            1
#   Open tables Queries per second avg
# 1           7                  5.314
# 2           6                  5.320
# 3           8                  5.323
# 4           6                  5.321
# 5           5                  5.328
person rawr    schedule 11.12.2015