Create the sequence by using an R-function - r

I need to create the following sequence:
> A
1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33
> B
-1, 2, -3, 4, -5, 6, -7, 8, -9, 10
I've tried to use seq() function like this:
seq(1:3, 31:33, by = 10)
But it only allows to input 1 number in "from" and "to"
Maybe, someone knows how to use this or other functions to create the given sequence. Thank you in advance.

You can use :
A <- c(sapply(seq(0, 30, 10), `+`, 1:3))
A
#[1] 1 2 3 11 12 13 21 22 23 31 32 33
B <- 1:10 * c(-1, 1)
B
#[1] -1 2 -3 4 -5 6 -7 8 -9 10

Here's one way to get to A:
A <- rep(1:3, 3) + rep(c(0, 10, 20), each=3)
or to generalize to n
A <- rep(1:n, n) + rep(seq(0, by=10, length.out=n), each=n)
For B, I can't find anything truly elegant:
B <- 1:10 * (-1)^(1:10 %% 2)
That's the best I got

Related

Examine if a value is in an interval using R

Having the following vector:
t <- c(2, 6, 8, 20, 22, 30, 40, 45, 60)
I would like to find the values that fall between the following intervals:
g <- list(c(1,20), c(20, 40))
The desired output is:
1, 20 c(2, 6, 8)
20, 40 c(20, 22, 30)
Using the dplyr library, I do the following:
library(dplyr)
for(i in t){
for(h in g){
if(between(i, h[[1]], h[[2]])==TRUE){print(c(i, h[[1]], h[[2]]))}
}}
Is there a better way of doing this in R?
We can loop over the list 'g' and extract the 't' elements based on the first and second values by creating a logical vector with >/< and extract the elements of 't'
lapply(g, function(x) t[t >= x[1] & t < x[2]])
-output
[[1]]
[1] 2 6 8
[[2]]
[1] 20 22 30
library(purrr)
library(dplyr)
map(g,~keep(t,between(t,.[1],.[2])))
[[1]]
[1] 2 6 8 20
[[2]]
[1] 20 22 30 40
You may find findInterval() from base R useful:
g <- c(1, 20, 40)
t <- c(2, 6, 8, 20, 22, 30, 40, 45, 60)
findInterval(t, g)
#> [1] 1 1 1 2 2 2 3 3 3
So t[1], t[2] and t[3] are in the first interval, t[4], t[5] and
t[6] in the second, and t[7], t[8] and t[9] the third (meaning that
these values are bigger than the right end point of the second interval.)
If you had values lower than one they would be labelled by 0:
t2 <- c(-1, 0, 2, 6, 8, 20, 22, 30, 40, 45, 60)
findInterval(t2, g)
#> [1] 0 0 1 1 1 2 2 2 3 3 3
You can save the result of findInterval() as e.g. y and use which(y==1) to find which entries correspond to the first interval.
We can try cut + is.na like below
lapply(
g,
function(x) {
t[!is.na(cut(t, x, include.lowest = TRUE))]
}
)
which gives
[[1]]
[1] 2 6 8 20
[[2]]
[1] 20 22 30 40

Sum every x elements in a vector

I have a vector v like:
v <- c(1, 2, 46, 6, 3, 5, 67, 2, ..., 9)
I want to add the numbers three by three, so I would have the results of adding 1+6+67...
Thank you!
I would suggest creating a sequence by the width you want (in this case 3) which will start from 1 to the length of your vector and then sum:
#Data
v <- c(1, 2, 46, 6, 3, 5, 67, 2, 9)
#Seq
seqv <- seq(1,length(v),by = 3)
#Sum
sum(v[seqv])
Output:
[1] 74
You could create a sequence of values by three and use that to index the vector v and then sum the result.
v <- 10:19
s <- seq(1,9, by=3)
> v
[1] 10 11 12 13 14 15 16 17 18 19
> s
[1] 1 4 7
> sum(v[s])
[1] 39

How do I operate basic functions within a column in R?

I apologize for the poor phrasing of this question, I am still a beginner in R and I am still getting used to the proper terminology. I have provided sample data below:
mydata <- data.frame(x = c(1, 2, 7, 19, 45), y=c(10, 12, 15, 19, 24))
View(mydata)
My intention is to find the x speed, and for this I would need to find the difference between 1 and 2, 2 and 7, 7 and 19, and so on. How would I do this?
You can use the diff function.
> diffs <- as.data.frame(diff(as.matrix(mydata)))
> diffs
x y
1 1 2
2 5 3
3 12 4
4 26 5
> mean(diffs$x)
[1] 11
You can use dplyr::lead() and dplyr::lag() depending on how you want the calculations to line up
library(dplyr)
mydata <- data.frame(x = c(1, 2, 7, 19, 45), y=c(10, 12, 15, 19, 24))
View(mydata)
mydata %>%
mutate(x_speed_diff_lead = lead(x) - x
, x_speed_diff_lag = x - lag(x))
# x y x_speed_diff_lead x_speed_diff_lag
# 1 1 10 1 NA
# 2 2 12 5 1
# 3 7 15 12 5
# 4 19 19 26 12
# 5 45 24 NA 26

Multiplication of several vectors

I have 10 vectors (v_1 to v_10) and I need all of them multiplied with another vector v_mult (i.e. v_1*v_mult, v_2*v_mult etc.). How to I solve this problem within a for-loop? Im stuck to the loop-solution (which I do not find) because it is part of a larger analysis.
v_10<-c(2, 3, 5, 8)
v_20<-c(3, 9, 0, 1)
v_30<-c(15, 9, 6, 0)
v_40<-c(4, 9, 6, 1)
v_50<-c(1, 7, 3, 9)
v_60<-c(5, 9, 5, 1)
v_70<-c(5, 8, 2, 6)
v_80<-c(5, 8, 1, 6)
v_90<-c(5, 0, 1, 6)
v_10<-c(2, 8, 1, 0)
v_mult<-c(8, 5, 1, 9)
Those vectors should be all together in a matrix:
vlist <- mget(ls(pattern = "v_[[:digit:]*]"))
m <- do.call(cbind, vlist)
m * v_mult
# v_10 v_20 v_30 v_40 v_50 v_60 v_70 v_80 v_90
#[1,] 16 24 120 32 8 40 40 40 40
#[2,] 40 45 45 45 35 45 40 40 0
#[3,] 1 0 6 6 3 5 2 1 1
#[4,] 0 9 0 9 81 9 54 54 54
You can of course extract each vector from the matrix using column subsetting, e.g., m[, "v_10"] or m[, 1].
We can get all the vector objects in a list using mgetand multiply each element of the list with 'v_mult' using Map.
Map('*',mget(paste('v', seq(10, 100, by=10), sep="_")), list(v_mult))
Or use set from data.table which would be very fast as it doesn't have the .[data.table overhead.
library(data.table)
DT <- setDT(mget(paste('v', seq(10, 100, by=10), sep="_")))
for(j in seq_along(DT)){
set(DT, i=NULL, j= j, value= DT[[j]]*v_mult)
}

How to fill in the "succeeding" numbers whenever there is a 0 in R?

I have a string of numbers:
n1 = c(1, 1, 0, 6, 0, 0, 10, 10, 11, 12, 0, 0, 19, 23, 0, 0)
I need to replace 0 with the corresponding number right "behind" it to get, while leaving the 0s in the tail alone (cause there is nothing right behind them):
n2 = c(1, 1, 6, 6, 10, 10, 10, 10, 11, 12, 19, 19, 19, 23, 0, 0)
How can I get from n1 to n2?
This seems to be a much harder question than the one I've asked earlier:
How to fill in the preceding numbers whenever there is a 0 in R?
where flodel has come up with an elegant solution:
n2 <- n1[cummax(seq_along(n1) * (n1 != 0))]
However, this solution does not work here; I've tried but failed to adapt the code.
Can someone else figure out an elegant solution?
Thanks in advance!
If you don't also have NA in the vector, you can use na.locf from package zoo:
n1[n1==0] <- NA
n2 = na.locf(n1, na.rm=FALSE, fromLast=TRUE)
n2[is.na(n2)] <- 0
n2
## [1] 1 1 6 6 10 10 10 10 11 12 19 19 19 23 0 0
Here's a rle approach:
out <- rle(n1)
locs <- out$values == 0 & !seq_along(out$values) %in% length(out$values)
out$values[locs] <- out$values[which(locs) + 1]
with(out, rep(values, lengths))
## [1] 1 1 6 6 10 10 10 10 11 12 19 19 19 23 0 0
You can use flodel's suggestion in reverse
na = c(1, 1, 0, 6, 0, 0, 10, 10, 11, 12, 0, 0, 19, 23, 0, 0)
locf<-function(x) {
x<-rev(x)
a<-x[cummax(seq_along(x) * (x != 0))]
c(rev(a), rep(0, length(x)-length(a)))
}
locf(na)
# [1] 1 1 6 6 10 10 10 10 11 12 19 19 19 23 0 0

Resources