Hi. I have some code which loops through raw GPS data. This initial loop calculates distance, angle, speed etc between successive coordinates as well as type of movement e.g.left, right, forward. I want to construct a second loop that goes through the movements and records 'Changes' as either '0' or '1' depending on whether the movement changed or not. I have put the whole code in for reference but the additional loop begins at the object 'holder.' I want to store movements in holder and then loop through holder to determine 'changes.' At the moment it gives me 'Error in holder[[t - 1]] : attempt to select less than one element.' The moment i make holder [[t]] it works but just gives a list of '0's. I have tried many different things and just cannot get it to work, so any help would be very much appreciated. Again, sorry for the long post. lst <- list() # temporary list to store the results for (i in seq(1, nrow(R) - 1)){ # loop through each row of the 'R' matrix lat1 <- deg2rad(R[i, 4]) long1 <- deg2rad(R[i, 5]) lat2 <- deg2rad(R[i + 1, 4]) long2 <- deg2rad(R[i + 1, 5]) gcd_vif <- gcd.vif(lat1, long1, lat2, long2) # calc estimated speed by mean of speeds between two GPS records estSpeed <- (R[i, 6] + R[i+1, 6])/2 # calculate acceleration (velocity) accel <- (R[i+1, 6] - R[i, 6]) / GPSSample # calculate absolute heading heading <- absoluteHeading(lat1, long1, lat2, long2) # calculate bearing relative to previous GPS record relAngle <- 0 # if the number of GPS records is less than 3 then no change in track if (i < 1) relAngle = heading # otherwise consider the previous heading in order to calculate the new track else if (i > 0) { relAngle = (previousHeading - heading) } # determine whether movement is occurring and if so what type # if there are insufficient history items then just record movement types discretely if (i < historyLength) movement <- movementType(relAngle, angleThreshold) else if (i > historyLength-1) { # Array to store speeds speedHistory <- array(historyLength) n = historyLength-1 # get the speeds from the previous n (hisoryLength) "Movements" for (j in seq(1, length(historyLength))){ speedHistory [n] = R[i-j, 6] n-1 } if (!bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- "non-moving" else if(bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- movementType(relAngle, angleThreshold) } holder <- list(movement) holder [[i]] <- (movement) for (t in length(holder)){ if (holder[[t]] == holder[[t-1]]) changes <- 0 else changes <- 1 } # update previous heading information previousHeading = heading # Store the input data and the results lst[[i]] <- c( latitude_position_1 = lat1, longtude_position_1 = long1, latitude_position_2 = lat2, longtude_position_2 = long2, Distance = gcd_vif, Speed = estSpeed, Acceleration = accel, Absolute_Heading = heading, Relative_Heading = relAngle, Movement = movement, Changes = changes ) } Results <- as.data.frame(do.call(rbind, lst)) # store the input data and the results in a data frame Results -- View this message in context: http://r.789695.n4.nabble.com/for-loop-not-working-tp4713392.html Sent from the R help mailing list archive at Nabble.com.
Hi mnw, It looks to me as though you are testing the entire "holder" list each time you go through the function. First, I'm not sure that a simple "==" is the test you want. "movement" seems to be more than a single value and so you might want to write a function that tests whether all of the components of two "movement" objects are equal e.g.: move_change<-function(currentx,previousx) { if(currentx$speed == previousx$speed) { if(currentx$heading == previousx$heading) return(0) } return(1) } Second, you probably don't want to test the entire list each time you loop through the function. Just use: if(i > 1) changes<-move_change(movement,holder) holder<-movement Jim On Sat, Oct 10, 2015 at 2:08 AM, mnw <maw90 at aber.ac.uk> wrote:> Hi. I have some code which loops through raw GPS data. This initial loop > calculates distance, angle, speed etc between successive coordinates as > well > as type of movement e.g.left, right, forward. I want to construct a second > loop that goes through the movements and records 'Changes' as either '0' or > '1' depending on whether the movement changed or not. I have put the whole > code in for reference but the additional loop begins at the object > 'holder.' > I want to store movements in holder and then loop through holder to > determine 'changes.' At the moment it gives me 'Error in holder[[t - 1]] : > attempt to select less than one element.' The moment i make holder [[t]] it > works but just gives a list of '0's. I have tried many different things and > just cannot get it to work, so any help would be very much appreciated. > Again, sorry for the long post. > > > > > lst <- list() # temporary list to store the results > for (i in seq(1, nrow(R) - 1)){ # loop through each row of the 'R' matrix > lat1 <- deg2rad(R[i, 4]) > long1 <- deg2rad(R[i, 5]) > lat2 <- deg2rad(R[i + 1, 4]) > long2 <- deg2rad(R[i + 1, 5]) > gcd_vif <- gcd.vif(lat1, long1, lat2, long2) > > # calc estimated speed by mean of speeds between two GPS records > estSpeed <- (R[i, 6] + R[i+1, 6])/2 > > # calculate acceleration (velocity) > accel <- (R[i+1, 6] - R[i, 6]) / GPSSample > > # calculate absolute heading > heading <- absoluteHeading(lat1, long1, lat2, long2) > > # calculate bearing relative to previous GPS record > relAngle <- 0 > # if the number of GPS records is less than 3 then no change in track > if (i < 1) relAngle = heading > # otherwise consider the previous heading in order to calculate the new > track > else if (i > 0) { > relAngle = (previousHeading - heading) > > } > > > # determine whether movement is occurring and if so what type > # if there are insufficient history items then just record movement types > discretely > if (i < historyLength) movement <- movementType(relAngle, > angleThreshold) > > else if (i > historyLength-1) { > # Array to store speeds > speedHistory <- array(historyLength) > n = historyLength-1 > # get the speeds from the previous n (hisoryLength) "Movements" > for (j in seq(1, length(historyLength))){ > speedHistory [n] = R[i-j, 6] > n-1 > } > > if (!bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- > "non-moving" > else if(bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- > movementType(relAngle, angleThreshold) > > > } > > > holder <- list(movement) > holder [[i]] <- (movement) > > > for (t in length(holder)){ > if (holder[[t]] == holder[[t-1]]) > changes <- 0 > else changes <- 1 > > } > > > > # update previous heading information > previousHeading = heading > > > > > > > # Store the input data and the results > lst[[i]] <- c( > latitude_position_1 = lat1, > longtude_position_1 = long1, > latitude_position_2 = lat2, > longtude_position_2 = long2, > Distance = gcd_vif, > Speed = estSpeed, > Acceleration = accel, > Absolute_Heading = heading, > Relative_Heading = relAngle, > Movement = movement, > Changes = changes > > ) > > } > Results <- as.data.frame(do.call(rbind, lst)) # store the input data and > the > results in a data frame > Results > > > > -- > View this message in context: > http://r.789695.n4.nabble.com/for-loop-not-working-tp4713392.html > Sent from the R help mailing list archive at Nabble.com. > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]]
In addition to Jim's comments you would benefit by learning more about how R works. You are using loops for operations that could easily be vectorized. It is not clear where your functions are coming from (eg. deg2rad and gcd.vif) but package geosphere will get your distances and bearings directly without looping.> install.packages("geosphere") > library(geosphere) > Cities <- c("New York", "Miami", "Los Angeles", "Seattle", "Chicago") > Lat <- c(40.7127, 25.7753, 34.05, 47.6097, 41.8369) > Long <- c(-74.0059, -80.2089, -118.250, -122.3331, -87.6847) > Places <- data.frame(Cities, Lat, Long) > PlacesCities Lat Long 1 New York 40.7127 -74.0059 2 Miami 25.7753 -80.2089 3 Los Angeles 34.0500 -118.2500 4 Seattle 47.6097 -122.3331 5 Chicago 41.8369 -87.6847> n <- nrow(Places) > distVincentyEllipsoid(Places[1:(n-1), 3:2], Places[2:n, 3:2])[1] 1753420 3763369 1544119 2794013> bearing(Places[1:(n-1), 3:2], Places[2:n, 3:2])[1] -158.98140 -66.71221 -11.57217 90.36231 David L. Carlson Department of Anthropology Texas A&M University -----Original Message----- From: R-help [mailto:r-help-bounces at r-project.org] On Behalf Of Jim Lemon Sent: Saturday, October 10, 2015 6:04 AM To: mnw <maw90 at aber.ac.uk> Cc: r-help mailing list <r-help at r-project.org> Subject: Re: [R] for loop not working Hi mnw, It looks to me as though you are testing the entire "holder" list each time you go through the function. First, I'm not sure that a simple "==" is the test you want. "movement" seems to be more than a single value and so you might want to write a function that tests whether all of the components of two "movement" objects are equal e.g.: move_change<-function(currentx,previousx) { if(currentx$speed == previousx$speed) { if(currentx$heading == previousx$heading) return(0) } return(1) } Second, you probably don't want to test the entire list each time you loop through the function. Just use: if(i > 1) changes<-move_change(movement,holder) holder<-movement Jim On Sat, Oct 10, 2015 at 2:08 AM, mnw <maw90 at aber.ac.uk> wrote:> Hi. I have some code which loops through raw GPS data. This initial loop > calculates distance, angle, speed etc between successive coordinates as > well > as type of movement e.g.left, right, forward. I want to construct a second > loop that goes through the movements and records 'Changes' as either '0' or > '1' depending on whether the movement changed or not. I have put the whole > code in for reference but the additional loop begins at the object > 'holder.' > I want to store movements in holder and then loop through holder to > determine 'changes.' At the moment it gives me 'Error in holder[[t - 1]] : > attempt to select less than one element.' The moment i make holder [[t]] it > works but just gives a list of '0's. I have tried many different things and > just cannot get it to work, so any help would be very much appreciated. > Again, sorry for the long post. > > > > > lst <- list() # temporary list to store the results > for (i in seq(1, nrow(R) - 1)){ # loop through each row of the 'R' matrix > lat1 <- deg2rad(R[i, 4]) > long1 <- deg2rad(R[i, 5]) > lat2 <- deg2rad(R[i + 1, 4]) > long2 <- deg2rad(R[i + 1, 5]) > gcd_vif <- gcd.vif(lat1, long1, lat2, long2) > > # calc estimated speed by mean of speeds between two GPS records > estSpeed <- (R[i, 6] + R[i+1, 6])/2 > > # calculate acceleration (velocity) > accel <- (R[i+1, 6] - R[i, 6]) / GPSSample > > # calculate absolute heading > heading <- absoluteHeading(lat1, long1, lat2, long2) > > # calculate bearing relative to previous GPS record > relAngle <- 0 > # if the number of GPS records is less than 3 then no change in track > if (i < 1) relAngle = heading > # otherwise consider the previous heading in order to calculate the new > track > else if (i > 0) { > relAngle = (previousHeading - heading) > > } > > > # determine whether movement is occurring and if so what type > # if there are insufficient history items then just record movement types > discretely > if (i < historyLength) movement <- movementType(relAngle, > angleThreshold) > > else if (i > historyLength-1) { > # Array to store speeds > speedHistory <- array(historyLength) > n = historyLength-1 > # get the speeds from the previous n (hisoryLength) "Movements" > for (j in seq(1, length(historyLength))){ > speedHistory [n] = R[i-j, 6] > n-1 > } > > if (!bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- > "non-moving" > else if(bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- > movementType(relAngle, angleThreshold) > > > } > > > holder <- list(movement) > holder [[i]] <- (movement) > > > for (t in length(holder)){ > if (holder[[t]] == holder[[t-1]]) > changes <- 0 > else changes <- 1 > > } > > > > # update previous heading information > previousHeading = heading > > > > > > > # Store the input data and the results > lst[[i]] <- c( > latitude_position_1 = lat1, > longtude_position_1 = long1, > latitude_position_2 = lat2, > longtude_position_2 = long2, > Distance = gcd_vif, > Speed = estSpeed, > Acceleration = accel, > Absolute_Heading = heading, > Relative_Heading = relAngle, > Movement = movement, > Changes = changes > > ) > > } > Results <- as.data.frame(do.call(rbind, lst)) # store the input data and > the > results in a data frame > Results > > > > -- > View this message in context: > http://r.789695.n4.nabble.com/for-loop-not-working-tp4713392.html > Sent from the R help mailing list archive at Nabble.com. > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]] ______________________________________________ R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Thank you for your comments. I guess what I need is to store movements and then loop through that matrix. Here is a snippet of the 'movement' code. I am trying to fill the matrix below with data from this loop. Is there something else my matrix (bottom) requires? Or its positioning? Many thanks, # determine whether movement is occurring and if so what type # if there are insufficient history items then just record movement types discretely if (i < historyLength) movement <- movementType(relAngle, angleThreshold) else if (i > historyLength-1) { # Array to store speeds speedHistory <- array(historyLength) n = historyLength-1 # get the speeds from the previous n (hisoryLength) "Movements" for (j in seq(1, length(historyLength))){ speedHistory [n] = R[i-j, 6] n-1 } if (!bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- "non-moving" else if(bayesFilter(speedHistory, minSpeed, GPS_accy)) movement <- movementType(relAngle, angleThreshold) holder <- matrix(data = movement, nrow = nrow(R), ncol = 1) } -- View this message in context: http://r.789695.n4.nabble.com/for-loop-not-working-tp4713392p4713525.html Sent from the R help mailing list archive at Nabble.com.