This question already has answers here:
Equivalent to unix "less" command within R console
(5 answers)
Closed 8 years ago.
Say I want to print a large object in R, such as
x <- 1:2e3
When I print x, the R console fills the screen with its elements and, since it doesn't fit all in the screen, it will scroll down. Then I have to scroll back up to see everything that went off screen.
What I would like is to have a command that would print x and stop when the screen fills, requiring the user to do something (like press enter) in order to have another screen full of data displayed. What I have in mind is something similar to MS DOS's dir /p command. Is there such a thing?
As suggested by #baptiste, this solution, page(x, method = 'print'), doesn't really solve my problem. To be more clear, what I would like is a solution that wouldn't involve printing the object in another window, as this would disrupt my workflow. If I didn't care for this, I'd just use View() or something similar.
Here is a quick and dirty more function:
more <- function(expr, lines=20) {
out <- capture.output(expr)
n <- length(out)
i <- 1
while( i < n ) {
j <- 0
while( j < lines && i <= n ) {
cat(out[i],"\n")
j <- j + 1
i <- i + 1
}
if(i<n) readline()
}
invisible(out)
}
It will evaluate the expression and print chunks of lines (default to 20, but you can change that). You need to press 'enter' to move on to the next chunk. Only 'Enter' will work, you can't just use the space bar or other keys like other programs and it does not have options for searching, going back, etc.
You can try it with a command like:
more( rnorm(250) )
Here is an expanded version that will quit if you type 'q' or 'Q' (or anything starting with either) then press 'Enter', it will print out the last lines rows of the output if you type 'T' then enter, and if you type a number it will jump to that decile through the output (e.g. typing 5 will jump to half way through, 8 will be 80% of the way through). Anything else and it will continue.
more <- function(expr, lines=20) {
out <- capture.output(expr)
n <- length(out)
i <- 1
while( i < n ) {
j <- 0
while( j < lines && i <= n ) {
cat(out[i],"\n")
j <- j + 1
i <- i + 1
}
if(i<n){
rl <- readline()
if( grepl('^ *q', rl, ignore.case=TRUE) ) i <- n
if( grepl('^ *t', rl, ignore.case=TRUE) ) i <- n - lines + 1
if( grepl('^ *[0-9]', rl) ) i <- as.numeric(rl)/10*n + 1
}
}
invisible(out)
}
Related
I have a question how to make a IF
for (i in 1:12){
for (j in 1:12) {
if (i != j) {
var = x + b
}
else{ }
}}
"else" I need that when they are equal to continue with j + 1 example: if i = 4 and j = 4 then continue with j = 5 and continue counting until the end of j and continue the process of when i! = j
I think you don't understand what is going on in your code or you don't understand what for loops do. One "trick" you can do is to actually print what happens in your for loops so that you will have one idea of what is going on. You could also do this with a piece of paper.
As they already pointed you out, you don't need the else because the for already takes care of this.
for (i in 1:12){
print("-------------------------------")
valueI <- paste0("my i value is ",i)
print(valueI)
for (j in 1:12) {
valueJ <- paste0("my j value is ",j)
print(valueJ)
if (i != j) {
#var = x + b
diff <- paste0(i, " is different than ", j)
print(diff)
}
else{
}
}
}
This code is the same as yours and will generate a log that explains you what happens step from step, you could also use a debugger but seeing your struggles, better use this for now. What are you trying to calculate? I feel like you want to calculate the power of something...
I used to write for loops in R like
for(i in 1:size) { ... }
and I thought that it was equivalent of
for(int i = 1; i <= size; i++) { ... }
but I just realised that if size == 0 R enters the loop anyway because 1:size = [1 0] and so my code behaves totally wrong.
So, what is the real standard way of translating the C for loop I wrote above, such that if size < 1 the program does not enter the loop?
Assuming that size is some size of your object, e.g. length(vec) or nrow(df), you can use seq_along like below:
x = NULL
for (i in seq_along(x)) print(x[i])
If size is originally the length of a vector, the standard way is
for (i in seq_along(myvector)) {...}
which will behave correctly if myvector has length zero. So you could even do
for (i in seq_along(numeric(size))) {...}
but that would be certainly not be considered "standard".
As noted in the comments (and in another answer) the better way is
for (i in seq_len(size)) {...}
You can use base::seq_len:
foo <- 2
bar <- 0
for (i in seq_len(foo)) {print(i)}
[1] 1
[1] 2
# No output
for (i in seq_len(bar)) {print(i)}
I did some programming work on R language to do the bubble sort. Sometimes it works perfectly without any error message, but sometimes, it shows "Error in if (x[i] > x[i + 1]) { : argument is of length zero". Can any one help me check whats wrong with it? I have attached my code below
example <- function(x) {
n <- length(x)
repeat {
hasChanged <- FALSE
n <- n - 1
for(i in 1:n) {
if ( x[i] > x[i+1] ) {
temp <- x[i]
x[i] <- x[i+1]
x[i+1] <- temp
hasChanged <- TRUE
cat("The current Vector is", x ,"\n")
}
}
if ( !hasChanged ) break;
}
}
x <-sample(1:10,5)
cat("The original Vector is", x ,"\n")
example(x)
The error occurs because you are iteratively decreasing n. Depending on the original vector's order (or lack thereof), n can reach the value of 1 after the last change. In that case, a further reduction of n in the next iteration step addresses the value x[0], which is undefined.
With a minimal correction your code will work properly, without giving error messages. Try to replace the line
if ( !hasChanged ) break;
with
if ( !hasChanged | n==1 ) break
Basically you have two termination criteria: Either nothing has been changed in the previous iteration or n is equal to one. In both cases, a further iteration won't change the vector since it is already ordered.
By the way, in R programming you don't need a semicolon at the end of a command. It is tolerated/ignored by the interpreter, but it clutters the code and is not considered good programming style.
Hope this helps.
I have a loop I want to execute that depends on the output of the previous loop in the code. This is the code;
holder <- list()
if (i < historyLength) movement <- movementType(relAngle, angleThreshold)
else if (i > historyLength-1) {
# Array to store speeds
speedHistory <- array(historyLength)
n = historyLength-1
# get the speeds from the previous n (hisoryLength) "Movements"
for (j in seq(1, length(historyLength))){
speedHistory [n] = R[i-j, 6]
n-1
}
if (!bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- "non-moving"
else if(bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- movementType(relAngle, angleThreshold)
}
holder [[i]] <- (movement)
for (t in seq(1, length(holder))){
if (t == t-1)
changes <- 0
else if (t != t-1)
changes <- 1
}
You cannot see the beginning of loop but it results in a column of data called 'movements.'
I have attempted to temporarily store the 'movements' in the object 'holder.' What i want then is for the bottom for loop to go through 'holder' and label changes as either 0 or 1 in another column. Basically if the next 'movement' is not equal to the previous record the change as 0 and so forth. I think the problem is with the object 'holder' perhaps?
Currently I'm getting it to loop but it's only printing out a column of '1's.'
Any help much appreciated! Thanks.
Currently get the following output:
Movement Changes
left 1
right 1
forward 1
non-moving 1
non-moving 1
Think the problem lies in the list where movements are stored? Sorry, if I knew where the problem was I'd be more specific. Really new to this!
I end up with a data frame with column headers "Distance" "Speed" "Heading" "Movement" and "Changes." It's looping fine but for some reason Changes reults in a column of 1's as above. Is there an obvious mistake below?:
holder[[i]] <- (movement)
for (t in seq(1, length(holder))){
if (t == t-1)
changes <- 0
else if (t != t-1)
changes <- 1
I have also tried this, but then it doesn't loop at all.
holder[[i]] <- (movement)
for (t in seq(1, length(holder))){
if (holder[t] == holder[t-1])
changes <- 0
else if (holder[t] != holder[t-1])
changes <- 1
I'm currently getting this error: Error in holder[[t - 1]] : attempt to select less than one element
for the following code:
holder <- list(movement)
for (t in length(holder)){
if (holder[[t]] == holder[[t-1]])
changes <- 0
else changes <- 1
This is too long for a comment so I'm putting this as answer (actually it might answer your problem):
As I already mentioned in a comment to your previous question, you should have a look at what is seq(1, length(holder)) and so what you are doing when you put if (t == t-1) : you are doing something like "if 1==0" which cannot be TRUE.
You need to go with "the second version" of your loop (or, actually, without a loop...), which compares the right things, except that holder is a list so you need to either define it as a vector or use double brackets (holder[[t]]).
You don't need another if after else (what you are actually "saying" to R is "if A is true then do something, else, if 'opposite A' is true then do something else" but, necessarily, if A is not TRUE, then 'opposite A' is...
So something like:
for (t in seq(length(holder))){
if (holder[[t]] == holder[[t-1]]) changes <- 0 else changes <- 1
}
Please consider spending some time on the answer from your previous question to understand why your solution didn't work and why the answer provided did. (This includes reading documentations for the different functions and also take a look at the values your variable can take, e.g. running the loop, one "turn" at a time).
I am programming R and am confronted with the following syntax errorĂ–
Here is the code:
for (i in (1:7)) {for (index in seq(i,56,8)) {values[[length(values)+1]] <- c(ADDLINEORDER[index]) } time_series_values[[length(time_series_value)+1]] <- values}
Error: unexpected symbol in "for (i in (1:7)) {for (index in seq(i,56,8)) {values[[length(values)+1]] <- c(ADDLINEORDER[index]) } time_series_values"
what I want is: lets say that there is a vector (1,5,6,7,3,9) as input
As I result I want to have it like ((1,6,3),(5,7,9))
1 5 are the starting points, I want it to be iterated by 2 so (1, 6, 9) are together in one list.
Thanks
Missing semicolon. You pasted this into one line from something that was more than one line?
for (i in (1:7)) {for (index in seq(i,56,8)) {values[[length(values)+1]] <- c(ADDLINEORDER[index]) }; time_series_values[[length(time_series_value)+1]] <- values}
#Spacedman has found the problem. Formatting properly also fixes it:
for ( i in (1:7) ) {
for ( index in seq(i, 56, 8) ) {
values[[ length(values) + 1 ]] <- c( ADDLINEORDER[index] )
}
time_series_values[[ length(time_series_value) + 1 ]] <- values
}