2017-01-17 2 views
0

У меня есть файлы matlab с целым числом в каждом имени моих переменных внутри (кроме первого). Я хочу, чтобы цикл совпадал с именем целых чисел. Существует мой код:Объединение строковых имен переменных matlabfile в R

library('R.matlab') 
mat <- readMat('SeriesContPJM.mat') 
#str(mat) 
#typeof(mat) 
             #mat[[1]] 
write.csv(mat$vol.PJM$data[[4]][[1]], "PJM.csv") 
i = 2 
while (i < 7) 
{ 
    write.csv(get(paste("mat$vol.PJM", as.character(i), "$data[[4]][[1]]", sep = "")), paste(paste("PJM", as.character(i), sep="_"), "csv", sep =".")) 
    i = i + 1 
} 

У меня есть write.csv(mat$vol.PJM$data[[4]][[1]], "PJM.csv"), который дает мне хороший вывод. Я хотел бы то же самое для других имен переменных в цикле, но я получаю следующее: вывод

+ Error in get(paste("mat$vol.PJM", as.character(i), "$data[[4]][[1]]", (from importpjm.R#10) : 
    objet 'mat$vol.PJM2$data[[4]][[1]]' introuvable 

«introuvable» означает «не найдено» на французском языке.

ответ

2

Здесь вы смешиваете, где вам нужно использовать get и где вам нужно использовать eval(parse()).

Вы можете использовать get со строковой переменной игрой, например get("mtcars"), но [ - это функция, которую необходимо оценить.

  • get("mtcars[2, 2]") не будет работать, потому что вы не имеете переменную с именем "mtcars[2, 2]", у вас есть переменная с именем "mtcars" и функцию с именем "[", который может принимать аргументы 2, 2.

  • eval(parse(text = "mtcars[2, 2]")) будет работать, потому что он не просто ищет переменную, он фактически оценивает текстовую строку, как если бы вы ввели ее в командной строке.

Таким образом, вы можете переписать цикл, заменив get(...) с eval(parse(text = ...)) и это, вероятно, работать, если строки вы paste d вместе имеют правильный синтаксис. Но это может быть трудно читать и отлаживать. Через 6 месяцев, если вы оглянетесь на этот код и вам нужно его понять или изменить, это будет путать.

Другой способ сделать это - использовать [[ со строками для извлечения подсписок. Вместо того, чтобы возиться с eval(parse()) Я хотел бы сделать это:

vols = paste0("vol.PJM", 2:7) 
for (vol in vols) { 
    write.csv(mat[[vol]][["data"]][[4]][[1]], 
       paste0(vol, ".csv")) 
} 

Я думаю, что это более удобным для чтения, и это легко отлаживать vols вектор заранее, чтобы убедиться, что все имена являются правильными. Аналогичным образом, если вы хотите перебрать все элементы, вы можете инициализировать vols как-то вроде names(mat) или использовать какие-то критерии регулярного выражения для извлечения соответствующих подписок с names(mat).

+0

Большое спасибо за этот очень подробный ответ. Ваше окончательное решение очень элегантно. Просто вопрос: что [['изменяется по сравнению с' $ '? –

+0

'[[' может использоваться со строками (и, следовательно, с именами, хранящимися как строки в переменных), тогда как '$' является «магическим ярлыком», который не работает со строками. Поскольку 'vol' - это строка,' mat [[vol]] 'работает, тогда как' mat $ vol' не будет работать. [См. Этот вопрос для получения дополнительной информации] (http://stackoverflow.com/q/18222286/903061). Для бит '[[" data "]]' это не имеет большого значения, но поскольку все остальное использует '[[' казалось, было приятно сохранить его согласованным. – Gregor

Смежные вопросы