如何将不同的函数应用于R中数据框中同一列的不同行?

时间:2016-07-12 16:06:25

标签: r

背景

我正在尝试使用以下公式预测车辆跟随另一辆车的速度:

enter image description here

请注意,第二个等式的分母中的Un(t)是拼写错误。它实际上是delta t。

其中,

Un(t)=在时间t跟随车辆的速度,
CC8 = 1.765,CC9 = 1.04,
delta t =时间步长= 1秒,
sn(t)=前保险杠与两辆车之间的前保险杠距离,
CC0 = 4.4,L_n-1 =主要车辆的长度,

请忽略uf并注意3.6仅用于确保速度单位为km / hr。此外,由于车辆位置由于速度而随时间变化,因此估计这些也很重要。

Excel中的计算

我可以在Excel中成功应用这些方程式,如下所示:

enter image description here

请注意:
Local.Y =从固定参考点(m)观察跟随车辆的纵向位置,
pred_Local.Y =跟随车辆的预测纵向位置,
PrecVehLocalY =观察到引导车辆的纵向位置,
Un =跟随车辆的观察速度(m / s),
Un_dt_1 =使用第一图像中的第一个等式预测跟随车辆的速度,
Un_dt_2 =使用第二个等式预测跟随车辆的速度,
Un_dt = Un_dt_1和Un_dt_2的最小值 Ln =牵引车辆的实际长度=方程式中的L_n-1,
sn_minus_Ln =观察到后车的前保险杠与前车后保险杠之间的距离; sn是从前到前的距离,
pred_sn_minus_Ln =预测的前后距离;

您可以看到第一行预测变量使用之前一步的观察变量。但在此之后,连续行仅使用预测变量。我不知道如何在R中做同样的事情?请帮忙。我想使用dplyr

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"))

我尝试了什么

请不要关闭此问题。我尝试使用以下代码,但它只适用于第一行:

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

'ifelse'可以是一个选项,但我不确定我应该为TRUEFALSE提供什么条件。

期望输出

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")

2 个答案:

答案 0 :(得分:1)

这里有一点我希望能帮助你开始使用data.table包(我个人的选择,当然不是唯一的方法):

library( data.table )
setDT( df )
df[ , Un_dt_1 := shift( Un, n = 1L, type = "lag" ) * 3.6 + 
          3.6 * ( 1.765 + ( 1.765 - 1.04 ) * 
                      shift( Un, n = 1L, type = "lag" ) * 
                      3.6 / 80 ) 
   ]

df[ , Un_dt_2 := 
          3.6 * ( shift( sn_minus_Ln, n = 1L, type = "lag" ) - 4.4 ) / 1 
   ]

请注意使用shift函数,按照n指定的方向({#1}}(&#34)将引用偏移一定数量的行type(默认值为1) ;滞后"查找,"领先"向下看)。这里输入的值实际上是默认值,因此您可以将它们保留,但我希望将它们包含在内以保证完整性。

我认为此处使用的方法适用于您在电子表格中显示的所有列。如果您需要通过分组变量应用内容,则需要以下内容:

df[ , output_column := function(x), by = group ]

function是您要应用的功能,x是该功能的输入列(或列),而group是一个唯一的列组标识符。

编辑回应OP的评论: 没有理由不能在计算中添加更多变量,或者已经计算到新计算中的参考变量。例如,Un_dt依赖于我上面包含计算的两列,因此请在下一步中参考每个列:

df[ , Un_dt := pmin( Un_dt_1, Un_dt_2 ) ]

答案 1 :(得分:1)

(添加单独的答案,因为我从头开始)

我很高兴我现在更好地理解你的问题,这肯定比我最初想的更复杂。

考虑到您的计算需要按顺序进行,这是一种完全不同的方法。因为涉及到这样的序列(即:对于每个计算而言,它首先完成之前的重要),我认为最好的方法是使用for循环。与后续运行相比,这还允许在第一次运行时为Un_dt_1Un_dt_2pred_Local.Y指定不同的计算:

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]
}

请注意,开始循环的seq_len调用将返回2中的所有值,并递增到帧的末尾。然后将第2行视为特殊情况,其中Un_dt_1Un_dt_2pred_Local.Y的计算方式与后续行的计算方式不同。

如果将其转换为function,则可以在较大数据集中的所有组上运行它。或者,您可以将其嵌套在另一个for循环中,将该组子集化为该较大循环中的第一步。

虽然我(我相信其他大多数人)认为最好尽可能远离for循环,但它们并非完全是邪恶的。他们确实有自己的位置,我相信你的问题是一个for循环是一个合理的解决方案。

编辑:好的,它似乎现在提供正确的输出。我没有注意到行之间的一些差异。让我知道这对你有用。