Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
123 views
in Technique[技术] by (71.8m points)

How to apply different functions to different rows of same column in a data frame in R?

Background

I am trying to predict the speed of a vehicle following another vehicle using the equations below:

enter image description here

Please note that the Un(t) in the denominator of second equation is a typo. It is actually delta t.

where,

Un(t) = speed of following vehicle at time t,
CC8 = 1.765, CC9 = 1.04,
delta t = time step = 1 second,
sn(t) = front bumper to front bumper distance between the two vehicles,
CC0 = 4.4, L_n-1 = Length of lead vehicle,

Please ignore the uf and note that 3.6 is just used to ensure that the units of speed are km/hr. Also, since the vehicle positions change over time due to speed, it is important to estimate those as well.

Calculations in Excel

I can successfully apply these equations in Excel as follows:

enter image description here

Note that:
Local.Y = Observed longitudinal position of following vehicle from a fixed reference point (m),
pred_Local.Y = Predicted longitudinal position of following vehicle,
PrecVehLocalY = Observed longitudinal position of lead vehicle,
Un = Observed speed of following vehicle (m/s),
Un_dt_1 = predicted speed of following vehicle using the first equation in the 1st image,
Un_dt_2 = predicted speed of following vehicle using the 2nd equation,
Un_dt = minimum of Un_dt_1 and Un_dt_2 Ln = actual length of lead vehicle = L_n-1 in the equation,
sn_minus_Ln = observed distance between front bumper of following vehicle and rear bumper of lead vehicle; sn is the front-to front distance,
pred_sn_minus_Ln = predicted front-to-rear distance;

You can see that the first row of predicted variables use the observed variables from one time step before. But after that the consecutive rows use the predicted variables only. I have no idea how can I do the same in R? Please help. I want to use dplyr.

Example data for R

structure(list(Local.Y = c(50.71994, 60.37412, 69.99005, 78.60745
), Un = c(9.48762, 9.93521, 8.9674, 8.33772), PrecVehLocalY = c(70.19624, 
78.50749, 86.49717, 93.4731), Ln = c(3.9019, 3.9019, 3.9019, 
3.9019), sn_minus_Ln = c(15.5744, 14.23147, 12.60522, 10.96375
)), row.names = c(NA, 4L), class = "data.frame", .Names = c("Local.Y", 
"Un", "PrecVehLocalY", "Ln", "sn_minus_Ln"))

What I have tried

Please don't close this question. I have tried using following code but it only works for the first row:

df %>% 
mutate(Un_dt_1 = lag(Un)*3.6 + 3.6*(1.765+(1.765-1.04)*lag(Un)*3.6/80))

'ifelse' could be an option but I am not sure what conditions should I provide for TRUE and FALSE.

Desired Output

structure(list(Local.Y = c(50.71994, 60.37412, 69.99005, 78.60745
), Un = c(9.48762, 9.93521, 8.9674, 8.33772), PrecVehLocalY = c(70.19624, 
78.50749, 86.49717, 93.4731), Ln = c(3.9019, 3.9019, 3.9019, 
3.9019), sn_minus_Ln = c(15.5744, 14.23147, 12.60522, 10.96375
), pred_Local.Y = c(NA, 57.624865, 69.5024275, 80.13921125), 
    pred_sn_minus_Ln = c(NA, 16.980725, 13.0928425, 9.43198875
    ), Un_dt_1 = c(NA, 41.62375297, 47.89427328, 53.12221615), 
    Un_dt_2 = c(NA, 40.22784, 45.29061, 31.294233), Un_dt = c(NA, 
    40.22784, 45.29061, 31.294233)), .Names = c("Local.Y", "Un", 
"PrecVehLocalY", "Ln", "sn_minus_Ln", "pred_Local.Y", "pred_sn_minus_Ln", 
"Un_dt_1", "Un_dt_2", "Un_dt"), row.names = c(NA, 4L), class = "data.frame")
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

( Adding a separate answer because I'm starting from scratch )

I'm glad I understand your question better now, it is certainly more complex a solution than I first thought.

Here's a completely different way to go about it, given that your calculations need to happen in sequence. Because there's such a sequence involved (ie: it's important for every calculation that the ones before it have been completed first), I think the best way is with a for loop. This also allows for specifying different calculations for Un_dt_1, Un_dt_2, and pred_Local.Y on the first run compared with subsequent runs:

for( i in ( seq_len( nrow(df)-1 ) + 1 ) ) {
    if( i <= 2L ) {
        df$Un_dt_1[i] <- df$Un[i-1] * 3.6 + 
            3.6 * ( 1.765 + ( 1.765 - 1.04 ) * 
                        df$Un[1] * 3.6 / 80 ) * 1
        df$Un_dt_2[i] <- 3.6 * ( df$sn_minus_Ln[i-1] - 4.4 ) / 1
    } else {
        df$Un_dt_1[i] <- df$Un_dt[i-1] + 
            3.6 * ( 1.765 + ( 1.765 - 1.04 ) * 
                        df$Un_dt[i-1] / 80 ) * 1
        df$Un_dt_2[i] <- 3.6 * ( df$pred_sn_minus_Ln[i-1] - 4.4 ) / 1
    }
    df$Un_dt[i] <- pmin( df$Un_dt_1[i], df$Un_dt_2[i] )
    if( i <= 2 ) {
        df$pred_Local.Y[i] <- df$Local.Y[i-1] + 
            0.5 * ( ( df$Un_dt[i] + df$Un[i-1] ) / 3.6 ) * 1
    } else {
        df$pred_Local.Y[i] <- df$pred_Local.Y[i-1] + 
            0.5 * ( ( df$Un_dt[i] + df$Un_dt[i-1] ) / 3.6 ) * 1
    }

    df$pred_sn_minus_Ln[i] <- df$PrecVehLocalY[i] - df$pred_Local.Y[i] - df$Ln[i]
}

Notice the seq_len call to begin the loop will return all values from 2, ascending to the end of your frame. Then row 2 is treated as a special case, where Un_dt_1, Un_dt_2, and pred_Local.Y are calculated in a different way to subsequent rows.

If you turn this into a function, you can then run it on all groups in your larger dataset. Alternatively, you could nest this in another for loop, subsetting the group as the first step in that larger loop.

While I (and I believe most others) think it's best to stay away from for loops when possible, they're not altogether evil. They do have their place, and I believe your problem here is one case where a for loop is a reasonable solution.

EDIT: OK, it seems to give the right output now. I hadn't noticed a few differences between rows. Let me know how this works for you.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...