Я публикую здесь мою проблему после того, как заметил, что это подход, рекомендованный автором Knitr для получить больше помощи.
Я немного озадачен файлом .Rmd, который я могу выполнять построчно в интерактивном сеансе R, а также с R CMD BATCH
, но это не удается при использовании knit("test.Rmd")
. Я не уверен, в чем проблема, и я попытался сузить проблему настолько, насколько мог. Вот пример (в test.Rmd
):
```{r Rinit, include = FALSE, cache = FALSE}
opts_knit$set(stop_on_error = 2L)
library(adehabitatLT)
```
The functions to be used later:
```{r functions}
ld <- function(ltraj) {
if (!inherits(ltraj, "ltraj"))
stop("ltraj should be of class ltraj")
inf <- infolocs(ltraj)
df <- data.frame(
x = unlist(lapply(ltraj, function(x) x$x)),
y = unlist(lapply(ltraj, function(x) x$y)),
date = unlist(lapply(ltraj, function(x) x$date)),
dx = unlist(lapply(ltraj, function(x) x$dx)),
dy = unlist(lapply(ltraj, function(x) x$dy)),
dist = unlist(lapply(ltraj, function(x) x$dist)),
dt = unlist(lapply(ltraj, function(x) x$dt)),
R2n = unlist(lapply(ltraj, function(x) x$R2n)),
abs.angle = unlist(lapply(ltraj, function(x) x$abs.angle)),
rel.angle = unlist(lapply(ltraj, function(x) x$rel.angle)),
id = rep(id(ltraj), sapply(ltraj, nrow)),
burst = rep(burst(ltraj), sapply(ltraj, nrow)))
class(df$date) <- c("POSIXct", "POSIXt")
attr(df$date, "tzone") <- attr(ltraj[[1]]$date, "tzone")
if (!is.null(inf)) {
nc <- ncol(inf[[1]])
infdf <- as.data.frame(matrix(nrow = nrow(df), ncol = nc))
names(infdf) <- names(inf[[1]])
for (i in 1:nc) infdf[[i]] <- unlist(lapply(inf, function(x) x[[i]]))
df <- cbind(df, infdf)
}
return(df)
}
ltraj2sldf <- function(ltr, proj4string = CRS(as.character(NA))) {
if (!inherits(ltr, "ltraj"))
stop("ltr should be of class ltraj")
df <- ld(ltr)
df <- subset(df, !is.na(dist))
coords <- data.frame(df[, c("x", "y", "dx", "dy")], id = as.numeric(row.names(df)))
res <- apply(coords, 1, function(dfi) Lines(Line(matrix(c(dfi["x"],
dfi["y"], dfi["x"] + dfi["dx"], dfi["y"] + dfi["dy"]),
ncol = 2, byrow = TRUE)), ID = format(dfi["id"], scientific = FALSE)))
res <- SpatialLinesDataFrame(SpatialLines(res, proj4string = proj4string),
data = df)
return(res)
}
```
I load the object and apply the `ltraj2sldf` function:
```{r fail}
load("tr.RData")
juvStp <- ltraj2sldf(trajjuv, proj4string = CRS("+init=epsg:32617"))
dim(juvStp)
```
Использование knitr("test.Rmd")
завершается ошибкой:
label: fail
Quitting from lines 66-75 (test.Rmd)
Error in SpatialLinesDataFrame(SpatialLines(res, proj4string =
proj4string), (from <text>#32) :
row.names of data and Lines IDs do not match
Использование вызова непосредственно в консоли R после возникновения ошибки работает, как и ожидалось...
Проблема связана с тем, как format
создает идентификатор (в вызове apply
ltraj2sldf
) непосредственно перед идентификатором 100 000: используя интерактивный вызов, R дает «99994», «99995», «99996», «99997», «99998». ", "99999", "100000"; использование вязальщика R дает «99994», «99995», «99996», «99997», «99998», «99999», «100000» с дополнительными пробелами в начале.
Есть ли причина такого поведения? Почему knitr
должен вести себя иначе, чем прямой вызов в R? Я должен признать, что у меня с этим проблемы, так как я не могу его отладить (он работает в интерактивном сеансе)!
Любая подсказка будет высоко оценена. Я могу предоставить .RData, если это поможет (файл 4,5 мес), но меня больше всего интересует, почему происходит такая разница. Я безуспешно пытался придумать самовоспроизводимый пример, извините за это. Заранее спасибо за любой вклад!
После комментария baptiste, вот еще несколько подробностей о генерации идентификаторов. По сути, идентификатор генерируется в каждой строке фрейма данных с помощью вызова apply
, который, в свою очередь, использует format
следующим образом: format(dfi["id"], scientific = FALSE)
. Здесь столбец id
— это просто ряд от 1 до количества строк (1:nrow(df)
). scientific = FALSE
просто для того, чтобы у меня не было таких результатов, как 1e+05 для 100000.
Основываясь на исследовании создания идентификаторов, проблема возникла только для тех, которые представлены в первом сообщении, то есть от 99995 до 99999, для которых добавлен начальный пробел. Этого не должно происходить с этим вызовом format
, так как я не запрашивал конкретное количество цифр в выводе. Например:
> format(99994:99999, scientific = FALSE)
[1] "99994" "99995" "99996" "99997" "99998" "99999"
Однако, если идентификаторы генерируются фрагментами, может произойти следующее:
> format(99994:100000, scientific = FALSE)
[1] " 99994" " 99995" " 99996" " 99997" " 99998" " 99999" "100000"
Обратите внимание, что одно и то же обработанное по одному дает ожидаемый результат:
> for (i in 99994:100000) print(format(i, scientific = FALSE))
[1] "99994"
[1] "99995"
[1] "99996"
[1] "99997"
[1] "99998"
[1] "99999"
[1] "100000"
В конце концов, это точно так же, как если бы идентификаторы готовились не по одному (как я ожидал бы от apply
вызова по строке), а в этом случае 6 за раз, и только когда близко к 1e+05.. , И, конечно, только при использовании Knitr, а не интерактивного или пакетного R.
Вот моя информация о сеансе:
> sessionInfo()
R version 3.0.1 (2013-05-16)
Platform: x86_64-pc-linux-gnu (64-bit)
locale:
[1] LC_CTYPE=fr_FR.UTF-8 LC_NUMERIC=C
[3] LC_TIME=fr_FR.UTF-8 LC_COLLATE=fr_FR.UTF-8
[5] LC_MONETARY=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8
[7] LC_PAPER=C LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] knitr_1.2 adehabitatLT_0.3.12 CircStats_0.2-4
[4] boot_1.3-9 MASS_7.3-27 adehabitatMA_0.3.6
[7] ade4_1.5-2 sp_1.0-11 basr_0.5.3
loaded via a namespace (and not attached):
[1] digest_0.6.3 evaluate_0.4.4 formatR_0.8 fortunes_1.5-0
[5] grid_3.0.1 lattice_0.20-15 stringr_0.6.2 tools_3.0.1
knitr
может изменить некоторые параметры форматирования (например, количество значащих цифр), каким-то образом влияя на то, как генерируются идентификаторы. - person baptiste   schedule 25.07.2013format()
не является хорошим выбором, так как на результаты может повлиять ряд глобальных параметров; чтобы точно получить символьное представление ваших чисел, я бы рекомендовал вам просто использоватьas.character()
, тогда ничего необычного не произойдет. Кстати, я рад, что вы последовали моему предложению прийти в SO. Как вы видели, один-единственный автор (то есть я) гораздо менее полезен и отзывчив, чем тысячи экспертов здесь :) - person Yihui Xie   schedule 27.07.2013as.character
вместоformat
решает проблему. Странно то, что я помню, как начал сas.character
, а потом переключился наformat
по какой-то причине. Эта причина, которую я не помню, вероятно, уже недействительна, так как функция теперь работает так, как я хочу. Спасибо за ваш комментарий! - person Mathieu Basille   schedule 29.07.2013format
, а неas.character
(и я действительно упомянул об этом в своем первом посте): это просто для того, чтобы избежать научного форматирования, такого как"1e+05"
, которое является результатомas.character(100000)
(и выдает мне ошибку, если это происходит в названиях строк). Таким образом, я буду придерживатьсяformat(..., scientific = FALSE, trim = TRUE)
. R работает таинственным образом... - person Mathieu Basille   schedule 30.07.2013as.character()
; спасибо за вашу поправку! - person Yihui Xie   schedule 30.07.2013