I've been trying to create a table with a header that contains a like break. I am not too ambitious here and do not really care whether I just break extremely long strings or just have a two-line header in general.
dat <- matrix(round(rnorm(9, 20, 10)), 3, 3)
colnames(dat) <- c("some very long colname","short","another toooooooolong colname")
require(xtable)
m <- xtable(dat)
print(m,
floating=FALSE,
hline.after=NULL,
size="\\footnotesize",
tabular.environment="tabular",
add.to.row=list(pos=list(-1,0,nrow(m),0
),
command=c('\\toprule ',
'\\midrule ',
'\\bottomrule',
'\\\\ \\rowcolor[gray]{.9}'
)
)
)
Is there a way to line break the header, because my table is not fitting on the page anymore, though I use landscape already. Some sanitize.rownames based trick? Fiddled around with \shortstack but could not get it to go...
(Writing my comment up into a proper answer)
In the call to xtable, you can specify various alignment arguments, one of which is a parbox of a fixed width in which text will be wrapped. That is specified with p{1in} where the value specified within the braces is how wide the box (column) will be. You have to manually specify this (rather than have it adapt to the available space), but it does give you one option for wrapping text.
Related
This is the command I'm using :
dallData <- fread("data.csv", showProgress = TRUE, colClasses = c(rep("NULL", 2), "character", rep("NULL", 37)))
but I get this error when trying to load it: R character strings are limited to 2^31-1 bytes|
Anyway to skip those values ?
Here's a strategy that may work or at least narrow down the possible sources of error. It assumes you have enough working memory to hold the data and that your separators are really commas. If you actually have tabs as separators then you will need to modify accordingly. The plan is to read using readLines which will basically ignore the quotes that are probably mismatched. Then figure out which line or lines are at fault using count.fields, table, and which.
input <- readLines("data.csv") # ignores quotes
counts.def <- count.fields(textConnection(input),
sep=",") # defaults quotes are both ' and "
table(counts.def) # might show a variety of line counts.
# Second try with just double-quotes
counts.dbl <- count.fields(textConnection(input),
sep=",", quote="\"") # just dbl-quotes
table(counts.dbl) # if all the same, then all you do is change the quotes argument
Depending on the results you may need to edit cerain lines which can be identified using which(counts.def < 40) assuming most of them are 40 as your input efforts suggest is the expected number of fields per line.
(If the tag for [ram] means you are limited and getting warnings or using virtual memory which slows things down horribly, then you should restart your OS, and only load R before trying again. R needs contiguous block of memory and Windoze isn't very good at memory management.)
Here's a small test case to work with:
input <- readLines(textConnection(
"v1,v2,v3,v4,v5,v6
text, text, text, text, text, text
text, text, O'Malley, text,text,text
junk,junk, more junk, \"text\", tex\"t, nothing
3,4,5,6,7,8")
is it possible to indent output in R?
e.g.
cat("text1\n")
indent.switch(indent=4)
cat("random text\n")
print("another random text")
indent.switch(indent=0)
cat("text2\n")
resulting in
text1
random text
another random text
text2
I searched for this a few months ago, found nothing and am now searching again.
My current idea is to "overwrite" (I forgot the special term) the functions cat and/or print with an additional argument like:
cat("random text", indent=4)
Only I'm stuck with this and I dont like this procedure very much.
Any ideas?
Edit:
I should be more particular, nevertheless thank you for the \t (omg, i totally forgot this -.-) and that I can format it inside cat.
The given solutions work, but only solve my second-choice-path.
A switch as shown in my first codeexample does not exist I suppose?
My problem is that I have parts of a bigger program which have multiple subscripts, and the output of each subscript should be indented. This is absolutely possible with the "\t" or just blanks inside cat() but has to be done in every command, which I dont like very much.
Solution
I used Chris C's code and extended it in a very easy way. (Thank you very much Chris!)
define.catt <- function(ntab = NULL, nspace=NULL){
catt <- function(input = NULL){
if(!is.null(ntab)) cat(paste0(paste(rep("\t", ntab), collapse = ""), input))
if(!is.null(nspace)) cat(paste0(paste(rep(" ", nspace), collapse = ""), input))
if(is.null(ntab) && is.null(nspace)) cat(input)
}
return(catt)
}
The same way you used \n to print a newline, you can use \t to print a tab.
E.g.
cat("Parent level \n \t Child level \n \t \t Double Child \n \t Child \n Parent level")
Evaluates to
Parent level
Child level
Double Child
Child
Parent level
As an alternative, you can create a derivative of cat called catt and alter options depending on the script. For example.
define.catt <- function(ntab = NULL){
catt <- function(input = NULL){
cat(paste0(paste(rep("\t", ntab), collapse = ""), input))
}
return(catt)
}
You would then set catt with however many tabs you wanted by
catt <- define.catt(ntab = 1)
catt("hi")
hi
catt <- define.catt(ntab = 2)
catt("hi")
hi
And just use catt() instead of cat().
You may consider the very versatile function capture.output(...), which evaluates the '...' list of expressions provided as main input arguments, and stores the text output (as if it would be displayed in the console) into a character vector instead. Then, you simply have to modify the strings as desired: here you want to add some leading spaces to each string. Finally, you write the strings to the console.
These can be done all in one line of nested calls. For example:
writeLines(paste(" ", capture.output(print(head(iris))), sep=""))
I therefore recommend you all to read the help of the capture.output function, and then try to use it for various purposes. Indeed, since the main input has the usual flexibility of the '...' list-like structure, you are free to include, for instance, a call to one home-made function, and thus do almost anything. As for indentation, that is simply done with paste function, once the former has done its magic.
I tend to use a lot of line breaks in my code like the following:
# Data =========================================================================
Where the entire comment is always 80 characters long (including the hashtag). What I would like to do is write a code snippet for Rstudio that will insert the hashtag, then a space, then allow the user to type out a series of words, then insert another space, and finally fill in a bunch of "=" until the 80 character limit is reached.
I'm not familiar with how snippets work at all so I'm not sure how difficult this is.
I have this much:
snippet lb
# ${1:name}
but I have no idea how to add a dynamic number of "=" signs. Also, lb = linebreak.
You can't do this with snippets, unfortunately; a snippet is a text template that contains fixed text with slots for user-inserted text.
There is a command built into RStudio to do something very similar, however; from the Code menu, choose Insert Section (or Ctrl+Shift+R). This will do exactly what you're describing, with two small differences:
The line will extend to 5 characters before the print margin (you can adjust the print margin in Tools -> Global Options -> Code.
The line is composed of - rather than = characters.
One advantage to sections marked in this way is that you can use them to fold and navigate inside the file (look at the editor status bar after adding one).
You can use the rstudioapi (which can return column position) inside the snippet to get something like what you want.
Below is a snippet I use called endhead. I use it by commenting my header title and then applying the snippet, eg:
# Section name endhead
which results in:
# Section name -----------------------------------------------------------------
snippet endhead
`r paste0(rep.int("-", 88 - rstudioapi::primary_selection(rstudioapi::getActiveDocumentContext())$range$start[2]), collapse = "")`
You can write a snippet to manipulate text (somewhat). I wrote the snippet below to do something similar to what you want to do. I'm still ironing out the issues (just asked this question).
snippet comm
`r paste0(
"#######################################><###################\n## ",
date(),
" -------------------------------\n## ",
eval(
paste0(
gsub(
".{1,51}\\s?\\K\\b",
"\n## ",
gsub("\\.", " ", paste0(text)),
perl = T
)
)
),
"###################################><###################\n"
)`
I think if you write an R code snippet using an anonymous function that accepts text input via $$, counts the nchar in the text, calculates the number of -'s needed at the end, and then uses eval(paste0()) to insert the comment you should be able to make it work. I'll post a comment or answer here if I figure it out. Please do the same on my question if you get it to work. Thanks. (P.S. Go Badgers!)
Inspired by nick's answer above I designed two snippets that allow the user to choose what level section to insert.
The first will fill-in the rest of the line with #, =, or -.
snippet end
`r strrep(ifelse(substr("$$", 1, 1) %in% c("-", "="), substr("$$", 1, 1), "#"), 84 - rstudioapi::primary_selection(rstudioapi::getActiveDocumentContext())$range$start[2])`
Just specify the character you want to use after end (will default to # if nothing or any other character is given). For example:
## Level 1 Header end<shift+tab>
## Level 2 Header end=<shift+tab>
## Level 3 Header end-<shift+tab>
end<shift+tab>
end=<shift+tab>
end-<shift+tab>
Produces the following lines:
## Level 1 Header ##############################################################
## Level 2 Header =============================================================
## Level 3 Header -------------------------------------------------------------
################################################################################
===============================================================================
-------------------------------------------------------------------------------
Similarly to what Josh was suggesting, the following snippet uses th $$ notation to pass the text following the snippet as described here.
snippet !
`r paste("##", substr("$$", 4, nchar("$$")), strrep(substr("$$", 2, 2), 79-nchar("$$")))`
Again this allows user to select the section level (#, =, or -). The first character after !# should be the header level character you want followed by a space and the header text. For example:
!## Level 1 Header<shift+tab>
!#= Level 2 Header<shift+tab>
!#- Level 3 Header<shift+tab>
Produces the following lines:
## Level 1 Header ##############################################################
## Level 2 Header ==============================================================
## Level 3 Header --------------------------------------------------------------
I prefer the end snippet above because it is more robust and only allows the characters #, =, or - to be inserted where as ! will allow anything, but it is shorter and, I think, easier to understand than calls to the rstudioapi.
!loon<shift+tab>
## n ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
when displaying a number with inline-code with more than four digits like
`r 21645`
the result in a knitted html-file is this: 2.164510^{4} (in reality inside the inline-hook there is a calculation going on which results in 21645). Even though I just want it to print the number, like so: 21645. I can easily fix this for one instance wrapping it inside as.integer or format or print, but how do I set an option for the whole knitr-document so that it prints whole integers as such (all I need is to print 5 digits)? Doing this by hand gets very annoying. Setting options(digits = 7) doesnt help. I am guessing I would have to set some chunk-optionor define a hook, but I have no idea how
I already solved it, just including the following line of code inside the setoptions-chunk in the beginning of a knitr document:
options(scipen=999)
resolves the issue, like one can read inside this answer from #Paul Hiemstra:
https://stackoverflow.com/a/25947542/4061993
from the documentation of ?options:
scipen: integer. A penalty to be applied when deciding to print
numeric values in fixed or exponential notation. Positive values bias
towards fixed and negative towards scientific notation: fixed notation
will be preferred unless it is more than scipen digits wider.
If you don't want to display scientific notation in this instance, but also don't want to disable it completely for your knitr report, you can use format() and set scientific=FALSE:
`r format(21645, scientific=FALSE)`
Note that if you type your numeric as integer it will be well formatted:
`r 21645L`
Of course you can always set an inline hook for more flexibility( even it is better to set globally options as in your answer):
```{r}
inline_hook <- function(x) {
if (is.numeric(x)) {
format(x, digits = 2)
} else x
}
knitr::knit_hooks$set(inline = inline_hook)
```
Is it possible to span a heading across multiple columns with hwrite (or any other HTML-creating package)? I can sort of fake it with dataframe pieces nested within a larger table, but it's not quite a real span (and it looks ugly).
I did not see a version of this in the examples but maybe there exists elsewhere.
Thanks,
Tom
Edit: I should add that the print.xtable method does html, also (I shouldn't assume that is known). Use the type = "html" option.
No experience with html, but I do the following with LaTeX.
In the xtable package, the print.xtable method has an option add.to.row that allows you to do just that. For add.to.row you add a list-of-lists, where the first list is a list of row numbers and the second list is a list of commands to insert at that spot. From the ?print.xtable:
add.to.row -- a list of two
components. The first component (which
should be called 'pos') is a list
contains the position of rows on which
extra commands should be added at the
end, The second component (which
should be called 'command') is a
character vector of the same length of
the first component which contains the
command that should be added at the
end of the specified rows. Default
value is NULL, i.e. do not add
commands.
For LaTeX I use the following homemade command that add a "(1)" above the coefficient and t-stat column.
my.add.to.row <- function(x) {
first <- "\\hline \\multicolumn{1}{c}{} & "
middle <- paste(paste("\\multicolumn{2}{c}{(", seq(x), ")}", sep = ""), collapse = " & ")
last <- paste("\\\\ \\cline {", 2, "-", 1 + 2 * x, "}", collapse = "")
string <- paste(first, middle, last, collapse = "")
list(pos = list(-1), command = string)
}
HTH.
I can't see an obvious way of generating a table with headers that cross multiple columns. Here's a really awful hack that might solve your problem though.
Generate your table as normal.
In the source code for that page, the first row of the table will look something like
<td someattribute="somevalue">First column name</td><td someattribute="somevalue">Second column name</td>
You can read the file into R, either with htmlTreeParse from the XML package, or plain old readLines.
Now replace the offending bit of html with the correct value. The stringr package may well help here.
<td someattribute="somevalue" colspan="2">Column name spanning two columns</td>
And write back out to file.