judge the values crossing zero - r

I would like to determine whether or not the ranges of min and max values cross zero (0 = crossing zero, 1 = not crossing zero).
min <- c(0, -1, -1, 1, 1)
max <- c(1, 1, -0.1, 3, 1.5)
answer <- c(0, 0, 1, 1, 1)
data <- cbind(min,max, answer)

You can use the between function from dplyr:
library(dplyr)
min <- c(0, -1, -1, 1, 1)
max <- c(1, 1, -0.1, 3, 1.5)
df1 = data.frame(min,max) %>%
rowwise() %>%
mutate(answer = as.numeric(!between(0,min,max)))
Or using base R:
df1 = data.frame(min,max)
df1$answer = apply(df1, 1, function(x) as.numeric(!(x[1]<= 0 & x[2] >=0)))

Base R vectorised answer -
transform(data, answer = as.integer(!(min <= 0 & max > 0)))
# min max answer
#1 0 1.0 0
#2 -1 1.0 0
#3 -1 -0.1 1
#4 1 3.0 1
#5 1 1.5 1
If you prefer dplyr the same can be written as -
library(dplyr)
data %>% mutate(answer = as.integer(!(min <= 0 & max > 0)))
data
min <- c(0, -1, -1, 1, 1)
max <- c(1, 1, -0.1, 3, 1.5)
data <- data.frame(min,max)

You can simply multiply them, as to cross you either need a negative product or one being zero.
answer <- ifelse(min * max <= 0, 0, 1)
or
answer <- as.integer(min * max > 0)
# [1] 0 0 1 1 1
If your 0 and 1 are not a requirement, even shorter to get a TRUE or FALSE
answer <- min * max <= 0
# [1] TRUE TRUE FALSE FALSE FALSE

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:

Calculate row specific based on min

My data looks like this
df <- data.frame(x = c(3, 5, 4, 4, 3, 2),
y = c(.9, .8, 1, 1.2, .5, .1))
I am trying to multiply each x value by either y or 1, depending on which has the least value.
df$z <- df$x * min(df$y, 1)
The problem is it is taking the min of the whole column, so it is multiplying every x by 0.1.
Instead, I need x multiplied by .9, .8, 1, 1, .5, .1...
We need pmin that will go through each value of 'y' and get the minimum val when it is compared with the second value (which is recycled)
pmin(df$y, 1)
#[1] 0.9 0.8 1.0 1.0 0.5 0.1
Likewise, we can have n arguments (as the parameter is ...)
pmin(df$y, 1, 0)
#[1] 0 0 0 0 0 0
To get the output, just multiply 'x' with the pmin output
df$x * pmin(df$y, 1)
which can also be written as
with(df, x * pmin(y, 1))
Maybe you could use an ifelse function:
df <- data.frame(x = c(3, 5, 4, 4, 3, 2),
y = c(.9, .8, 1, 1.2, .5, .1))
df$z = ifelse(df$y<1, df$x*df$y, df$x*1)
This will compare the values of each row.
Hope it helps! :)

R function with multiple operators

data ranges from -6 to 6 and I am trying to create 3 categories, however my function is not returning anyone for category 2 even though there are people present
FFMIBMDcopdcases$lowBMD = ifelse((FFMIBMDcopdcases$copd_Tscore >= -1) , 0,
ifelse((FFMIBMDcopdcases$copd_Tscore < -1), 1,
ifelse((FFMIBMDcopdcases$copd_Tscore <= -2.5), 2, NA)))
Try using cut function. Example:
myValues <- runif(n = 20, min = -6, max = 6)
as.numeric(as.character(cut(x = myValues, breaks = c(-Inf, -2.5, -1, Inf), labels = c(2, 1, 0))))
Since you want a numeric result it might be easiest to use findInterval although you will need to subtract the result from 2 to get in the inverse order ( 2 for lowest and 0 for highest) :
FFMIBMDcopdcases$lowBMD = 2 - findInterval(FFMIBMDcopdcases$copd_Tscore ,
c(-Inf, -2.5, -1, Inf) )

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

Resources