umair durrani
umair durrani

Reputation: 6179

Efficient method to smooth data in R

This question is related to another question which I asked here.

Data

My data frame contains velocities and accelerations of vehicles in every 0.1 seconds time frames. Following shows very few data points of the data frame which originally contains more than 1,000,000 rows:

> dput(head(traj2[, c(1,2,12,13)], 30))
structure(list(Vehicle.ID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L), Frame.ID = 270:299, Vehicle.velocity = c(19.89, 
19.89, 19.89, 19.89, 19.89, 19.97, 20, 19.86, 19.18, 18.17, 17.63, 
17.87, 18.76, 19.67, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 
20, 20, 20, 20, 19.99, 19.98), Vehicle.acceleration = c(0, 0, 
0, 0, 1.07, 0.6, 0, -2.42, -9.79, -11.2, -2.64, 9.2, 11.2, 5.32, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.11, -0.2)), .Names = c("Vehicle.ID", 
"Frame.ID", "Vehicle.velocity", "Vehicle.acceleration"), row.names = c(NA, 
30L), class = "data.frame")

Please note that there are about 2000 unique Vehicle.IDs, each repeating in different number of frames.

Goal

I want to smooth the velocities and accelerations by using the equation provided in the first question. But I want to minimize the time and make the code as efficient as possible.

What I have Tried

I used following code for smoothing:

#  VELOCITY SMOOTHING FUNCTION
smooth <- function (x, D, delta){
z <- exp(-abs(-D:D/delta))
r <- convolve (x, z, type='filter')/convolve(rep(1, length(x)),z,type='filter')
r
}
#  ACCELERATION SMOOTHING FUNCTION
smootha <- function (x, D, delta){
  za <- exp(-abs(-D:D/delta))
  ra <- convolve (x, za, type='filter')/convolve(rep(1, length(x)),za,type='filter')
  ra
} ### D=3*delta = 3*40 = 120, delta for acceleration = T / dt = 4 seconds/0.1 = 40
ftaa <- list()


 # Split data by vehicle ID
    length(ftaa) <- length(unique(traj1$'Vehicle.ID'))

# Apply smoothing function
for (i in 1:length(unique(traj2$'Vehicle.ID'))){
  veh <- subset (traj2, traj2$'Vehicle.ID'==unique(traj2$'Vehicle.ID')[i])
  svel <- round(smooth(veh$'Vehicle.velocity',30,10), digits=2)
  svel <- data.frame(svel)
  svel <- head(tail(svel,-90),-90)
  sacc <- round(smootha(veh$'Vehicle.acceleration',120,40), digits=2)
  sacc <- data.frame(sacc)
  veh <- head(tail(veh, -120), -120)
  ftaa[[i]] <- cbind(veh,svel,sacc)
}

# Combining results
final.data1<-do.call("rbind", ftaa)

The Problem

This approach takes about 40 minutes to complete smoothing the given data frame. Is there any way I could reduce this time?

Upvotes: 0

Views: 1683

Answers (1)

Mike.Gahan
Mike.Gahan

Reputation: 4615

I highly recommend ditching the loop and using data.table. Also, why not use the round function inside of your smooth and smootha functions?

require(data.table)
setDT(traj2)

traj2[ , svel := smooth(Vehicle.velocity,30,10), by =Vehicle.ID]
traj2[ , sacc := smootha(Vehicle.acceleration,120,40), by =Vehicle.ID]

This is difficult to test because your problem is not setup in a reproducible way. Your smoothing functions need identically sized vectors (your link shows using convolve with type="open" instead of how you are using it). But this is a good template for getting your code to run much much faster.

Upvotes: 2

Related Questions