This question already has answers here:
How to merge 2 vectors alternating indexes?
(6 answers)
Closed 9 months ago.
I have a DB like this:
a <-c(4, 2, 10, 2, 10, 6, 2)
b <-c(4, 6, 70, 8, 18, 4, 3)
rbind(a,b)
I can create something like this:
x <- (4, 4, 2, 6, 10, 70, 2, 8, 10, 18, 6, 4, 3)
A DB that contains a and b order in this way, it is possible? I need to do a time series and the value must be in the same position
rbind works only when both the vectors are of the same length or else it will give unexpected output. i.e.
> rbind(c(4, 3, 5), c(3, 4))
[,1] [,2] [,3]
[1,] 4 3 5
[2,] 3 4 3
Warning message:
In rbind(c(4, 3, 5), c(3, 4)) :
number of columns of result is not a multiple of vector length (arg 2)
and when we do c to make a vector, it returns an extra 3 from recycling
A more general approach is to order based on the sequence of values in both vector while concatenating the vectors`
c(a, b)[order(c(seq_along(a), seq_along(b)))]
[1] 4 4 2 6 10 70 2 8 10 18 6 4 2 3
Related
library(seastests)
paste_noNA <- function(x) {
ts(x[!is.na(x)],frequency=12)
}
a <- data.frame(a=c(1,2),b=c(2,5),c=c(10,2),
d=c(9,22),e=c(6,3),f=c(5,7),
g=c(2,12),h=c(9,7),i=c(8,8),
j=c(4,21),k=c(NA,7),l=c(4,2),
m=c(7,3),n=c(11,8),o=c(7,8),
p=c(9,6),q=c(10,9),r=c(8,9),s=c("f","h"))
a$time_series<-apply( a[,c(2:18)] , 1 , paste_noNA )
> a
a b c d e f g h i j k l m n o p q r s
1 1 2 10 9 6 5 2 9 8 4 NA 4 7 11 7 9 10 8 f
2 2 5 2 22 3 7 12 7 8 21 7 2 3 8 8 6 9 9 h
time_series
1 2, 10, 9, 6, 5, 2, 9, 8, 4, 4, 7, 11, 7, 9, 10, 8
2 5, 2, 22, 3, 7, 12, 7, 8, 21, 7, 2, 3, 8, 8, 6, 9, 9
a<-a %>% mutate(iss=isSeasonal(time_series))
Error: Problem with `mutate()` column `iss`.
i `iss = isSeasonal(time_series)`.
x Do not know the frequency of the time series.
Run `rlang::last_error()` to see where the error occurred.
Consider the code above. I am trying to get in column "time_series" a concatenation of values in the numerical columns 2 through 18 treated as a time series. I then want to check the time series for seasonality, but I get the error as stated at the end of the code block above although the paste_noNA function has already converted the concatenation to a time series. Can someone help?
I also tried
a<-a %>% mutate(time_series=ts(time_series,frequency=12)) %>%
mutate(iss=isSeasonal(time_series))
but got the error
Error: Problem with `mutate()` column `time_series`.
i `time_series = ts(time_series, frequency = 12)`.
x `time_series` must be a vector, not a `ts` object.
Run `rlang::last_error()` to see where the error occurred.
In this case, the apply function returns a list object, because " the calls to ‘FUN’ return vectors of different lengths".
time_series <- apply(a[,c(2:18)] , 1 , paste_noNA)
class(time_series)
# list
I believe the error is due to isSeasonal expecting you to provide a ts object instead of list.
I would try something like
lapply(time_series, isSeasonal)
I'm working on a Monte-Carlo simulation type problem and need to generate a vector of repeated random numbers, with the matching numbers grouped together, but in random order.
It's easier to explain with an example. If I had:
1, 3, 7, 12, 1, 3, 7, 12, 1, 3, 7, 12
I would like it sorted as:
7, 7, 7, 3, 3, 3, 12, 12, 12, 1, 1, 1 (or with the groups of matching numbers in any order but ascending/descending).
The reason I need the random order is because my MC simulation is for 2 variables, so if both are in order they won't vary independently.
I've got as far as:
sort(rep(runif(50,1,10),10), decreasing = FALSE)
Which generates 50 random numbers between 1 and 10, repeats each 10 times, then sorts the 50 groups of 10 matching random numbers in ascending order (or it could easily be descending order if I changed "FALSE" to "TRUE"). I just can't figure out the last step of getting 50 groups of 10 matching numbers in random order. Can anyone help?
Here is one option with split
unlist(sample(split(v1, v1)), use.names = FALSE)
#[1] 3 3 3 1 1 1 12 12 12 7 7 7
Or another option is match with unique
v1[order(match(v1, sample(unique(v1))))]
data
v1 <- c(1, 3, 7, 12, 1, 3, 7, 12, 1, 3, 7, 12)
An option could be as:
v <- c(1, 3, 7, 12, 1, 3, 7, 12, 1, 3, 7, 12)
lst <- split(v, unique(v))
sapply(sample(seq(length(lst)),length(lst)), function(i)lst[[i]])
# [,1] [,2] [,3] [,4]
#[1,] 3 12 7 1
#[2,] 3 12 7 1
#[3,] 3 12 7 1
#OR for having just a vector
as.vector(sapply(sample(seq(length(lst)),length(lst)), function(i)lst[[i]]))
#[1] 3 3 3 12 12 12 7 7 7 1 1 1
Say we have the following:
a=c( 1, 9, 5, 7, 8, 11)
length(a) ## 6
and I want to obtain:
a_desired=c( 1, 1, 9, 9, 5, 5, 7, 7, 8, 11)
length(a_desired) ## 10
Basically it stops replicating when it reaches the desired length, in this case 10.
If the desired length is 14,
a_desired=c( 1, 1, 1, 9, 9, 9, 5, 5, 7, 7, 8, 8, 11, 11)
Does anyone have a suggestion on how to obtain this or perhaps a link on something similar asked before ?(I'm not too sure what keyword to look for)
You could write your own function to do something like this
extend_to <- function(x, len) {
stopifnot(len>0)
times = len %/% length(x)
each <- rep(times, length(x))
more <- len-sum(each)
if (more>0) {
each[1:more] <- each[1:more]+1
}
rep(x, each)
}
a <- c( 1, 9, 5, 7, 8, 11)
extend_to(a, 6)
# [1] 1 9 5 7 8 11
extend_to(a, 10)
# [1] 1 1 9 9 5 5 7 7 8 11
extend_to(a, 14)
# [1] 1 1 1 9 9 9 5 5 7 7 8 8 11 11
extend_to(a, 2)
# [1] 1 9
We use the rep() to repeat each element a certain number of times.
So if your sequence is currently of length M and you want length N > M, then you have these possibilities:
N <= 2M: double the first (N-M) items
2M < N <= 3M: triple the first (N-2M) items, double the rest
3M < N <= 4M: quadruple the first (N-3M) items, triple the rest.
and so on.
So first, divide the target length by the current length, take the floor, and replicate the sequence that many times. Then add an extra copy of the first remainder items.
a=c( 1, 9, 5, 7, 8, 11)
m=length(a)
n=10 # desired new length
new_a = append(
rep(a[1:(n%%m)],each=ceiling(n/m)),
rep(a[((n%%m)+1):m],each=floor(n/m)))
I have bunch of observations
x = c(1, 2, 4, 1, 6, 7, 11, 11, 12, 13, 14)
that I want to turn into the group:
y = c(1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3)
I.e I want the first 5 integers (1 to 5) to constitute one group, the next 5 integers to constitute the next group (6 to 10), and so on.
Is there a straightforward way to accomplish this without a loop?
Clarification: I need to programmatically create the groups form the input vector (x)
We can use %/% to create the group
x%/%5+1
#[1] 1 1 1 1 2 2 3 3 3 3 3
You can use ceiling to create groups
ceiling(x/5)
# [1] 1 1 1 1 2 2 3 3 3 3 3
I want to rearrange this vector decreasingly:
x <- c(10, 10, 7, 3, 6, 2, 2, 7, 8, 1, 3, 1, 1, 1, 5, 5, 5, 4, 4, 2, 1, 4, 4, 3, 3, 2, 2, 1)
order(x)
But it returns numbers which are different:
## [1] 10 12 13 14 21 28 6 7 20 26 27 4 11 24 25 18 19 22 23 15 16 17 5 3 8 9 1 2
order function returns permutation, not sorted vector:
http://stat.ethz.ch/R-manual/R-patched/library/base/html/order.html
> x <- c (3, 2, 4, 1)
> order(x)
[1] 4 2 1 3
The result (4 2 1 3) means that the smallest item is the 4th (that's 1), the second smallest is the 2nd (2)... and the biggest is the 3d item (which is 4)
if you want to sort the vector, use sort function:
> sort(x)
[1] 1 2 3 4
To sort in decreasing order specify decreasing parameter:
> sort(x, decreasing = TRUE)
[1] 4 3 2 1
order(x) returns indices of the elements of x in increasing order. You'll note that the smallest element of x is in 10th position in x, the second smallest (actually just as small) is at position 12 and so on.
to get x in decreasing order you can either use
sort(x, decreasing=TRUE)
or use order as an index:
x[order(-x)]
(why -x? Because order returns indices in increasing order. by flipping the numbers around zero you get the indices in decreasing order)