I have a long vector, let's say A <- c(12, 16, 23, 15, 89, 43, ...) and I would like to find the positions of some numbers in this vector, contained in another vector, B <- c(16, 89).
In this example, I would like to obtain the vector c(2,5). A the moment I am using a for loop, but I would really like to avoid it:
C <- numeric(length(B))
for (i in 1:length(C)){
C[i] <- which(A==B[i])
}
Any suggestion?
Thanks in advance
Try with
x <- which(A %in% B)
#> x
#[1] 2 5
Hope this helps
You can use simply:
match(B,A)
#[1] 2 5
Related
How to find GCD for a list of (1:n) numbers in R ?
GCD=function(a, b){
m=min(a, b)
while(a%%m>0|b%%m>0){m=m-1}
return(m)}
Here is my code to find GCD for two integers, how can I modify it to find GCD for a list of numbers from 1 to n without too much changes on my original code?
Thankyou very much !
You can use the any function:
GCD <- function(x) {
m = min(x)
while (any(x %% m > 0)){
m = m - 1
}
return(m)
}
GCD(c(12, 24, 28, 36, 200))
# [1] 4
GCD(c(6, 24, 28, 36, 200))
# [1] 2
You can define function gcd based on GCD like below
gcd <- function(...) Reduce(GCD,list(...))
and you can try
> gcd(6, 24, 28, 36, 200)
[1] 2
I would like to merge 2 vectors this way :
a = c(1,2,3)
b = c(11,12,13)
merged vector : c(1,11,2,12,3,13)
How could I do it ?
This will work using rbind :
c(rbind(a, b))
For example:
a = c(1,2,3)
b = c(11,12,13)
c(rbind(a,b))
#[1] 1 11 2 12 3 13
Explanation
This works because R stores arrays in column-major order.
When you rbind() the two vectors, you get:
rbind_result <- rbind(a, b)
rbind_result
# [,1] [,2] [,3]
# a 1 2 3
# b 11 12 13
Then c() coerces rbind_result into a column-wise flattened vector:
merged <- c(rbind_result)
merged
# [1] 1 11 2 12 3 13
The rbind() answer by #jalapic is excellent. Here's an alternative that creates a new vector then assigns the alternating values to it.
a <- c(1,2,3)
b <- c(11,12,13)
x <- vector(class(a), length(c(a, b)))
x[c(TRUE, FALSE)] <- a
x[c(FALSE, TRUE)] <- b
x
# [1] 1 11 2 12 3 13
And one more that shows append
c(sapply(seq_along(a), function(i) append(a[i], b[i], i)))
# [1] 1 11 2 12 3 13
Just wanted to add a simpler solution that works for when vectors are unequal length and you want to append the extra data to the end.
> a <- 1:3
> b <- 11:17
> c(a, b)[order(c(seq_along(a)*2 - 1, seq_along(b)*2))]
[1] 1 11 2 12 3 13 14 15 16 17
Explanation:
c(a, b) creates a vector of the values in a and b.
seq_along(a)*2 - 1 creates a vector of the first length(a) odd numbers.
seq_along(b)*2 creates a vector of the first length(b) even numbers.
order(...) will return the indexes of the numbers in the two seq_along vectors such that x[order(x)] is an ordered list. Since the first seq_along contains the even numbers and the second seq_along has the odds, order will take the first element from the first seq_along, then the first elements of the second seq_along, then the second element from the first seq_along, etc. interspersing the two vector indexes and leaving the extra data at the tail.
By indexing c(a, b) using the order vector, we will intersperse a and b.
As a note, since seq_along returns numeric(0) when the input is NULL this solution works even if one of the vectors is length 0.
I had to solve a similar problem, but my vectors were of unequal length. And, I didn't want to recycle the shorter vector, but just append the tail of the longer vector.
And the solution for #RichardScriven didn't work for me (though I may have done something wrong and didn't try hard to troubleshoot).
Here is my solution:
#' Riffle-merges two vectors, possibly of different lengths
#'
#' Takes two vectors and interleaves the elements. If one vector is longer than
#' the other, it appends on the tail of the longer vector to the output vector.
#' #param a First vector
#' #param b Second vector
#' #return Interleaved vector as described above.
#' #author Matt Pettis
riffle <- function(a, b) {
len_a <- length(a)
len_b <- length(b)
len_comm <- pmin(len_a, len_b)
len_tail <- abs(len_a - len_b)
if (len_a < 1) stop("First vector has length less than 1")
if (len_b < 1) stop("Second vector has length less than 1")
riffle_common <- c(rbind(a[1:len_comm], b[1:len_comm]))
if (len_tail == 0) return(riffle_common)
if (len_a > len_b) {
return(c(riffle_common, a[(len_comm + 1):len_a]))
} else {
return(c(riffle_common, b[(len_comm + 1):len_b]))
}
}
# Try it out
riffle(1:7, 11:13)
[1] 1 11 2 12 3 13 4 5 6 7
riffle(1:3, 11:17)
[1] 1 11 2 12 3 13 14 15 16 17
HTH,
Matt
#MBo's answer to my question at https://stackoverflow.com/a/58773002/2556061 implies a solution for evenly interlacing vectors of unequal length. I'm reporting it here in for reference.
interleave <- function(x, y)
{
m <- length(x)
n <- length(y)
xi <- yi <- 1
len <- m + n
err <- len %/% 2
res <- vector()
for (i in 1:len)
{
err <- err - m
if (err < 0)
{
res[i] <- x[xi]
xi <- xi + 1
err <- err + len
} else
{
res[i] <- y[yi]
yi <- yi + 1
}
}
res
}
gives
interleave(1:10, 100:120)
c(100, 1, 101, 102, 2, 103, 104, 3, 105, 106, 4, 107, 108, 5, 109, 110, 111, 6, 112, 113, 7, 114, 115, 8, 116, 117, 9, 118, 119, 10, 120)
A tidyverse approach is vctrs::vec_interleave:
vctrs::vec_interleave(a, b)
#[1] 1 11 2 12 3 13
I would like to convert a vector into a transitions matrix.
I have a vector t and divided this by its max value to get values between 0 and 1. I then made this into a matrix
t <- c(22, 65, 37, 84, 36, 14, 9, 19, 5, 49)
x <- t/max(t)
y <- x%*%t(x)
My problem is that I want the columns of the matrix (y) to add up to 1, i.e. to make it into a transition matrix but I'm not sure how to do that. Any suggestions appreciated!
sweep() is a versatile little function that you can use here to divide each column by its own sum:
yy <- sweep(y, MARGIN = 2, STATS = colSums(y), FUN = "/")
## Confirm that the columns of yy all sum to 1
colSums(yy)
## [1] 1 1 1 1 1 1 1 1 1 1
Let I have an array like
a <- seq(1, 100, 1)
and I want to select just the elements that occur each 3 steps with a for() loop starting from the second one, e.g. 2, 5, 8, 11 and so on.
How should I use for() in this case?
b <- NULL
# for(i in 1:length(a)) { # Is there any additional argument?
# b[i] <- a[...] # Or I can just multiply 'i' by some integer?
# }
Thanks,
Use 3 as the value for by in seq
for (i in seq(2, length(a), by=3)) {}
> seq(2, 11, 3)
[1] 2 5 8 11
Why use for ?
b <- a[seq(2,length(a),3)]
I have two vectors with a few thousand points, but generalized here:
A <- c(10, 20, 30, 40, 50)
b <- c(13, 17, 20)
How can I get the indicies of A that are nearest to b? The expected outcome would be c(1, 2, 2).
I know that findInterval can only find the first occurrence, and not the nearest, and I'm aware that which.min(abs(b[2] - A)) is getting warmer, but I can't figure out how to vectorize it to work with long vectors of both A and b.
You can just put your code in a sapply. I think this has the same speed as a for loop so isn't technically vectorized though:
sapply(b,function(x)which.min(abs(x - A)))
FindInterval gets you very close. You just have to pick between the offset it returns and the next one:
#returns the nearest occurence of x in vec
nearest.vec <- function(x, vec)
{
smallCandidate <- findInterval(x, vec, all.inside=TRUE)
largeCandidate <- smallCandidate + 1
#nudge is TRUE if large candidate is nearer, FALSE otherwise
nudge <- 2 * x > vec[smallCandidate] + vec[largeCandidate]
return(smallCandidate + nudge)
}
nearest.vec(b,A)
returns (1,2,2), and should comparable to FindInterval in performance.
Here's a solution that uses R's often overlooked outer function. Not sure if it'll perform better, but it does avoid sapply.
A <- c(10, 20, 30, 40, 50)
b <- c(13, 17, 20)
dist <- abs(outer(A, b, '-'))
result <- apply(dist, 2, which.min)
# [1] 1 2 2