I want to calculate the timedifference between to times - r

I want to calculate the difference of two columns of a dataframe containing times. Since not always a value from the same column ist bigger/later, I have to do a workaround with an if-clause:
counter = 1
while(counter <= nrow(data)){
if(data$time_end[counter] - data$time_begin[counter] < 0){
data$chargingDuration[counter] = 1-abs(data$time_end[counter]-data$time_begin[counter])
}
if(data$time_end[counter] - data$time_begin[counter] > 0){
data$chargingDuration[counter] = data$time_end[counter]-data$time_begin[counter]
}
counter = counter + 1
}
The output I get is a decimalvalue smaller than 1 (i.e.: 0,53322 meaning half a day)... However, if I use my console and calculate the timedifference manually for a single line, I get my desired result looking like 02:12:03...
Thanks for the help guys :)

Related

How to create two cumulative columns based off of condition output from another column?

I am trying to loop through my dataframe's rows and add 1 to either the Won or Loss column based off the Result column in the dataframe. I need it to print the dataframe row after every loop through the code.
I have tried to use the cumsum() function, but I need it to be conditional on the Result character(Won or Lost), but I have failed every time. I have also tried a for loop, and the closest I came to solving the issue was it printing out the new dataset with the total matches played in the Won Column.
for (row in 1:nrow(Dylan)) {
if( Dylan$Result == "Won") {Dylan$Won = Dylan$Won + 1}
else {Dylan$Lost = Dylan$Lost + 1}
}
Here are the errors I get:
In if (Dylan$Result == "Won") { ... :
the condition has length > 1 and only the first element will be used
2: In if (Dylan$Result == "Won") { ... :
the condition has length > 1 and only the first element will be used
I need the new dataframe to show the continual additions to each Won and Loss Columns, so the columns increase over the rows, and not just show the total amount of wins and total amount of losses in every row.
does this work:
for (row in 1:nrow(Dylan)) {
if (Dylan$Result[row] == "Won") {
Dylan$Won = Dylan$Won + 1
} else {
Dylan$Lost = Dylan$Lost + 1
}
}

Adding a counter to a loop

On a broad question that I haven't been able to find for R:
I'm trying to add a counter at the beginning of a loop.
So that when I run the loop sim = 1000:
if(hours$week1 > 1 and hours$week1 < 48) add 1 to the counter
ifelse add 0
I have came across counter tutorials that print a sentence to let you know where you are (if something goes wrong):
e.g
For (i in 1:1000) {
if (i%%100==0) print(paste("No work", i))
}
But the purpose of my counter is to generate a value output, measuring how many of the 1000 runs in the loop fall inside a specified range.
You basically had it. You just need to a) initialize the counter before the loop, b) use & instead of and in your if condition, c) actually add 1 to the counter. Since adding 0 is the same as doing nothing, you don't have to worry about the "else".
counter = 0
for (blah in your_loop_definition) {
... loop code ...
if(hours$week1 > 1 & hours$week1 < 48) {
counter = counter + 1
}
... more loop code ...
}
Instead of
if(hours$week1 > 1 & hours$week1 < 48) {
counter = counter + 1
}
you could also use
counter = counter + (hours$week1 > 1 && hours$week1 < 48)
since R is converting TRUE to 1 and FALSE to 0.
How about this?
count = 0
for (i in 1:1000) {
count = ifelse(i %in% 1:100, count + 1, count)
}
count
#> [1] 100
If your goal is just to monitor progression coarsely, and you're using Rstudio, a simple solution is to just refresh the environment tab to check the current value of i.

Get out of infinite while loop

What is the best way to have a while loop recognize when it is stuck in an infinite loop in R?
Here's my situation:
diff_val = Inf
last_val = 0
while(diff_val > 0.1){
### calculate val from data subset that is greater than the previous iteration's val
val = foo(subset(data, col1 > last_val))
diff_val = abs(val - last_val) ### how much did this change val?
last_val = val ### set last_val for the next iteration
}
The goal is to have val get progressively closer and closer to a stable value, and when val is within 0.1 of the val from the last iteration, then it is deemed sufficiently stable and is released from the while loop. My problem is that with some data sets, val gets stuck alternating back and forth between two values. For example, iterating back and forth between 27.0 and 27.7. Thus, it never stabilizes. How can I break the while loop if this occurs?
I know of break but do not know how to tell the loop when to use it. I imagine holding onto the value from two iterations before would work, but I do not know of a way to keep values two iterations ago...
while(diff_val > 0.1){
val = foo(subset(data, col1 > last_val))
diff_val = abs(val - last_val)
last_val = val
if(val == val_2_iterations_ago) break
}
How can I create val_2_iterations_ago?
Apologies for the non-reproducible code. The real foo() and data that are needed to replicate the situation are not mine to share... they aren't key to figuring out this issue with control flow, though.
I don't know if just keeping track of the previous two iterations will actually suffice, but it isn't too much trouble to add logic for this.
The logic is that at each iteration, the second to last value becomes the last value, the last value becomes the current value, and the current value is derived from foo(). Consider this code:
while (diff_val > 0.1) {
val <- foo(subset(data, col1 > last_val))
if (val == val_2_iterations_ago) break
diff_val = abs(val - last_val)
val_2_iterations_ago <- last_val
last_val <- val
}
Another approach, perhaps a little more general, would be to track your iterations and set a maximum.
Pairing this with Tim's nice answer:
iter = 0
max_iter = 1e6
while (diff_val > 0.1 & iter < max_iter) {
val <- foo(subset(data, col1 > last_val))
if (val == val_2_iterations_ago) break
diff_val = abs(val - last_val)
val_2_iterations_ago <- last_val
last_val <- val
iter = iter + 1
}
How this is generally done is that you have:
A convergence tolerance, so that when your objective function doesn't change appreciably, the algorithm is deemed to have converged
A limit on the number of iterations, so that the code is guaranteed to terminate eventually
A check that the objective function is actually decreasing, to catch the situation where it's diverging/cyclic (many optimisation algorithms are designed so this shouldn't happen, but in your case it does happen)
Pseudocode:
oldVal <- Inf
for(i in 1:NITERS)
{
val <- objective(x)
diffVal <- val - oldVal
converged <- (diffVal <= 0 && abs(diffVal) < TOL)
if(converged || diffVal > 0)
break
oldVal <- val
}

R and apply info

I could find any answers to that. So I've got the following code and trying to put it into apply, so it does the work quicker, my data set is 130k rows long. I need an apply that will calculate the missing times of the horses from Behind(in Length) and the winning Horse time. The problem is that the column Behind gives a the distance behind the horse before, not the first 1. So I'm in need to create a variable that will carry on as the function goes and if new race is identified, finds that the position == 1, it resets the variables.
missingTimes <- function(x) {
L <- 2.4384
for(i in 1:nrow(x) - 10) {
distanceL <- (x$distance[i] * 1000) / L
LperS <- x$Winner.Race.time[i] / distanceL
if(x$position[i] == 1 && !is.na(x$position[i])) {
distanceL <- NULL
LperS <- NULL
}
if(grepl("L",x$Behind[i])) {
x$results[i] <- (distanceL + as.numeric(sub("L", "", x$Behind[i]))) * LperS
}
}
}
I need at least 10 reputation to post images, thats why I give you links instead!
http://i.stack.imgur.com/xN23M.png
http://i.stack.imgur.com/Cspfr.png
The results should just give me a column with the proper times for the finish times of the other horses, in a form like the column Winner Race Time
For further understanding Imma count a few results myself for you:
Starting with first row, it sees position = 1, so it cleans the variables.
Then it takes the distance * 1000, and divides it by the constant L,
2.375 * 1000 / 2.4384 = 973.99
Then It need to get the time in seconds it takes to complete 1 length(L),
290.9 / 973.99 = 0.298
Now to get the finish time for the second horse It adds the length BEHIND to the distance of the racing track and multiplies it by the length per second,
973.99 + 2.25 = 976.24 * 0.298 = 290.91952
Then for the next horses time it'd be:
976.24 + 13 = 989.24 * 0.298 = 294.79352
and so on, remember when it hits position = 1, distance needs to reset
What I've done alternatively is put the distanceL in a separate column, same with LperS, of course after calculation.
If you could walk me through steps required to get that done It'd be great. I'm a complete rookie to the R stuff, so please be descriptive. I hope you catch my understanding!
Thank you!

R while loop and number of times

got a while loop going, and that's working fine.
However I also need to add another condition.
I need the loop to keep going until it satisfies the while loop, but then I also need to add that this can only get repeated x times.
I think you would have to make a for loop to do x times, is it possible to put a while loop in this?
Basically how can I make a loop either reach the goal or stop after x loops??
The expression in while needs to be TRUE for the loop to continue. You can use | or & to add extra conditions. This loop runs 99 times or until sum of random variables is less than 100.
counter <- 0
result <- 0
while(counter < 100 | sum(result) < 100) {
result <- sum(result, rnorm(1, mean = 5, sd = 1))
counter <- sum(counter, 1)
}
> result
[1] 101.5264
> counter
[1] 21
Just pass the current iterator value as an argument to your function. That way you can break the recursion if that reaches a particular value.
But why do you have a while loop if you use recursion, for example:
add_one_recursive = function(number) {
number = number + 1
cat("New number = ", number, "\n")
if(number > 10) {
return(number)
} else {
return(add_one_recursive(number))
}
}
final_number = add_one_recursive(0)
New number = 1
New number = 2
New number = 3
New number = 4
New number = 5
New number = 6
New number = 7
New number = 8
New number = 9
New number = 10
New number = 11
Does not require an explicit loop at all.

Resources