2017-01-18 4 views
0

У меня есть файлы, которые автоматически генерируются, и я не могу изменить формат. Я хотел бы иметь возможность хранить данные в соответствующем формате R. Они идут так:R хранить несколько векторов из неотформатированных текстовых файлов

File: /path/to/file 


Start Date: 07/05/16 
Subject: 0 
Start Time: 10:01:09 
Name: FooBar 
K:  0.000 
O:  0.000 
A: 
    0:  91.600  65.000  238.000  31.000  24.000 
    5:  7.000 22162.000  78.000  10.000 20000.000 
    10:  55.000  0.000  2.000  6.000  53.000 
B: 
    0:  0.000  2.000  1.000  1.000  1.000 
    5:  1.000  1.000  1.000  1.000  1.000 

[...] # Goes all the way to Z 
Start Date: 07/05/16 
Subject: 8 
Start Time: 10:11:09 
Name: JohnDoe 
K:  0.000 
O:  0.000 
A: 
    0:  91.600  65.000  238.000  31.000  24.000 
[...] # Goes all the way to Z 

Я открыл файл, используя readLines, поэтому линия каждый длинный характер. Каждый файл содержит несколько сеансов, которые идентифицируются по дате, имени, теме и времени. Каждый сеанс содержит несколько числовых переменных, которые представляют алфавит (LETTERS). Например, в первой сессии (FooBar), K может быть представлена ​​в виде c(0.000) и B, как

c(0.000,2.000,1.000,1.000,1.000,1.000,1.000,1.000,1.000,1.000) 

Первые строки (Файл, дата начала, время начала, название) являются информацией о сессиях, которые я был в состоянии сохранить в этом dataframe:

#Sessions data.frame 
structure(list(`Start Date` = c("07/05/16", "07/05/16"), Subject = c("0", "8"), `Start Time` = c("10:01:09", 
"10:11:09"), Name = c("FooBar", 
"JohnDoe" 
)), .Names = c("Start Date", "Subject", "Start Time", "name"), row.names = 1:2, class = "data.frame") 

это две вещи, которые я борюсь с

  1. Как сохранить переменные (AZ) в качестве числовых векторов?
  2. Как я могу структурировать эти числовые векторы, чтобы их было легко получить для каждой сессии?

я имел в виду сочетание apply, startsWith и scan, но я не могу понять, что лучший способ структурировать мои данные.

+0

вы были бы открыты для решения не с помощью R? Я думаю, awk может неплохо обработать файл и вывести что-то более пригодное для R. – Tensibai

+0

@ Tensibai К сожалению, мы можем использовать только R-решение в нашей среде. Тем не менее, я могу работать с любым пакетом R, если это необходимо. – Wistar

+0

Тогда удачи, было бы довольно легко превратить это в csv с awk, не так просто в R. (Мне было бы любопытно, почему awk не может быть использован, который сказал, даже назвав его из R 'system2' в худшем случае) – Tensibai

ответ

0

Возможно, не совсем то, что вам нужно, но это лучшее, что я могу придумать с недостатком, в цикле есть вектор, увеличивающий вектор, потому что мы не можем догадываться, как долго вектор будет заблаговременно.
Мы не можем создать data.frame, потому что A, B и т.д. векторы не из тех же длин (это нужно будет раздуть их с НС, но это звучит не интересно вообще)

sessions <- list() 
sd <- subject <- st <- sname <- cvec <- "" 
lines = readLines("c:/tmp/test.txt") 
cases <- c("Start Date:", "Subject:", "Start Time:", "Name:", LETTERS, " ") 
lnames <- c("SDate", "Subject", "STime", "Name", LETTERS) 
for (l in lines) { # loop on line 
    if (nchar(l) < 2) # skip lines with less than 1 char (A:) 
    next 
    v <- lnames[min(which(startsWith(l, cases)))] # Get the "field" name 
    fields <- strsplit(l, " ")[[1]] 
    # Here comes the fun, for each case store the value or update a vector 
    if (is.na(v)) { # No field, it's a line of the form "spaces digit: space separated values" 
    vals <- fields[nchar(fields) > 1] 
    sessions[[sname]][[cvec]] <- 
     c(sessions[[sname]][[cvec]], as.integer(vals[-1])) # We just concatenate with previous value for this letter 
    } 
    else if (v == "SDate") 
    sd <- fields[3] 
    else if (v == "Subject") 
    subject = fields[2] 
    else if (v == "STime") 
    st <- fields[3] 
    else if (v == "Name") { 
    sname <- fields[2] 
    # Create a new session list entry 
    sessions[[sname]] = list(
     "SDate" = sd, 
     "STime" = st, 
     "Subject" = as.numeric(subject) 
    ) 
    } 
    else if (any(v %in% LETTERS)) { # Swich letter vector, use on line value if there's some 
    cvec <- v 
    sessions[[sname]][[cvec]] <- vector("numeric") 
    if (length(fields) > 1) { 
     vals <- fields[-1] 
     sessions[[sname]][[cvec]] <- as.numeric(vals[nchar(vals) > 1]) 
    } 
    } 
} 

Это создание списка списка:

> str(sessions) 
List of 2 
$ FooBar :List of 7 
    ..$ SDate : chr "07/05/16" 
    ..$ STime : chr "10:01:09" 
    ..$ Subject: num 0 
    ..$ K  : num 0 
    ..$ O  : num 0 
    ..$ A  : num [1:15] 91 65 238 31 24 ... 
    ..$ B  : num [1:10] 0 2 1 1 1 1 1 1 1 1 
$ JohnDoe:List of 7 
    ..$ SDate : chr "07/05/16" 
    ..$ STime : chr "10:11:09" 
    ..$ Subject: num 8 
    ..$ K  : num 0 
    ..$ O  : num 0 
    ..$ A  : num [1:15] 91 65 238 31 24 ... 
    ..$ B  : num [1:10] 0 2 1 1 1 1 1 1 1 1 

Это дает для сеанса «FooBar»:

sessions$FooBar 
$SDate 
[1] "07/05/16" 

$STime 
[1] "10:01:09" 

$Subject 
[1] 0 

$K 
[1] 0 

$O 
[1] 0 

$A 
[1] 91 65 238 31 24  7 22162 78 10 20000 55  0  2  6 53 

$B 
[1] 0 2 1 1 1 1 1 1 1 1 
Смежные вопросы