I have this formula in R, i want to be able to apply it to a different number of value without rewriting it again. e.g: 6 price comparisons instead of 4. How can i do that?
i have been doing is this way, but when i want to compare to different lags and leads, I have to rewrite it
a<- for (i in price [sP+1]:length(price)){
if (price[i] < price[i-1] & price[i] < price[i-2] &
price[i] < price[i-3] & price[i] < price[i-4] &
price[i] < price[i+1] & price[i] < price[i+2] &
price[i] < price[i+3] & price[i] < price[i+4])
}
You could check the differences around price[i]. e.g.
price <- c(27, 30, 4, 13, 2, 19, 25, 28, 26, 8)
# Say you want to check around i=5:
lo <- price[5] - price[1:4]
-25 -28 -2 -11
hi <- price[5] - price[6:9]
-17 -23 -26 -24
both <- c(lo, hi)
all(both < 0)
TRUE
You could wrap that in a function that passes the price vector, the target price index number and the lo/hi ranges as parameters, then return the output from the all function.
Related
I am struggling with some constraints that have ranged variables and several decision variables.
The constraints are
`if a[i] <= t <= a[i]+b[i], then M[t][i] == 1,
else if t < a[i] or t > a[i]+b[i], then M[t][i] == 0.
decision variables (int a[i], b[i])
(boolean M[t][i])
Examples of ranges of the variables
0 <= a[i] <= 50
0 <= b[i] <= 10
0 <= t <= 100`
I'd like to linearize these formulations, like as Big-M method or etc...
Plz, let me know the way to overcome it.
Thank you.
Linearization by using the Big-M method or etc...
such as...
M*t + (M-1)*t <= M*(a[i]) + (M-1)*a[i]
I'm trying to round random grades (vector) to the nearest grade (category) with for and if loop. The idea is that the function takes the grades and puts them into a category. The category holds the rounded grades and has the variable 'gradesRounded'. gradesRounded will be returned and printed and this is giving logical(0) as output. I would very much like for a vector containing the rounded grades to be the output. How do I fix this? (input/output should be vectors and function name + return(gradesRounded must include due to it being assignment-related) output should be -3, 7, 4, 12, -3
roundGrade <- function(grades) {
grades <- c(-3, 7, 3, 11, -2)
gradesRounded <- category
for (i in grades){
if (grades >= -3 & grades <= -2) {category=("-3")}
else if (grades >= -2 & grades <= 00) {category=("00")}
else if (grades >= 1 & grades <= 02) {category=("02")}
else if (grades >= 3 & grades <= 4) {category=("4")}
else if (grades >= 6 & grades <= 7) {category=("7")}
else if (grades >= 8 & grades <= 10) {category=("10")}
else if (grades >= 11 & grades <= 12) {category=("12")}
return(gradesRounded)
}
}
You probably were trying to do :
roundGrade <- function(grades) {
category <- numeric(length(grades))
for (i in seq_along(grades)) {
if (grades[i] >= -3 & grades[i] <= -2) {category[i]= -3}
else if (grades[i] >= -2 & grades[i] <= 0) {category[i]= 0}
else if (grades[i] >= 1 & grades[i] <= 2) {category[i]= 2}
else if (grades[i] >= 3 & grades[i] <= 4) {category[i]= 4}
else if (grades[i] >= 6 & grades[i] <= 7) {category[i]= 7}
else if (grades[i] >= 8 & grades[i] <= 10) {category[i]= 10}
else if (grades[i] >= 11 & grades[i] <= 12) {category[i]= 12}
}
return(category)
}
grades <- c(-3, 7, 3, 11, -2)
result <- roundGrade(grades)
result
#[1] -3 7 4 12 -3
Also have a look at ?cut and ?findInterval which is helpful for such cases.
I am trying to check numbers in three columns in a data frame and if they're within a certain range, I want a certain output. I have this part of the code, but one of my tests wants to know if all three are negative, then I get a certain output. My issue is that some of the data in some of the columns are NA. I want to ignore the NAs in my logic. Is there a way to do this? A sample of my code is below.
if((DataWSGR$RouteType == 7 | DataWSGR$RouteType == 9) & (DataWSGR$SGR > 5 ) & (0 < DataWSGR$`30_Year_SGR` < 5) & (0 < DataWSGR$`20_Year_SGR` < 5) & (0 < DataWSGR$`10_Year_SGR` < 5)) {}
The 10, 20, and 30 year SGRs are the columns that will have NAs in them.
After fixing the range condition, I think you can just add | is.na(var) to the last three conditions:
if ((DataWSGR$RouteType == 7 |
DataWSGR$RouteType == 9)) &
(DataWSGR$SGR > 5) &
(DataWSGR$`30_Year_SGR` > 0 & DataWSGR$`30_Year_SGR` < 5 | is.na(DataWSGR$`30_Year_SGR`)) &
(DataWSGR$`20_Year_SGR` > 0 & DataWSGR$`20_Year_SGR` < 5 | is.na(DataWSGR$`20_Year_SGR`)) &
(DataWSGR$`10_Year_SGR` > 0 & DataWSGR$`10_Year_SGR` < 5 | is.na(DataWSGR$`10_Year_SGR`))) {
}
If DataWSGR has more than one row, the above will throw an error.
Here is a reproducible example for doing this in a for loop:
df <- data.frame(
route_type = c(7, 6, 9),
sgr = c(6, 3, 6),
sgr_30 = c(3, 1, NA),
sgr_20 = c(1, 1, NA),
sgr_10 = c(2, 1, NA)
)
for (i in 1:nrow(df)) {
if (
(df$route_type[i] == 7 | df$route_type[i] == 9) &
(df$sgr[i] > 5) &
(df$sgr_30[1] > 0 & df$sgr_30[i] < 5 | is.na(df$sgr_30[i])) &
(df$sgr_20[1] > 0 & df$sgr_20[i] < 5 | is.na(df$sgr_20[i])) &
(df$sgr_10[1] > 0 & df$sgr_10[i] < 5 | is.na(df$sgr_10[i]))
) {
print(paste("In range in row", i))
}
}
I have a problem with a school task -> BMI calculator
Here is my code:
#Przedziały
niedowaga <- seq(16.00, 18.40, 0.01)
norma <- seq(18.50, 24.90, 0.01)
nadwaga <- seq(25.00, 30.00, 0.01)
print(niedowaga)
print(norma)
print(nadwaga)
#Pytanie
waga = as.integer(readline(prompt="Podaj swoją wagę: "))
wzrost = as.integer(readline(prompt="Podaj swój wzrost w cm: "))
#Formuła
bmi <- waga/wzrost**2 * 10000
#Zaokrąglenie BMI do jednej liczby po przecinku
bmi_round <-round(bmi, digits = 2)
#Wyświetlenie wartości BMI po zaokrągleniu
print(bmi_round)
#Sprawdzenie BMI w oparciu o przedziały
for(bmi_round in niedowaga) {
if(bmi == niedowaga) {
print("Niedowaga")
}
}
else {
if (bmi == norma) {
print("Norma")
}
}
else if (bmi == nadwaga) {
print("Nadwaga")
}
I have three sequence variables, "niedowaga, norma, and nadwaga"
I calculated the BMI index.
Now I need to make a loop to check the computed BMI. "bmi_round" have to check to which sequence it fits - "niedowaga", "norma" and "nadwaga" (the first three variables) and give the output based on the computed BMI and sequence-
How can I do this?
Sorry for language in comments and in variables name - it's polish ;)
A loop is not needed for this:
waga = 30L #changed from readline
wzrost = 60L #changed from readline
bmi <- waga/wzrost**2 * 10000
ifelse(bmi >= 16 & bmi < 18.5, 'Niedowaga',
ifelse(bmi >= 18.5 & bmi < 25, 'Norma',
ifelse(bmi >=25 & bmi <= 30, 'nadwaga', 'outside normal range')))
# or
dplyr::case_when(bmi >= 16 & bmi < 18.5 ~ 'Niedowaga',
bmi >= 18.5 & bmi < 25 ~ 'Norma',
bmi >=25 & bmi <= 30 ~ 'nadwaga',
TRUE ~ 'outside normal range')
For your loop, there are overall errors. It appears that you are trying to compare the bmi_round variable with everything else. Instead, your loop isn't really doing anything - bmi_round is changing to each element of niedowaga in the loop and is not being used. Here is one way to change it
bmi_round <- 23
for(nied in niedowaga){
if (bmi_round == nied) print("Niedowaga")
}
for (norm in norma){
if (bmi_round == norm) print("Norma")
}
# [1] "Norma"
for (nad in nadwaga){
if (bmi_round == norm) print("Nadwaga")
}
I have a dataframe named flow with over 17,000 entries which contains daily water quality days for about 50 years. I have a column that has the jday (day of the year) of each entry but now I want to assign each entry a season from 1 to 4 (winter, spring, fall, summer). This is what I have so far:
> for(i in flow){
+ if (flow$jdays[i] <= 80 | flow$jdays[i]>355){
+ flow$season [i] <- 1
+ } else if (flow$jdays [i] > 80 & flow$jdays [i]<= 172){
flow$season [i] <- 2
+ }
+ else if(flow$jdays [i] > 172 & flow$jdays [i]<= 264){
+ flow$season [i] <- 3
+ }
+ else{
+ flow$season [i] <- 4
+ }
+ }
I keep getting the following message:
Error in if (flow$jdays[i] <= 80 | flow$jdays[i] > 355) { :
argument is of length zero
this may be better approach,
flow$season<-ifelse(flow$jdays<=80 | flow$jdays>355 ,1,
ifelse(flow$jdays<=172,2,
ifelse(flow$jdays<=264,3,4)))
This is in error:
for(i in flow){
Change to:
for(in in seq(nrow(flow))){
A vectorized solution using ifelse:
transform(flow, season=
ifelse (jdays <= 80 | jdays>355, 1,
ifelse(jdays <= 172,2,
ifelse(jdays <= 264, 3, 4))))