Why "c" is equal to 1000 here? - r

This loop is going over all the values of i in range(92:1000) and whichever value of i is holding the condition true it is breaking the loop by setting that value of i in c and when i am trying to run this code block in R language it is giving me c=1000.
> c=0
> for (i in range(92:1000)){
+ if(dpois(i,94.32)<=dpois(5,94.32))
+ {c=i;
+ break;
+ }
+ }
> c
[1] 1000
But what i expected it should give value of c=235 as at i=235 as:--
> dpois(235,94.32)
[1] 2.201473e-34
> dpois(5,94.32)
[1] 6.779258e-34
> dpois(235,94.32)<=dpois(5,94.32)
[1] TRUE
And it should break whenever the condition is true for the first time.
Where am i going wrong ?

In R, range computes the range of the given data, i.e. the minimum and maximum
> range(92:1000)
[1] 92 1000
Also, using c as a variable name is very bad practice in R. Since c is an intrinsic function used to define vectors.
The following gives the expected answer
> c0=0
> for (i in 92:1000){
+ if(dpois(i,94.32)<=dpois(5,94.32))
+ {
+
+ c0=i
+ break
+
+ }
+ }
> c0
[1] 234

Related

How do I create a function that defines a moving threshold along local maxima in R?

The goal is to quantify a certain growth. The definition is as follows:
Every value in the sequence shall be compared to the preceding value and if the following value is greater than the preceding one, it shall be taken into regard (returned). If not, it shall be dropped. Consequently, the greater value is used as a new reference for the following ones. A threshold that moves with the ascending values. I've tried this:
growthdata<-c(21679, 21722, 21788, 21863, 21833, 21818, 21809, 21834, 21937, 22026, 22025, 22235, 22191, 22348, 22399, 22463, 22532, 22562, 22589, 22609, 22556, 22565)
growthfun<-function (a) {
for (i in a) {
if (i < (i+1)) {
return(i)
}
else {
next
}
}
}
It's a beginner's problem. I seem to be uncapable of defining the following value (i+1). The way I wrote it, R simply adds 1 to i's value.
The result should look like this:
21679, 21722, 21788, 21863, 21937, 22026, 22235, 22348, 22399, 22463, 22532, 22562, 22589, 22609
Thanks in advance!
There are some issues in your function growthfun:
What you need might be print, not return. Otherwise, the function exits when the condition is met
You may need the index of elements in a, which should be i in seq_along(a)
An example for you objective might be something like below:
If you want to print the progress, then use print
growthfun<-function (a) {
for (i in seq_along(a)) {
if (a[i] >= max(a[1:(i-1)])) {
print(a[i])
}
else {
next
}
}
}
which gives
> growthfun(growthdata)
[1] 21679
[1] 21722
[1] 21788
[1] 21863
[1] 21937
[1] 22026
[1] 22235
[1] 22348
[1] 22399
[1] 22463
[1] 22532
[1] 22562
[1] 22589
[1] 22609
If you want to save the output in an array
growthfun<-function (a) {
r <- c()
for (i in seq_along(a)) {
if (a[i] >= max(a[1:(i-1)])) {
r <- c(r,a[i])
}
else {
next
}
}
r
}
which gives
> growthfun(growthdata)
[1] 21679 21722 21788 21863 21937 22026 22235 22348 22399 22463
[11] 22532 22562 22589 22609
You can use cummax with only unique values.
unique(cummax(growthdata))
#[1] 21679 21722 21788 21863 21937 22026 22235 22348 22399 22463 22532 22562 22589 22609

Pythagorean Theorem in R programming

I want write R code for Pythagoras theorem.
The Pythagorean Theorem states that the square of the hypotenuse (the side opposite the right angle) is equal to the sum of the squares of the other two sides.
(sideA)^2+(SideB)^2=hypotenuse^2
Now I wrote the R code as below:
pythag<-function(sidea,sideb){
if (sidea>=0&sideb>=0)
hypoteneuse=sqrt(sidea^2+sideb^2)
else if (sidea<0|sideb<0)
hypoteneuse<-"Values Need to be Positive"
else if (!is.vector(x))
hypoteneuse<-"I need numeric values to make this work"
print(hypoteneuse)
}
pythag(4,5)
pythag("A","B")
pythag(-4,-5)
In case of pythag(4,5) it is ok, also pythag(-4,-5) is giving comment "Values Need to be Positive".
But in case of pythag("A","B") I want comment "I need numeric values to make this work", but unfortunately my code does't work for this.
You can try like this:
get_hypotenuse_length <- function(height, base)
{
sides <- c(height, base)
if(any(sides < 0))
{
message("sides must be positive")
} else if(!is.numeric(x = sides))
{
message("sides can not be non-numeric")
} else
{
sqrt(x = sum(sides ^ 2))
}
}
Here's an annotated version. It is creating the function which takes the values a and b and calculates c. It is first testing if the values are numeric, if they are not numeric it will print your error message, otherwise it will ignore what is within those curly brackets and move on to the next test. The second test is checking that both are greater than zero (seeing as a triangle can't have a side of length zero or negative length). If it satifies the condition that both are >0 then it will calculate c, if not it will give the error stating that there are negative values.
# Feed it the values a and b (length of the two sides)
pythag <- function(a,b){
# Test that both are numeric - return error if either is not numeric
if(is.numeric(a) == FALSE | is.numeric(b) == FALSE){
return('I need numeric values to make this work')}
# Test that both are positive - return length of hypoteneuese if true...
if(a > 0 & b > 0){
return(sqrt((a^2)+(b^2)))
}else{
# ... give an error either is not positive
return('Values Need to be Positive')
}
}
Here's a more streamlined version:
pythag <- function(a,b){
if(is.numeric(a) == FALSE | is.numeric(b) == FALSE){return('I need numeric values to make this work')}
if(a > 0 & b > 0){return(sqrt((a^2)+(b^2)))}
else{return('Values Need to be Positive')}
}
And this is what it returns with your examples:
> pythag(4,5)
[1] 6.403124
> pythag("A","B")
[1] "I need numeric values to make this work"
> pythag(-4,-5)
[1] "Values Need to be Positive"
if x = c("sideA", "sideB"), then it will still be a vector so your test is.vector(x) will return true:
> is.vector(x)
[1] TRUE
But you want to test if it's numbers, so if it's numeric:
> is.numeric(x)
[1] FALSE

Plot function with else if statement in R

trying to plot the following function over the interval [-1,1] but am getting error code:
"Warning messages:
1: In if (g < a) { :
the condition has length > 1 and only the first element will be used
2: In if (g >= a & g <= b) { :
the condition has length > 1 and only the first element will be used"
unifCDF<-function(g) {
if (g< a) {
0
}
else if (g>=a & g<=b) {
(g-a)/(b-a)
}
else if (g>b) {
1
}
}
I know the function itself works since unifCDF() works for all values I tested. Any ideas?
Your function works on single values:
> unifCDF(.5)
[1] 0.75
but not on vectors:
> unifCDF(c(0.2,.3))
[1] 0.60 0.65
Warning messages:
1: In if (g < a) { :
the condition has length > 1 and only the first element will be used
2: In if (g >= a & g <= b) { :
the condition has length > 1 and only the first element will be used
and plot.function needs functions to work on vectors. The lazy way is to just Vectorize your function:
> unifCDF=Vectorize(unifCDF)
> unifCDF(c(0.2,.3))
[1] 0.60 0.65
> plot.function(unifCDF,-1,1)
which then works.
The right way is to code it so that it handles vector arguments naturally.
unifCDF = function(g){
res = (g-a)/(b-a)
res[g<a]=0
res[g>b]=1
res
}
in this code, res is always a vector of the same length as g. The first line computes the slopey bit for all values of g, and then the next two lines set the relevant bits outside the (a,b) limits to 0 and 1.
Note that having global variables, like a and b are generally a bad thing.

How to detect numbers from one column in another and write data from another column in R?

I'm very new at R language. I tried to make simple code to find some data in different intervals with information about start-end of interval and table with bigger intervals for now, I got several codes for solving but none of them work.
The main idea is that I have several variables which represent different arrays (i,k,j). Code, in my opinion, should look for each array in another table for two things (if it bigger than the first column and if it smaller then second, if both true - right all this to another table and go to other intervals).
if(mydatatable[k,21]>=mydatatable[i,16]){
if(mydatatable[k,21]<=mydatatable[j,18])
shifr[n,1]<-n&shifr[n,2]<-mydata[k,21]&shifr[n,3]<-mydata[k,22]&i+1&j+1&k+1&n+1
else i+1&j+1&k+1
}
else {
if(mydatatable[i,16]==0) end
else i+1&j+1&k+1
}
for this code several errors
Error in if (mydatatable[k, 21] >= mydatatable[i, 16]) { :
missing value where TRUE/FALSE needed
In addition: Warning message:
In Ops.factor(mydatatable[k, 21], mydatatable[i, 16]) :
‘>=’ not meaningful for factors
I wonder, why programm thinks, that mydatatable is factor? Why it should be some TRUE/FALSE value, I thought, that it was already established in formula.
The second code is pretty much the same and it even might work.
I preestablished the values i,k and j as 1 (i=1, k=1, j=1)
But there comes a error
> ifelse(mydatatable[k,21]>=mydatatable[i,16],
+ ifelse(mydatatable[k,21]<=mydatatable[j,18],
+ shifr[n,1]<-n&shifr[n,2]<-mydata[k,21]&shifr[n,3]<-mydata[k,22]&i+1&j+1&k+1&n+1,i+1&j+1&k+1),
+ ifelse(mydatatable[i,16]==0,
+ end),
+ i+1&j+1&k+1)
Error in ifelse(mydatatable[k, 21] >= mydatatable[i, 16], ifelse(mydatatable[k, :
unused argument (i + 1 & j + 1 & k + 1)
I'm confused, why it's happening.
Please, help.
Here is an example of data. What I want to get is demonstrated here https://1drv.ms/f/s!Aj4W4aYSeYkGiIFKHG0TV-TRQvWaIQ
Here what I got, after several use of data.table::foverlaps (I fixed some problems, but initially I got this)
> data.table::foverlaps(int1,sh2,by.x=c("start","end"),by.y=c("start","end"))
Error in data.table::foverlaps(int1, sh2, by.x = c("start", "end"), by.y = c("start", :
The first 2 columns of y's key is not identical to the columns specified in by.y.
I have also got some progress with previous code. Several problems: first, how to unite several commands (I used & and ; but none of them worked properly in shifr[n,1]<-n;shifr[n,2]<-sh[k,1];shifr[n,3]<-sh[k,1];i+1&j+?)
Second, is about Error in FUN(left, right).
> ifelse(sh[k,1]>=int[i,1],
+ + ifelse(sh[k,2]<=int[j,2],
+ + shifr[n,1]<-n;shifr[n,2]<-sh[k,1];shifr[n,3]<-sh[k,1];i+1;j+1;k+1;n+1,i+1;j+1;k+1),
Error: unexpected ';' in:
" + ifelse(sh[k,2]<=int[j,2],
+ shifr[n,1]<-n;"
> + i+1;j+1;k+1
[1] 16
[1] 16
[1] 65
> ifelse(sh[k,1]>=int[i,1],
+ + ifelse(sh[k,2]<=int[j,2],
+ + shifr[n,1]<-n;shifr[n,2]<-sh[k,1];shifr[n,3]<-sh[k,1];i+1&j+1&k+1&n+1,i+1&j+1&k+1),
Error: unexpected ';' in:
" + ifelse(sh[k,2]<=int[j,2],
+ shifr[n,1]<-n;"
> + i+1&j+1&k+1
[1] TRUE
> ifelse(sh[k,1]>=int[i,1],
+ + ifelse(sh[k,2]<=int[j,2],
+ + shifr[n,1]<-n&shifr[n,2]<-sh[k,1]&shifr[n,3]<-sh[k,1]&i+1&j+1&k+1&n+1,i+1&j+1&k+1),
+ + i+1&j+1&k+1
+ )
Error in FUN(left, right) :
operations are possible only for numeric, logical or complex types
This code is, actually, awful. I eventually done it like that(in python):
for i in interval:
...
if float(i) < intervals[b][0]:
print("Interval are too high", intervals[b][1])
break
....
if float(i) >= intervals[b - 1][1]:
....

Lubridate fix the time units

When we take the difference of two time, there is something going on automatically there in units.
> ymd_hms("2016-05-09 15:17:03") - ymd_hms("2016-05-09 15:17:04")
Time difference of -1 secs
> ymd_hms("2016-05-09 16:17:03") - ymd_hms("2016-05-09 15:17:04")
Time difference of 59.98333 mins
> ymd_hms("2016-05-10 16:17:03") - ymd_hms("2016-05-09 15:17:04")
Time difference of 1.041655 days
How can I fix the units without using difftime function.
So I can do the following:
VECTOR = c(ymd_hms("2016-05-10 16:17:03"),
ymd_hms("2016-05-10 17:19:33"),
ymd_hms("2016-05-10 19:55:03")
)
diffs = diff(VECTOR)
IntervalsInHours = toHours(diffs)
Additionally, is there any way to know the units being used in a lubridate time object. For example,
> ymd_hms("2016-05-09 15:17:03") - ymd_hms("2016-05-09 15:17:04")
Time difference of -1 secs
The units used here are seconds.
"you want to use diff function to take the time differences between a VECTOR elements, only in the units specified"
pls try below code : (by int_diff function)
> VECTOR = c(ymd_hms("2016-05-10 16:17:03"),
+ ymd_hms("2016-05-10 16:17:04"),
+ ymd_hms("2016-05-10 17:19:33"),
+ ymd_hms("2016-05-10 19:55:03")
+ )
> as.numeric(int_diff(VECTOR))
[1] 1 3749 9330
> round(as.numeric(int_diff(VECTOR))/3600,2)
[1] 0.00 1.04 2.59
see, whatever the time interval min unit is seconds or not, it is always scaled by seconds as below.
> VECTOR = c(ymd_hms("2016-05-10 16:17:03"),
+ #ymd_hms("2016-05-10 16:17:04"),
+ ymd_hms("2016-05-10 17:19:33"),
+ ymd_hms("2016-05-10 19:55:03")
+ )
> as.numeric(int_diff(VECTOR))
[1] 3750 9330
> round(as.numeric(int_diff(VECTOR))/3600,2)
[1] 1.04 2.59
please try below to transform the time difference into hours.
library(lubridate)
x=ymd_hms("2016-05-09 16:17:03")
y=ymd_hms("2016-05-19 15:17:04")
diffs=as.duration(x-y)
IntervalsInHours=as.numeric(abs(diffs))/3600;IntervalsInHours
or you can use this way:
library(lubridate)
x=ymd_hms("2016-05-09 16:17:03")
y=ymd_hms("2016-05-19 16:17:04")
diffs=as.duration(x-y);
IntervalsInHours=abs(diffs)/dhours(1);IntervalsInHours
I wrote two functions in case anyone might find useful.
timeDiffUnitConvert = function(Diffs, to="day", roundingN = 1){
if(to == "day"){
R = round(as.numeric(as.duration(Diffs))/3600/24,roundingN)
} else if (to == "hour") {
R = round(as.numeric(as.duration(Diffs))/3600, roundingN)
} else if (to == "min") {
R = round(as.numeric(as.duration(Diffs))/60, roundingN)
} else if (to == "sec"){
R = round(as.numeric(as.duration(Diffs)), roundingN)
} else {
stop("to which unit? it must be `day`, `hour`, `min` or `sec`.")
}
R
}
timeDiffVector = function(TimeVector, to="day", roundingN = 1, attachNaMode = "none"){
R = timeDiffUnitConvert(diff(TimeVector), to = to, roundingN = roundingN)
if(attachNaMode == "leading"){
R = c(NA,R)
} else if(attachNaMode == "trailing"){
R = c(R,NA)
} else{
stop("check your attachNaMode: shall be either `leading` or `trailing`")
}
R
}

Resources