working with nested for loop with if statment - r

I have a data frame of two columns first is the longitude and second is the latitude. I want to find the coordinates of the center cell.
e.g. the range is lat[31 31.5], lon[33 33.5] if the first values of two columns fulfill this condition then create the third column and put the value 31.25 and create the fourth column and put in it the value 33.25
I have tried nested for loop but it does not work
# my dataframe is cycle8 contain 166 rows and two columns
latitude<- seq(31,37,by=0.5)
longitude<- seq(33,37,by=0.5)
cycle8$latcenter<- 0
cycle8$loncenter<-0
for (m in 1:nrow(cycle8))
{
for(j in seq_along(latitude))
{
for(k in seq_along(longitude))
{
if (cycle8$lat[m]>=j && cycle8$lat[m]<=j+0.5 && cycle8$lon[m]>=k &&
cycle8$lon[m]<=k+0.5)
{
cycle8$latcenter[m]<- j+0.25
cycle8$loncenter[m]<- k+0.25
}
}
}
}
the following code will work and deliver the desired result but it is so long and requires a lot of statement typing
cycle8$latcenter<- 0
for (m in 1:nrow(cycle8))
{
if (cycle8$lat[m]>=31 && cycle8$lat[m]<=31.5 )
{
cycle8$latcenter[m]<- 31+0.25
}
else if
(cycle8$lat[m]>=31.5 && cycle8$lat[m]<=32 ){
cycle8$latcenter[m]<- 31.5+0.25
}
else if
(cycle8$lat[m]>=32 && cycle8$lat[m]<=32.5 ){
cycle8$latcenter[m]<- 32+0.25
}
else if
(cycle8$lat[m]>=32.5 && cycle8$lat[m]<=33 ){
cycle8$latcenter[m]<- 32.5+0.25
}
else if
(cycle8$lat[m]>=33 && cycle8$lat[m]<=33.5 ){
cycle8$latcenter[m]<- 33+0.25
}
else if
(cycle8$lat[m]>=33.5 && cycle8$lat[m]<=34 ){
cycle8$latcenter[m]<- 33.5+0.25
}
else if
(cycle8$lat[m]>=34 && cycle8$lat[m]<=34.5 ){
cycle8$latcenter[m]<- 34+0.25
}
else if
(cycle8$lat[m]>=34.5 && cycle8$lat[m]<=35 ){
cycle8$latcenter[m]<- 34.5+0.25
}
else if
(cycle8$lat[m]>=35 && cycle8$lat[m]<=35.5 ){
cycle8$latcenter[m]<- 35+0.25
}
else if
(cycle8$lat[m]>=35.5 && cycle8$lat[m]<=36 ){
cycle8$latcenter[m]<- 35.5+0.25
}
else if
(cycle8$lat[m]>=36 && cycle8$lat[m]<=36.5 ){
cycle8$latcenter[m]<- 36+0.25
}
else if
(cycle8$lat[m]>=36.5 && cycle8$lat[m]<=37 ){
cycle8$latcenter[m]<- 36.5+0.25
}
}

My solution avoids for-loops, sapply or other similiar functions. The logic behind the code is as follows: Since the ranges have decimals .50 or .00, the centered values will always be .25 or .75. This means that we simply need to replace the decimals; all decimals between .00 and.50 become.25, while the other ones become .75.
Here the code for this
# generate data
latitude <- seq(30, 32, .1)
longitude <- seq(30, 32, .1)
cycle8 <- data.frame(latitude, longitude)
# make a function that replaces decimals as explained above
lat_lon <- function(vec){
decimals <- as.character(format(vec, nsmall= 1))
decimals <- as.numeric(gsub("^.*\\.", "", decimals))
decimals <- ifelse(decimals < 5, .25, .75)
values <- as.numeric(gsub("\\..*","",vec)) + as.numeric(decimals)
return(values)
}
# apply function
cycle8$lat_center <- lat_lon(latitude)
cycle8$lon_center <- lat_lon(longitude)
# see results
cycle8
EDIT
Because you want 30.00 to be 29.75 and 30.50 to be 30.25, here is an edit. But the logic remains the same.
latitude <- seq(30, 32, .1)
longitude <- seq(30, 32, .1)
cycle8 <- data.frame(latitude, longitude)
lat_lon <- function(vec){
decimals <- as.character(format(vec, nsmall= 1))
decimals <- as.numeric(gsub("^.*\\.", "", decimals))
decimals_new <- ifelse(decimals > 5 | decimals == 0, .75, .25)
values <- as.numeric(gsub("\\..*","",vec)) + as.numeric(decimals_new)
values[decimals == 0] <- values[decimals == 0] - 1
return(values)
}
cycle8$lat_center <- lat_lon(latitude)
cycle8$lon_center <- lat_lon(longitude)
cycle8

# The other way of solving this question is
mydata<- c(35.666,35.4578,35.0, 33.50,32.10)
centered_value <- function(val){
a<- trunc(val)
b<- val %% 1
c<- ifelse(b/0.5 > 1, a +0.75 , ifelse(b/0.5> 1, a+0.25, ifelse(b/0.5 ==0, a-
0.25,a+0.25)))
}
d<- centered_value(mydata)
d

Related

Creating a random play function in R

I want to create a gambling game that does the following:
It is a lottery, which asks for 5 numbers comprised between 01 and 43 and an additional number comprised between 01 and 16; the idea is that I give my 6 numbers and it tells me if I won or not.
To do so, use this code
Lotery = function(a,b,c,d,e,f){
NumeroAleatorio <- matrix(1:6, ncol = 6)
NumeroAleatorio[1] <- sample (1:43, 1, replace= FALSE)
for (i in 2:6) {
if(i!=6){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
if(i == 2){
while(NumeroAleatorio[i] == NumeroAleatorio[1] ){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
}
}else{
if(i == 3 ){
while(NumeroAleatorio[i] == NumeroAleatorio[1] || NumeroAleatorio[i] == NumeroAleatorio[2]){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
}
}else{
if(i == 4 ){
while(NumeroAleatorio[i] == NumeroAleatorio[1] || NumeroAleatorio[i] == NumeroAleatorio[2] || NumeroAleatorio[i] == NumeroAleatorio[3]){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
}
}else{
if(i == 5 ){
while(NumeroAleatorio[i] == NumeroAleatorio[1] || NumeroAleatorio[i] == NumeroAleatorio[2] || NumeroAleatorio[i] == NumeroAleatorio[3] || NumeroAleatorio[i] == NumeroAleatorio[4] ){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
}
}
}
}
}
}else{
NumeroAleatorio[6] <- sample (1:16, 1, replace= FALSE)
}
}
ContA<-0
ContB<-0
ContC<-0
ContD<-0
ContE<-0
ContF<-0
for(p in 1:6){
if(NumeroAleatorio[p] == a){
ContA<-ContA+1
}
if(NumeroAleatorio[p] == b){
ContB<-ContB+1
}
if(NumeroAleatorio[p] == c){
ContC<-ContC+1
}
if(NumeroAleatorio[p] == d){
ContD<-ContD+1
}
if(NumeroAleatorio[p] == e){
ContE<-ContE+1
}
if(NumeroAleatorio[p] == f){
ContF<-ContF+1
}
}
if(ContA==0 || ContB==0 || ContC==0 || ContD==0 || ContE==0 || ContF==0){
return(data.frame("Resultado", NumeroAleatorio, "Numero escogido", a, b, c, d, e, f, "No Ganaste"))
}else{
return(data.frame("Resultado", NumeroAleatorio, "Numero escogido", a, b, c, d, e, f, "Ganaste"))
}
}
Lotery(20,15,3,45,9,8)
It seems to work, but I want to know if I can make things simpler because I think the code is too long.
I may not be following your code, but it looks like you randomly select 6 numbers and compare them to the numbers submitted. None of the first 5 should match, but the 6th can match one of the first 5. If that is correct then this will generate the random 6 numbers:
NumeroAleatorio <- c(sample.int(43, 5, replace=FALSE), sample.int(16, 1))
To compare this to the submitted values, just use
NumeroAleatorio == comp
All FALSE indicates no matches. Any TRUE values indicate a match at that position.

Couldn't calculate prime numbers within a range

for (i in 2:100 )
{
count <- 0
for (j in i )
if( (i %% j ) == 0 )
count <- count + 1
if(count == 2 )
print(i)
}
I am trying to print print prime numbers in R. Could any one help me to resolve
Let us look at your code and show what went wrong. It's the inner loop that did not loop at all:
for (i in 2:100 )
{
count <- 0
for (j in 1:i ) # you forgot to provide a vector here
if( i %% j == 0 )
count <- count + 1
if(count == 2)
print(i)
}
The answer above tries to optimise the code some more and is a more efficient solution. For example does it only test odd numbers because even ones clearly aren't prime numbers.
The below code creates the function prime_numbers which returns prime numbers up to an inputted number.
prime_numbers <- function(n) {
if (n >= 2) {
x = seq(2, n)
prime_nums = c()
for (i in seq(2, n)) {
if (any(x == i)) {
prime_nums = c(prime_nums, i)
x = c(x[(x %% i) != 0], i)
}
}
return(prime_nums)
}
else {
stop("Input number should be at least 2.")
}
}
## return the answer to your question
prime_numbers(100)
If you wanted the range 3:100, after running the above code you could run something like this:
a<-prime_numbers(100)
a[a>3]
I hope this helps!

Loop returns error: 'argument is of length zero'

i <- 2
j <- 0
for (i in 2:1000) {
if(return.prime(i)){j = j + 1}
i = i + 1
}
I want to check how many prime numbers there are in 1 to 1000 using my own function return.prime which returns TRUE when the number input is a prime and FALSE when the number input is not prime. The return.prime function is the function below and it is correct.
return.prime <- function(d){
if(d ==1 ){print(FALSE)}
if (d == 2){
print(TRUE)
}
if(d !=2 && d!=1){
if(any(d %% (2:(d-1)) == rep(0,d-2))==TRUE){
print(FALSE)}
else
print(TRUE)
}
}
The problem is when I run my program it says:
[1] TRUE
Error in if (return.prime(i)) { : argument is of length zero
I do not know what causes the length zero.
R doesn't work that way. You're just having the function print the word "TRUE" or "FALSE". Instead, you need to ?return TRUE or FALSE. Consider:
return.prime <- function(d){
if(d==1){ return(FALSE) }
if(d==2){ return(TRUE) }
if(d !=2 && d!=1){
if(any(d %% (2:(d-1)) == rep(0,d-2))==TRUE){
return(FALSE)
} else{
return(TRUE)
}
}
}
i <- 2
j <- 0
for (i in 2:1000) {
if(return.prime(i)){j = j + 1}
i = i + 1
}
j # [1] 168

implement matrix determinant in R

I was asked to implement function that calculates n-dimensional matrix determinant using Laplace expansion. This involves recursion. I developed this:
minor<-function(A,i,j) {
return(A[c(1:(i-1),(i+1):dim(A)[1]),c(1:(j-1),(j+1):dim(A)[2])])
}
determinantRec<-function(X,k) {
if (dim(X)[1] == 1 && dim(X)[2] == 1) return(X[1][1])
else {
s = 0
for (i in 1:dim(X)[2]) {
s = s + X[k][i]*(-1)^(k+i)*determinantRec(minor(X,k,i),k)
}
return(s)
}
}
where k in determinantRec(X,k) function indicates which row I want to use Laplace expansion along of.
My problem is when I run determinantRec(matrix(c(1,2,3,4),nrow = 2,ncol = 2),1) this error appears:
C stack usage 7970628 is too close to the limit
What is wrong with my code?
#julia, there is one simple type in your code. Just remove the '*' at the end of the definition of 's'. And don't indent the recursion.
determinantRek<-function(X,k) {
if (dim(X)[1] == 1 && dim(X)[2] == 1)
return(X[1,1])
if (dim(X)[1] == 2 && dim(X)[2] == 2)
return(X[1,1]*X[2,2]-X[1,2]*X[2,1])
else
s = 0
for (i in 1:dim(X)[2]) {
s = s + X[k,i]*(-1)^(k+i)
determinantRek(X[-k,-i],k)
}
return(s)
}
I did this way and works just fine, although it is super slow, compared to the det function in base R
laplace_expansion <- function(mat){
det1 <- function(mat){
mat[1]*mat[4]-mat[2]*mat[3]
}
determinant <- 0
for(j in 1:ncol(mat)){
mat1 <- mat[-1,-j]
if(nrow(mat1) == 2){
determinant <- determinant+mat[1,j]*(-1)^(1+j)*det1(mat1)
}else{
val <- mat[1,j]*(-1)^(1+j)
if(val != 0){
determinant <- determinant+val*laplace_expansion(mat1)
}
}
}
return(determinant)
}
This is my approach, I think it's cleaner.
deter <- function(X) {
stopifnot(is.matrix(X))
stopifnot(identical(ncol(X), nrow(X)))
if (all(dim(X) == c(1, 1))) return(as.numeric(X))
i <- 1:nrow(X)
out <- purrr::map_dbl(i, function(i){
X[i, 1] * (-1)^(i + 1) * deter(X[-i, -1, drop = FALSE])
})
return(sum(out))
}
Thank you #ArtemSokolov and #MrFlick for pointing the problem cause, it was it. I also discovered that this code does not calculate properly the determinant of 2x2 matrix. After all it looks like that:
determinantRek<-function(X,k) {
if (dim(X)[1] == 1 && dim(X)[2] == 1)
return(X[1,1])
if (dim(X)[1] == 2 && dim(X)[2] == 2)
return(X[1,1]*X[2,2]-X[1,2]*X[2,1])
else
s = 0
for (i in 1:dim(X)[2]) {
s = s + X[k,i]*(-1)^(k+i)*
determinantRek(X[-k,-i],k)
}
return(s)
}
Debuging with browser() was also helpful :)

Change winddirection degrees to char in R

I have read in a csv file about weather on days. One of the variables is called winddirection (windrichting) but it is given in degrees and 0 and 990 have special meaning.
I want to change the numbers to North/South/West/East but when I used the replace function it changed the datatype of the whole vector to char which prevented my next replace with a range to work. So now I ended up with an if/else if/else statement but I can't get it to work. Also I get an error condition has length > 1. Can anyone help me get this to work so I have the ranges 45-135 to east, 135-225 south, etc.
here is my code where mydata$DD is the variable for wind direction with over 2000 values.
windrichting <- mydata$DD
windrichting <- if (windrichting == 990 ){
windrichting == "Veranderlijk"
} else if (windrichting>45 && windrichting<=135){
windrichting == "Oost"
} else if (windrichting>135 && windrichting<=225){
windrichting == "Zuid"
} else if (windrichting>225 && windrichting <=315){
windrichting == "West"
} else if (windrichting ==0){
windrichting == "Windstil"
} else windrichting == "Noord"
Perhaps something along the lines of this?
tmp <- round((windrichting + 45) / 90) %% 8
tmp[windrichting == 990] <- 8
tmp <- factor(tmp, levels = 0:9, labels = c("Noord", "Oost", "Zuid", "West", "Veranderlijk", "Windstil"))
tmp[windrichting == 0] <- "Windstil"
windrichting <- tmp
You can do this using an *apply function.
windrichting_text <- unlist(lapply(windrichting, function (x) {
if (x == 990) {
return("Veranderlijk")
} else if {
....
} else {
return ("Noord")
})
This applies the function defined to all elements in the list.

Resources