Working in RStudio, I am using knitr to create pdf files with chunks of code. In the following example, notice how in the output, spacing after the ## characters is different across the three vectors:
This looks pretty neat, but I am writing a document with examples having only one line of output and I'd like to have all the [1]'s properly in line with one another.
In the example, that would mean removing an extra space after the ##'s for the second vector. I am only starting to work with knitr and latex, so I'm not sure how I would achieve such a thing. Some sort of post-processing of the .tex? Or maybe something simpler?
This is not a knitr problem but arises from R's printing:
> 1:5
[1] 1 2 3 4 5
> 1:10
[1] 1 2 3 4 5 6 7 8 9 10
> 1:100
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
[37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
[55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
[73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
[91] 91 92 93 94 95 96 97 98 99 100
Post processing would stop your output looking like it would from R.
I'd work on getting that fixed in base R (if it is really a bug and not intended) rather than try to special case this. An RDevel email with the above example (confirmed in a recent R - the above was with 3.0.x-patched) would help you clarify (if) you need a work around.
To focus attention, consider (From #Dominic Comtois' comment)
> 20:28
[1] 20 21 22 23 24 25 26 27 28
> 20:29
[1] 20 21 22 23 24 25 26 27 28 29
why does adding a tenth element change the way R prints the vector?
This may not necessarily be an ideal solution, but I hope it will vaguely suit your needs after some tweaks.
I've defined an "adjusted" print function:
print_adj <- function(x, adjpos=6, width=3) {
# capture output
con <- textConnection("text", open="w")
sink(con)
print(format(x, width=width), quote=FALSE)
sink()
close(con)
library(stringr)
pos <- str_locate(text, fixed("]"))
for (i in seq_along(text))
text[i] <- str_c(str_dup(" ", adjpos-pos[i,1]), text[i])
cat(text, sep="\n")
}
It prints a vector x in such a way that:
the square bracket ] always occurs in the given text column
each element occupies exactly width text columns
Sample output:
> print_adj(1:5)
[1] 1 2 3 4 5
> print_adj(1:10)
[1] 1 2 3 4 5 6 7 8 9 10
> print_adj(1:100)
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
[29] 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
[57] 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
[85] 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
If you'd like to use this function in a knitr chunk, try:
<<eval=2,echo=1>>=
print(1:100) # don't eval
print_adj(1:100) # don't print this cmd
#
I was able to solve my problem by defining a hook, as Gavin Simpson suggested.
\documentclass{article}
\begin{document}
<<setup, include=FALSE>>=
require(stringr)
hook.out <- function(x, options)
return(str_c("\\begin{verbatim}",
sub("\\s+\\[1\\]\\s+"," [1] ",x),
"\\end{verbatim}"))
knit_hooks$set(output=hook.out)
#
<<>>=
1:9
1:10
#
\end{document}
Output now looks like this:
My only remaining concern is that for longer vectors, I will need to bypass the hook and I don't know how to do that.
Credits also go to Rod Alence for his example on this page.
Related
In Stata, when changing values to variables (or other related operations), the output includes a comment regarding the number of changes. E.g:
Is there a way to obtain similar commentary in RStudio?
For instance, sometimes I want to check how many changes a command made (partly to see if command worked, or to count the extent of a potential problem in the data). Currently, I have to inspect the data manually or do a pretty uninformative comparison using all(), for instance.
Base R doesn't do this, but you could write a function to do it, and then instead of saying
x <- y
you'd say
x <- showChanges(x, y)
For example,
library(waldo)
showChanges <- function(oldval, newval) {
print(compare(oldval, newval))
newval
}
set.seed(123)
x <- 1:100
x <- showChanges(x, x + rbinom(100, size = 1, prob = 0.01))
#> `old[21:27]`: 21 22 23 24 25 26 27
#> `new[21:27]`: 21 22 23 25 25 26 27
x
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#> [19] 19 20 21 22 23 25 25 26 27 28 29 30 31 32 33 34 35 36
#> [37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#> [55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#> [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#> [91] 91 92 93 94 95 96 97 98 99 100
Created on 2021-10-21 by the reprex package (v2.0.0)
I am unable to figure out how can i write or condition inside which in R.
This statemnet does not work.
which(value>100 | value<=200)
I know it very basic thing but i am unable to find the right solution.
Every value is either larger than 100 or smaller-or-equal to 200. Maybe you need other numbers or & instead of |? Otherwise, there is no problem with that statement, the syntax is correct:
> value <- c(110, 2, 3, 4, 120)
> which(value>100 | value<=200)
[1] 1 2 3 4 5
> which(value>100 | value<=2)
[1] 1 2 5
> which(value>100 & value<=200)
[1] 1 5
> which(iris$Species == "setosa" | iris$Species == "virginica")
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
[37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
[55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
[73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
[91] 91 92 93 94 95 96 97 98 99 100
does work. Remember to fully qualify the names of the variables you are selecting, as iris$Species in the example at hand (and not only Species).
Have a look at the documentation here.
Also notice that whatever you do with which can be generally done otherwise in a faster and better way.
Is there actually an easy solution to reordering a vector like
first element, last element, second element, second last element, etc.
So I expect for c(1,2,3,4,5) to get c(1,5,2,4,3).
The reason is I have a color palette with 16 colours and color 1 is very similar to two but not to color 16. But within my plots, the dots coloured by color 1 are close to the ones are coloured by color 2.
For my color palette I use Set 1 from color brewer and also use colorRampPalette to calculate colours in between, so they get a bit similar.
One solution would be to just sample(my_colors) but actually I would like to reorder them like I told above.
This will do what you need:
a <- c(1,2,3,4,5)
b <- rbind(a,a[5:1])
c <-b [1:5]
Hope this helps
Here is a fiddle
You can generalise this with
rbind(a,rev(a))[1:length(a)]
Here is an easy way to do this:
a<-seq(1,100)
b<-a-median(a)
names(a)=b
a<-order(-abs(b))
print(a)
[1] 1 100 2 99 3 98 4 97 5 96 6 95 7 94 8 93 9 92 10 91 11 90 12 89 13 88 14 87
[29] 15 86 16 85 17 84 18 83 19 82 20 81 21 80 22 79 23 78 24 77 25 76 26 75 27 74 28 73
[57] 29 72 30 71 31 70 32 69 33 68 34 67 35 66 36 65 37 64 38 63 39 62 40 61 41 60 42 59
[85] 43 58 44 57 45 56 46 55 47 54 48 53 49 52 50 51
From the comments:
1: From #bgoldst: A better (one line) approach that doesn't involve vector names:
a[order(-abs(a-median(a)))]
2: (Also from bgoldst) For dealing with non-numeric (alphabetical order) values:
letters[order(-abs(seq_along(letters)-(length(letters)+1)/2))]
An analysis which I ran produced around 500 files which are named file1 to file500
However, some files in between are missing (such as file233 and file245 as well as others). I would like to further process them in a loop in R but then I would need to filter out the files which are not present.
Is there an easy way to store the number after file in a vector in R which I can then use for the loop?
v<-containing all numbers after file which are present in the directory
Should have mentioned that the files do not have the ending .txt but are just names fileXX where the XX is the number
The best way is to simply create a list of the files that are actually present in the directory, like #beginneR said:
list_of_files = list.files('/path/to/dir')
do_some_processing = function(list_element) {
# Perform some processing and return something
}
lapply(list_of_files, do_some_processing)
If you need the numbers in the filename, a simple regular expression will do:
> grep('[0-9]', sprintf('file%d', 1:100))
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
[37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
[55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
[73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
[91] 91 92 93 94 95 96 97 98 99 100
The getOption("max.print") can be used to limit the number of values that can be printed from a single function call. For example:
options(max.print=20)
print(cars)
prints only the first 10 rows of 2 columns. However, max.print doesn't work very well lists. Especially if they are nested deeply, the amount of lines printed to the console can still be infinite.
Is there any way to specify a harder cutoff of the amount that can be printed to the screen? For example by specifying the amount of lines after which the printing can be interrupted? Something that also protects against printing huge recursive objects?
Based in part on this question, I would suggest just building a wrapper for print that uses capture.output to regulate what is printed:
print2 <- function(x, nlines=10,...)
cat(head(capture.output(print(x,...)), nlines), sep="\n")
For example:
> print2(list(1:10000,1:10000))
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12
[13] 13 14 15 16 17 18 19 20 21 22 23 24
[25] 25 26 27 28 29 30 31 32 33 34 35 36
[37] 37 38 39 40 41 42 43 44 45 46 47 48
[49] 49 50 51 52 53 54 55 56 57 58 59 60
[61] 61 62 63 64 65 66 67 68 69 70 71 72
[73] 73 74 75 76 77 78 79 80 81 82 83 84
[85] 85 86 87 88 89 90 91 92 93 94 95 96
[97] 97 98 99 100 101 102 103 104 105 106 107 108