我有一个数据表,例如:
CurrOdo Lat NextLat PrevODO NextOdo
2.62 30.01115868 30.01115868
5.19 30.01116407 30.01116407
7.61 30.01116919 30.01116919
18.82 30.01119282 7.61 19.06
19.06 30.01119282 30.01119282
19.35 30.01119339 30.01119339
20.54 30.01122998 19.35 81.5
20.81 30.01122998 20.54 81.5
37.38 30.01122998 20.81 81.5
81.5 30.01132238 30.01132238
atable<-data.table(odo = c(2.62,5.19,7.61,18.82,19.06,19.35,20.54,20.81, 37.38,81.5 ),
Lat = c(30.01115868,30.01116407,30.01116919,NA,30.01119282,30.01119339,NA,NA, NA, 30.01132238),
NextLat=c(30.01115868,30.01116407,30.01116919, 30.01119282, 30.01119282,30.01119339,
30.01122998,30.01122998,30.01122998,30.01122998 ),
PrevLat=c(NA,NA,NA, NA, NA,NA, NA,NA,NA,NA ),
PrevODO=c(NA,NA,NA, 7.61, NA,NA, 19.35,20.54,20.81,NA ),
NextOdo=c(NA,NA,NA, 19.06, NA,NA, 81.5,81.5,81.5,NA ))
Run Code Online (Sandbox Code Playgroud)
Lat值是基于以下公式的滚动计算:
纬度:(NextLat- PrevLat)*((CurrODO-PrevODO)/(NextODO-PrevODO))+ PrevLat
如何计算纬度的示例
Row CurrODO 18.82: (30.01119282- 30.01116919) * (( 18.82 - 7.61) / (19.06 - 7.61)) + 30.01116919
Row CurrODO 20.54: (30.01122998- 30.01119339) * (( 20.54 - 19.35) / (81.5 - 19.35)) + 30.01119339
Row CurrODO 20.81: (30.01122998- Lat calc result from 20.54 row) * ((20.81 - 20.54) / (81.5 - 20.54)) + Lat calc result from 20.54 row
Row CurrODO 37.38: (30.01122998- Lat calc result from 20.81 row) * (( 37.38 - 20.81) / (81.5 - 20.81)) + Lat calc result from 20.81 row
Run Code Online (Sandbox Code Playgroud)
最终结果将是:
CurrOdo Lat NextLat PrevODO NextOdo
2.62 30.01115868 30.01115868
5.19 30.01116407 30.01116407
7.61 30.01116919 30.01116919
18.82 30.0111923247 30.01119282 7.61 19.06
19.06 30.01119282 30.01119282
19.35 30.01119339 30.01119339
20.54 30.0111940906 30.01122998 19.35 81.5
20.81 30.0111942496 30.01122998 20.54 81.5
37.38 30.0112040049 30.01122998 20.81 81.5
81.5 30.01132238 30.01132238
Run Code Online (Sandbox Code Playgroud)
我目前正在SQL Server中以循环方式运行此程序,但是这需要很长时间。我也可以将其与R放置在循环中,但是对于大型数据集,它的效果将不佳。我已经坚持了好几天,所以对您的帮助表示感谢!
我的回答涉及一个重复循环,尽管您说“ no loops”,但我没有看到其他任何方式(当然可能是R ;-)。
循环应该执行得非常快,但是在我的系统上,大约需要一秒钟的时间来填充1000万行中的NA(请参阅基准)。
Lat的输出与问题中所需的输出匹配。
旁注:
如果您的第一个Lat有价值,那么您可能会遇到问题NA。
由于PrevLat第一行的NA始终为NA,因此不会重新计算Lat的first-NA,循环也不会中断。
您(当然)可以在防止这种情况的循环中构建转义路径/中断。我将其保留,以使示例易于理解且简短。
repeat{
#until there are no more NA in Lat
if( sum( is.na( atable$Lat ) ) == 0 ){
break
}
#(re)calculate PrevLat
atable[, PrevLat := shift( Lat, 1, type = "lag" ) ]
#calculate Lat when PrevLat is known, but Lat is not
atable[ is.na( Lat ) & !is.na( PrevLat ),
Lat := (NextLat-PrevLat)*((odo-PrevODO)/(NextOdo-PrevODO))+PrevLat ]
}
# odo Lat NextLat PrevLat PrevODO NextOdo
# 1: 2.62 30.0111586800 30.01115868 NA NA NA
# 2: 5.19 30.0111640700 30.01116407 30.0111586800 NA NA
# 3: 7.61 30.0111691900 30.01116919 30.0111640700 NA NA
# 4: 18.82 30.0111923247 30.01119282 30.0111691900 7.61 19.06
# 5: 19.06 30.0111928200 30.01119282 30.0111923247 NA NA
# 6: 19.35 30.0111933900 30.01119339 30.0111928200 NA NA
# 7: 20.54 30.0111940906 30.01122998 30.0111933900 19.35 81.50
# 8: 20.81 30.0111942496 30.01122998 30.0111940906 20.54 81.50
# 9: 37.38 30.0112040049 30.01122998 30.0111942496 20.81 81.50
# 10: 81.50 30.0113223800 30.01122998 NA NA NA
Run Code Online (Sandbox Code Playgroud)
基准测试
在1000万行的数据表上(atable重复1M次);
在我的系统(具有16Gb内存的+/- 6岁的i5)上,循环大约需要一秒钟来计算每个Lat的值。
dt <- atable[rep(atable[, .I], 1000000)]
system.time(
repeat{
#until there are no more NA in Lat
if( sum( is.na( dt$Lat ) ) == 0 ){
break
}
#(re)calculate PrevLat
dt[, PrevLat := shift( Lat, 1, type = "lag" ) ]
#calculate Lat when PrevLat is known
dt[ is.na( Lat ) & !is.na( PrevLat ),
Lat := (NextLat- PrevLat ) * ((odo - PrevODO) / (NextOdo - PrevODO)) + PrevLat ]
}
)
# user system elapsed
# 0.90 0.35 1.08
Run Code Online (Sandbox Code Playgroud)
会话信息
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18362)
other attached packages: [1] data.table_1.12.4
Run Code Online (Sandbox Code Playgroud)
更新::代码说明
代码的作用是:
Prevlat的Lat-value 填充列Lat是NA, 并且其中PrevLat具有值(即不是 NA)Lat,请根据您提供的函数计算的值重复步骤1到3,直到检查的总和is.na(atable$Lat)等于0。满足此条件时,该列中不再有NA值Lat。因此,我们可以repeat使用退出-loop break。
| 归档时间: |
|
| 查看次数: |
206 次 |
| 最近记录: |