Closed vlsi closed 10 years ago
Cool, thanks, I'll add this feature for R5 in the next few days as well. Until then, you can use the brew
version with <%= ... %>
type of chunks, which shows error messages. E.g.:
> Pandoc.brew(text = '
+ <%=
+ d <- data.table(x=2,y=3)
+ ggplot(d, aes(x,z))+geom_point()
+ %>')
**ERROR**^[could not find function "data.table"] **ERROR**^[could not find function "ggplot"]
Until then, you can use the brew version with <%= ... %> type of chunks
The thing is I have loops in my report: "for given scenario, list details on the performance of steps of that scenario".
There is no <%loop.over.xyz
kind of tag, thus I have to resort to <% .. %>
.
<%..%>
is not very error-friendly, thus I switch to R5.
I will definitely survive a few days or weeks with the current state of affairs. At least R5 + approach of "always use just $add.paragraph
" seems to show error messages at the cost of more verbose report code (e.g. explicit pandoc.image.return
)
What about this example:
> Pandoc.brew(text = '
+ <% for (i in 1:3) { %>
+
+ <%=
+ ggplot(d, aes(x,z))+geom_point()
+ %>
+
+ <% } %>')
**ERROR**^[could not find function "ggplot"]
**ERROR**^[could not find function "ggplot"]
**ERROR**^[could not find function "ggplot"]
You can include <%= ... %>
chunks between <% ... %>
loops.
That is what I do.
However <% ... %>
still includes some code (e.g. loops, code to slice and dice data for a given loop iteration) and this code fails from time to time.
Why don't you move everything out of <% ... %>
into a separate <%= ... %>
chunk? The <% ... %>
should not really contain anything beside for
or if
statements, and all operations should rather be done in a previous <%= ... %>
chunk.
Example: 1) Prepare data for a particular step (filter raw data from the overall raw set of measurements) 2) Render top 5 samples from the prepared set 3) Render top 5 samples from the prepared set 4) Plot samples as a chart
I feel I like to prepare the data just once and render it multiple times.
Here's the sample:
<%
setkey(src$ui, "step")
cases <- src$summary[category=="UI" & scenario=="Overall" & !is.na(duration)][order(-stddev), ]
if (nrow(cases) > 0) {
apply(cases, 1, function(it) {
%>
## <%= it[["step"]] %>
Category: <%= it[["category"]] %>
<%
.e <- environment()
d <- src$ui[step==it[["step"]]]
d <- d[order(-duration), ]
nfrlines <- data.table(
time=src$overview$start.time,
duration=as.numeric(c(it[["required.time90"]], it[["duration90"]])),
label=c(paste0("Response time NFR (", it[["required.time90"]], "s)"), paste0("90% line (", it[["duration90"]], "s)"))
)
%>
<%=
ggplot(d, aes(x=time, y=duration, color=scenario))+geom_hline(data=nfrlines, aes(yintercept=duration)) + geom_text(data=nfrlines,aes(time, duration, label=label), color="#000000", vjust=-0.2, hjust=0) + geom_point()+ggtitle(paste0(it[["step"]], "\n", "response time over time")) + scale_color_discrete(name="Scenario") + scale_y_continuous("Response time, seconds", limits=lims)+scale_x_continuous(paste0("Time in ", reportTZ, " time zone"), trans=time_trans(tz=reportTZ), limits=c(src$overview$start.time, src$overview$stop.time))+facet_grid(success~., labeller=function(var, x) ifelse(x, "Success", "Failure")) + twoCol %>
### Top 5 slowest entries {.exclude_from_toc}
<%=
pandoc.table.return(
head(d[, list("Timestamp"=time, "Time since start"=time-src$overview$start.time, "Scenario"=scenario, "Customer ID"=customer.id, "ICOMS site"=site.id, "Duration, sec"=duration, "Result"=ifelse(success, "Success", "Failure"))], 5)
, justify=c("left", "left", "left", "left", "center", "right", "left"))
%>
### Top 5 entries approaching 95% line {.exclude_from_toc}
<%=
pandoc.table.return(
head(d[floor(nrow(d)*0.05):floor(nrow(d)*0.05+4), list("Timestamp"=time, "Time since start"=time-src$overview$start.time, "Scenario"=scenario, "Customer ID"=customer.id, "ICOMS site"=site.id, "Duration, sec"=duration, "Result"=ifelse(success, "Success", "Failure"))], 5)
, justify=c("left", "left", "left", "left", "center", "right", "left"))
%>
### Top 5 entries approaching 90% line {.exclude_from_toc}
<%=
pandoc.table.return(
head(d[floor(nrow(d)*0.1):floor(nrow(d)*0.1+4), list("Timestamp"=time, "Time since start"=time-src$overview$start.time, "Scenario"=scenario, "Customer ID"=customer.id, "ICOMS site"=site.id, "Duration, sec"=duration, "Result"=ifelse(success, "Success", "Failure"))], 5)
, justify=c("left", "left", "left", "left", "center", "right", "left"))
%>
### Top 5 fastest entries {.exclude_from_toc}
<%=
pandoc.table.return(
tail(d[, list("Timestamp"=time, "Time since start"=time-src$overview$start.time, "Scenario"=scenario, "Customer ID"=customer.id, "ICOMS site"=site.id, "Duration, sec"=duration, "Result"=ifelse(success, "Success", "Failure"))], 5)
, justify=c("left", "left", "left", "left", "center", "right", "left"))
%>
<% })} %>
Ah, okay, I get what you mean. I'd not call apply
with an anonymous function here, there's a lot easier design without the need to call pandoc.table.return
etc. Probably I miss something obvious, but what about simply looping through nrow(cases)
? So instead:
<%
setkey(src$ui, "step")
cases <- src$summary[category=="UI" & scenario=="Overall" & !is.na(duration)][order(-stddev), ]
if (nrow(cases) > 0) {
apply(cases, 1, function(it) {
%>
Something like:
<%=
setkey(src$ui, "step")
cases <- src$summary[category=="UI" & scenario=="Overall" & !is.na(duration)][order(-stddev), ]
%>
<%
if (nrow(cases) > 0) {
for (it in 1:nrows(cases)) {
%>
If you could post a minimal reproducible example with some minimal dataset, I'd be happy to come up with a working demo.
Probably I miss something obvious, but what about simply looping through nrow(cases)?
Initially I thought apply
was somehow idiomatic-r.
After some experiments I figured out that apply
fails dismally in case of empty input list, thus I just fixed that with if (nrow()>0
. Now I am just lazy to rewrite it since it works and it is not extra verbose.
Note that I can fetch data from iterator as it["required.time90"]
, while in for(it in 1:nrows(...))
style loop you'll have just the index. That's not a big deal, but in general the absence of "row-by-row iterator" was unexpected for me.
If you could post a minimal reproducible example with some minimal dataset, I'd be happy to come up with a working demo.
Will see if I can put it together.
design without the need to call pandoc.table.return etc
I use explicit pandoc.table.return
for two main reasons:
1) Column alignment. It is not just "numerics right aligned", but sometimes I want text columns right aligned or centered.
2) Transposed tables like the following (as far as I can remember I have to specify style="rmarkdown"
otherwise it looks bad):
pandoc.table.return(t(data.table(
"Date" = "26/07/2013"
, "Project" = "Acme load test"
, "Test type" = "Scalability"
, "Version test" = "acme_build_2.zip"
, "Hardware layout" = "1 app server + 1 database, SW loadbalancer at app machine"
)), style="rmarkdown", justify=c("left"))
Will see if I can put it together.
That would be very useful, thank you!
1) Column alignment. It is not just "numerics right aligned", but sometimes I want text columns right aligned or centered.
What about panderOptions('table.alignment.default')
?
2) Transposed tables like the following (as far as I can remember I have to specify style="rmarkdown" otherwise it looks bad):
What about panderOptions('table.style')
?
E.g.:
> library(data.table)
data.table 1.9.2 For help type: help("data.table")
> panderOptions('table.alignment.default', 'left')
> panderOptions('table.style', 'rmarkdown')
> Pandoc.brew(text = '<%=
+ t(data.table(
+ "Date" = "26/07/2013"
+ , "Project" = "Acme load test"
+ , "Test type" = "Scalability"
+ , "Version test" = "acme_build_2.zip"
+ , "Hardware layout" = "1 app server + 1 database, SW loadbalancer at app machine"
+ ))
+ %>')
| | |
|:---------------------:|:----------------------------------------------------------|
| **Date** | 26/07/2013 |
| **Project** | Acme load test |
| **Test type** | Scalability |
| **Version test** | acme_build_2.zip |
| **Hardware layout** | 1 app server + 1 database, SW loadbalancer at app machine |
To also set the default alignment for the row.names
, see table.alignment.rownames
in the options.
Quick demo:
> r <- Pandoc$new()
> r$add(ggplot2::ggplot(foobar))
> r$add(warning('foobar'))
> r$add(thereIsNoSuchFunctoin())
> r
Anonymous's report
==================
written by *Anonymous* at *Tue Sep 16 01:30:07 2014*
This report holds 3 block(s).
---
**ERROR:** object 'foobar' not found
**WARNING:** foobar
**ERROR:** could not find function "thereIsNoSuchFunctoin"
---
Proc. time: 0.038 seconds.
Here's testcase: the chart is using
z
column that is intentional soggplot
will fail when trying to render the chart.Note that
report.md
includes no signs of the error.The same applies for
Pandoc.brew
: it does not provide backtrace and it just tells you "there is an error in BRCODES"