Combined subsetting in R? - r

I trying to subset 3 ys for when xs are -1, 0, and 1 in my code below. But I was hoping to do this all at once using y[c(x == -1, x == 0, x == 1)] which apparently does not work (see below).
Any better way to do this subsetting all at once?
x = seq(-1, 1, l = 1e4)
y = dcauchy(x, 0, sqrt(2)/2)
y[c(x == -1, x == 0, x == 1)] ## This subsetting format doesn't work

We can do this.
y[x == -1| x == 0| x == 1]
Or this
y[x %in% c(-1, 0, 1)]

Related

How to convert binary output to values in relation to a column in r

The sample data is as follows
ID <- c(1, 2, 3)
O1D1 <- c(0, 0, 0)
O1D2 <- c(0, 0, 0)
O1D3 <- c(0, 10, 0)
O2D1 <- c(0, 0, 0)
O2D2 <- c(0, 0, 0)
O2D3 <- c(18, 0, 17)
O3D1 <- c(0, 9, 0)
O3D2 <- c(20, 1, 22)
O3D3 <- c(0, 0, 0)
x <- data.frame(ID, O1D1, O1D2, O1D3, O2D1, O2D2, O2D3, O3D1, O3D2, O3D3)
I created a new column with some conditional logic.
Say, the new column is n
x$n <- (x$O1D3 > 0 & x$O2D3 == 0)
> x$n
[1] FALSE TRUE FALSE
What I am looking to get instead is a column with values such as
> x$n
[1] 0 10 0
Or, in other words, the values of O1D3 should replace TRUE values in the n column and the FALSE values can be replaced with 0.
Thanks for your time and help.

Piecewise Function Help in R

For a class I must create a piecewise function defined in the following way:
2x-2 , x < -1
0 , -1 <= X <= 1
x^(2)-1, x > 1
I have tried an ifelse sequence but I cant seem to make it work. I've also tried an if, elseif, else sequence, but that only seems to use the first function to calculate answers.
The end goal is to have this:
pwfun(c(-2, 0.5, 3))
2 0 8
A piece-wise function like below?
pwfun <- function(x) ifelse(x < -1, 2 * x - 2, ifelse(x <= 1, 0, x**2 - 1))
such that
> pwfun(c(-2, 0.5, 3))
[1] -6 0 8
pwfun <- function(x) ifelse(x < -1, (x * x) -2, ifelse(x <= 1, 0, x**2 - 1))
> pwfun(c(-2, 0.5, 3))
[1] -2 0 8
The above edit to ThomasIsCoding's answer gives you what you want, but I would use this approach because it communicates it's intent better:
library(dplyr)
df <- data.frame(x = c(-2, 0.5, 3))
pwfunc <- function(data){
data %>%
mutate(y =
case_when(x < -1 ~ -2,
x > 0 & x <= 1 ~ 0,
TRUE ~ x**2 - 1)) ## TRUE in a case_when basically
## means "everything that isnt caught by my specified conditions
## becomes..." so it works like the "else" clause
}
Then just call the function on your data:
df <- data.frame(x = c(-2, 0.5, 3))
pwfunc(data)
And get:

variable data in loop in R

I have the code below where I have a loop above which is fed with a single value X:
n = 25
X = 1
p = 0.2 #probability
P = matrix( c(p, 1-p, 0, 0, 0, 0,
p, 0, 1-p, 0, 0, 0,
p, 0, 0, 1-p, 0, 0,
0, p, 0, 0, 1-p, 0,
0, 0, p, 0, 0, 1-p,
0, 0, 0, p, 0, 1-p),
ncol=6, nrow=6, byrow = TRUE) #transition matrix
for(i in 1:n){
Y = runif(1) #uniform sample
k = P[X[i], ] #calculate k values
k = cumsum(k)
if(Y <= k[1]){ #update the chain
X[i+1] = 1}
else if(Y <= k[2]){
X[i+1] = 2}
else if (Y <= k[3]){
X[i+1] = 3}
else if (Y<=k[4]){
X[i+1] = 4}
else if (Y<=k[5]){
X[i+1] = 5}
else {X[i+1]=6}
}
plot(1:n, X[1:i], type = 's')
I'm wondering that can I set my X be multi data like X = c(1,3,4), such that I can run all three values for X in only one line of code without having to resimulate by changing the value for X? The three graphs should be produced as a result.
First of all, you will want to put your code inside a function, if you aim to re-use that code. Secondly, in the code you posted, you plot the graph in the graphic device, which will be lost after you plot something else, so you might wanna save it as a PDF or PNG or something like that:
xtoplot <- function(X, n = 25, p = 0.2, transit = P){
for(i in 1:n){
Y <- runif(1) # uniform sample
k <- P[X[i], ] # calculate k values
k <- cumsum(k)
if(Y <= k[1]){ # update the chain
X[i+1] <- 1}
else if(Y <= k[2]){
X[i+1] <- 2}
else if(Y <= k[3]){
X[i+1] <- 3}
else if(Y <= k[4]){
X[i+1] <- 4}
else if(Y <= k[5]){
X[i+1] <- 5}
else{
X[i+1] <- 6}
}
pltname <- paste0("plot_", X, ".pdf") # The document name of the plot
pdf(pltname) # Tell R to prepare to export something to PDF
plot(1:n, X[1:i], type = 's') # The plot to be exported
dev.off()
}
Now that the function is in place, you can use a member of the "apply()-family" to run the function for multiple input values for X like this:
lapply(c(1,3,4), xtoplot)
In your working directory, you will find three PDFs called plot_1.pdf, plot_3.pdf and plot_4.pdf with the graphs you were looking for.

how to find the longest same number in R

for example I have data like this
x<-c(0,0,1,1,1,1,0,0,1,1,0,1,1,1)
I want find the longest sequence of "1" by considering the start and end position, in this case should be (3,6)
How to do this in R
thanks all
Here's an approach that uses seqle from the "cgwtools" package:
library(cgwtools)
y <- seqle(which(x == 1))
z <- which.max(y$lengths)
y$values[z] + (sequence(y$lengths[z]) - 1)
# [1] 3 4 5 6
You can use range if you just wanted the "3" and "6".
seqle "extends rle to find and encode linear sequences".
Here's the answer as a function:
longSeq <- function(invec, range = TRUE) {
require(cgwtools)
y <- seqle(which(invec == 1))
z <- which.max(y$lengths)
out <- y$values[z] + (sequence(y$lengths[z]) - 1)
if (isTRUE(range)) range(out) else out
}
Usage would be:
x <- c(0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1)
longSeq(x)
# [1] 3 6
longSeq(x, range = FALSE)
# [1] 3 4 5 6
And, with KFB's example input:
y <- c(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1)
longSeq(y)
# [1] 9 11
You can do this easily with base R too using rle and inverse.rle combination
Creating the funciton
longSeq2 <- function(x, range = TRUE){
temp <- rle(x == 1)
temp$values <- temp$lengths == max(temp$lengths[temp$values == TRUE])
temp <- which(inverse.rle(temp))
if (isTRUE(range)) range(temp) else temp
}
Testing
x <- c(0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,0,1,1,1)
longSeq2(x)
## [1] 3 6
longSeq2(x, range = FALSE)
## [1] 3 4 5 6
y <- c(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1)
longSeq2(y)
## [1] 9 11
longSeq2(y, range = FALSE)
## [1] 9 10 11

Buy Low Sell High

I've a data like this:
library("xts")
close <- c(0, -0.5, -0.75, -1, -0.75, -1.5, -2, -2.5, -3, -3.5, -3, -2.5, -2, -1, 0, 1, 1.5, 2, 2.5, 3, 2.5, 2, 0)
data <- xts(close, Sys.Date()-23:1)
colnames(data) <- "close"
I'd like to generate another column which will give me a trade signal based on the logic below:
Buy when the close is # or below -1, -2 and -3.
Sell all the 3 when close is # or above 0.
Short Sell when the close is # or above 1, 2 and 3
Buy all the 3 when close is # or below 0.
For this i've tried
data$trade <- 0
data$trade[data$close <= -1] <- 1
data$trade[data$close <= -2] <- 2
data$trade[data$close <= -3] <- 3
data$trade[data$close >= 1] <- -1
data$trade[data$close >= 2] <- -2
data$trade[data$close >= 3] <- -3
data trade column is giving me (0,0,0,1,0,1,2,2,,3,3,3,2,2,1,0,-1,-1,-2,-2,-3,-2,-2,0)
but i want that it should give me ((0,0,0,1,1,1,2,2,3,3,3,3,3,3,0,-1,-1,-2,-2,-3,-3,-3,0)
i want that when i buy # say -1 or -2 the trade signal should be on till we reach 0 or above and similarly when we short sell it # say -1, -2 etc the trade signal should be on till we reach 0 or below. Kindly help i've tried lots of combinations, but not getting the required result.
If I've understood correctly, this is hard to do efficiently because the choice depends upon the past. It's not elegant but this code gives the output you require,
library("xts")
close <- c(0, -0.5, -0.75, -1, -0.75, -1.5, -2, -2.5, -3, -3.5, -3, -2.5, -2, -1, 0, 1, 1.5, 2, 2.5, 3, 2.5, 2, 0)
data <- xts(close, Sys.Date()-23:1)
colnames(data) <- "close"
sig.buy <- c(F,F,F)
sig.short <- c(F,F,F)
for(i in 1:length(data))
{
if(data$close[i] <= -1) sig.buy[1] <- T
if(data$close[i] <= -2) sig.buy[2] <- T
if(data$close[i] <= -3) sig.buy[3] <- T
if(sig.buy[1] && data$close[i] >= 0) sig.buy[1] <- F
if(sig.buy[2] && data$close[i] >= 0) sig.buy[2] <- F
if(sig.buy[3] && data$close[i] >= 0) sig.buy[3] <- F
if(data$close[i] >= 1) sig.short[1] <- T
if(data$close[i] >= 2) sig.short[2] <- T
if(data$close[i] >= 3) sig.short[3] <- T
if(sig.short[1] && data$close[i] <= 0) sig.short[1] <- F
if(sig.short[2] && data$close[i] <= 0) sig.short[2] <- F
if(sig.short[3] && data$close[i] <= 0) sig.short[3] <- F
data$trade[i] <- sum(sig.buy) - sum(sig.short)
}

Resources