Convenient indexing to end of array - r

So I'm coming from Python where I can index until the end of an array by either omitting the end index. (Note that Python is 0-indexed):
In [1]: x = range(10)
In [2]: x
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [3]: x[4:]
Out[3]: [4, 5, 6, 7, 8, 9]
In [4]: x[-6:]
Out[4]: [4, 5, 6, 7, 8, 9]
In [5]: x[-1]
Out[5]: 9
Also, negative indices start from the end of the array. In R, so far I've found that I need to do things like this:
> x <- 0:9
> x[5:length(x)]
[1] 4 5 6 7 8 9
and so on. Is there any sort of syntactic sugar for length(x)? (Perhaps something like end that MATLAB uses).

You could use the tail function instead of indexing.
In the following, the final 6 elements of the vector x are returned. 6 is the default return length for tail (and head, shown below), and the second argument changes that. So if you were to write tail(x, 5) for example, the final 5 elements will be returned.
> x <- 0:9
> tail(x)
# [1] 4 5 6 7 8 9
> tail(x, 5)
# [1] 5 6 7 8 9
Similarly, there is a head function for viewing the first few elements, which operates in the same manner.
> head(x)
# [1] 0 1 2 3 4 5
> head(x, 5)
# [1] 0 1 2 3 4

Logical indexing is one method. As mentioned (but not demonstrating the second argument to head or tail):
> x <- 1:10
> head(x,-3)
[1] 1 2 3 4 5 6 7
> tail(x,-3)
[1] 4 5 6 7 8 9 10
> x[x>=4]
[1] 4 5 6 7 8 9 10
Mixing negative and positive indices is not allowed.

Related

What function is the opposite of diff in R?

I know this is a stupid question, but is there a function in R that is the opposite of diff, where you can add consecutive pairs in a vector. I.e. if you had the original vector 1, 2, 3, 4, 5, you would get back 3, 5, 7, 11 (1+2, 2+3, 3+4, 4+5)?
You could use filter function.just ensure you have the right felter/kernel for the lag. Ie lag=1 in the diff function use filter=c(1,1) in the filter function. :
x <-1:5
filter(x, c(1,1), sides = 1)
Here are some possibilities:
rowSums(embed(x, 2))
## [1] 3 5 7 9
x |> embed(2) |> rowSums() # same but with pipes
## [1] 3 5 7 9
head(x, -1) + tail(x, -1)
## [1] 3 5 7 9
diff(cumsum(c(0, x)), 2)
## [1] 3 5 7 9
c(ts(x) + lag(ts(x)))
## [1] 3 5 7 9
library(zoo)
rollsum(x, 2)
## [1] 3 5 7 9
# Since this is a linear operation it has a matrix M
M <- apply(diag(length(x)), 2, rollsum, 2)
c(M %*% x)
## [1] 3 5 7 9
# Take sub or super diagonal of the outer sum
out <- outer(x, x, `+`)
out[row(out) == col(out) - 1]
## [1] 3 5 7 9
Note
x <- 1:5

How can I merge a list of vectors (in R) such that they have a minimum length?

I have the following four vectors:
A <- c(5, 5, 5, 5, 5, 5, 5)
B <- c(6, 6, 6)
C <- c(7, 7, 7, 7)
D <- c(8, 8, 8, 8)
In the end, I'd like to transform this list of vectors (here 4 vectors) into all pairwise combinations of full vectors (i.e. no splitting of individual vector) with the concatenated vector having a minimum length of 7. One possible solution would thereby be:
s1 <- c(5, 5, 5, 5, 5, 5, 5, 6, 6, 6)
s2 <- c(7, 7, 7, 7, 8, 8, 8, 8)
How would I do that?
I use combn to make pairwise combinations of your individual vector (ignoring direction c(A,B) == c(B,A) and self-concatenation, c(A,A) is not desired)
temp <- combn(list(A,B,C,D), 2)
threshold <- 7
L1 <- lapply(1:ncol(temp), function(x) Reduce("c", c(temp[1,x], temp[2,x])))
Discard concatenated vectors with length less than 7. I use lengths (note different from length) to grab length of all vectors in the list
L2 <- L1[lengths(L1) >= threshold]
Output
[[1]]
[1] 5 5 5 5 5 5 5 6 6 6
[[2]]
[1] 5 5 5 5 5 5 5 7 7 7 7
[[3]]
[1] 5 5 5 5 5 5 5 8 8 8 8
[[4]]
[1] 6 6 6 7 7 7 7
[[5]]
[1] 6 6 6 8 8 8 8
[[6]]
[1] 7 7 7 7 8 8 8 8

Subsetting elements of a vector in R

I have been trying to create a list with the coordinates of a vector which have the same values.
Example: for a vector Points = (2, 2, 3, 6, 3, 6, 3), coordinates that have the same value are (1,2), (3, 5, 7) and (4,6). So the output should be something like
[[1]]
1 2
[[2]]
3 5 7
[[3]]
4 6
Just to contextualize the necessity of this function: I'm trying to simulate random walks with multiple starting points. Once any given chains hit each other, the one with smallest index will be update. The vector Points is the position of all the walks at some time step t. I need to verify, at each time step, which chains have the same value, in order to update just the one with smallest index. In this particular example, just chains 1, 3 and 4 would be updated at instant t+1.
Maybe something like this:
X = c(2, 3, 4 )
Y = c(4, 3 ,5)
Z = c(8, 8 , 9, 6)
W = c(3, 3, 7,4)
V = c(9, 9, 9,3)
findeev<-function(vi){ #takes a list of vector(s) to extract from `allv`
nms=paste("v",vi,sep="")
ne=max(sapply(allv[vi],length)) #max number of elements
ine=1:ne
# Computes sd along the positions of all vetors
rest=apply(cbind(sapply(allv[vi],function(vt)vt[ine])),1,sd)
# determine if some vectors have the same value across a position
resc=which(rest==0)
if(length(resc)){ret=allv[vi];ret$pos=resc
names(ret)[-length(ret)]<-nms
ret} else invisible()
}
allv=list(X,Y,Z,W,V)
findeev(c(3,5)) #exmple
sol=list();j=1 # This contains all pairs
for(i in (length(allv)-1):2){
# compare all combinations of vector using `findeev`
res<-apply(t(combn(1:length(allv),i )),1,findeev)
if(is.null(res))next #not found continues
# eliminate NAs form list and assign that to sol[[j]]
sol[[j]]<-Filter(Negate(function(x) is.null(unlist(x))), res)
j=j+1
}
sol
You get:
> findeev(c(3,5))
$v3
[1] 8 8 9 6
$v5
[1] 9 9 9 3
$pos
[1] 3
> sol
[[1]]
[[1]][[1]]
[[1]][[1]]$v1
[1] 2 3 4
[[1]][[1]]$v2
[1] 4 3 5
[[1]][[1]]$v4
[1] 3 3 7 4
[[1]][[1]]$pos
[1] 2
[[2]]
[[2]][[1]]
[[2]][[1]]$v1
[1] 2 3 4
[[2]][[1]]$v2
[1] 4 3 5
[[2]][[1]]$pos
[1] 2
[[2]][[2]]
[[2]][[2]]$v1
[1] 2 3 4
[[2]][[2]]$v4
[1] 3 3 7 4
[[2]][[2]]$pos
[1] 2
[[2]][[3]]
[[2]][[3]]$v2
[1] 4 3 5
[[2]][[3]]$v4
[1] 3 3 7 4
[[2]][[3]]$pos
[1] 2
[[2]][[4]]
[[2]][[4]]$v3
[1] 8 8 9 6
[[2]][[4]]$v5
[1] 9 9 9 3
[[2]][[4]]$pos
[1] 3

Abbreviate a numeric vector when displaying it in the console

I'd like to abbreviate a numeric vector when displaying it through the R console. I tried already the function ?abbreviate, but it does not the thing I want. In fact I want the whole vector to be abbreviated, not each element of the vector. In addition, I want to pass ... at the breaking position so to indicate it goes on. How can I make this?
x = 1:100
x 1, 2, 3, 4, 5, 6 ...
Try str().
x <- 1:100
str(x, vec.len = 2.5, give.head = FALSE)
# 1 2 3 4 5 6 ...
But David Arenburg makes a good suggestion with cat(). Here's a function which allows you to adjust the length more precisely.
f <- function(x, n) cat(x[1:n], "...")
f(x, 5)
# 1 2 3 4 5 ...
f(x, 9)
# 1 2 3 4 5 6 7 8 9 ...
Update: In response to your comment about putting the text name of the input before the values, you can adjust the function as follows.
f <- function(x, n) {
cat(substitute(x), head(x, n), if(n < length(x)) "...")
}
stuff <- 1:100
f(stuff, 6)
# stuff 1 2 3 4 5 6 ...
f(stuff, 12)
# stuff 1 2 3 4 5 6 7 8 9 10 11 12 ...

how to get index of sorted array elements

Say I have an array in R : c(10, 7, 4, 3, 8, 2)
Upon sorting, this would be : c(2, 3, 4, 7, 8, 10)
What is the best way in R to return the indices for the sorted array elements from the original array. I'm looking for an output like :
6(index of 2), 4(index of 3), 3(index of 4), 2(index of 7), 5(index of 8), 1(index of 10)
The function you're looking for is order:
> x
[1] 10 7 4 3 8 2
> order(x)
[1] 6 4 3 2 5 1
sort has index.return argument, which by default is FALSE
x <- c(10,7,4,3,8,2)
sort(x, index.return=TRUE) #returns a list with `sorted values`
#and `$ix` as index.
#$x
#[1] 2 3 4 7 8 10
#$ix
#[1] 6 4 3 2 5 1
You can extract the index by
sort(x, index.return=TRUE)$ix
#[1] 6 4 3 2 5 1

Resources