HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Imperative code in R keeping track of state

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
keepingtrackimperativestatecode

Problem

A friend of mine has a spreadsheet where she coded a classroom video for various teaching events, which I needed to help her plot. For each recording, she used several video cassettes, and her time codes were relative to each video cassette (ie. they always start on 0). To be able to plot these on a timeline, I needed to convert the times into a relative (continuous) time. The code below works perfectly (and I've solved the problem), however it doesn't look good to me. It looks like the code I used to write in Ruby, before I began playing with R, Haskell etc.

This is not the first time I've come across this kind of a problem - iterating through rows, or lines of text, needing to keep track of several different kinds of "state", etc. I would be curious if this code could be rewritten to look cleaner, more idiomatic.

Example dataset

structure(list(code = structure(c(4L, 3L, 1L, 1L, 5L, 4L, 3L,
1L, 5L, 2L), .Label = c("CC-NoZZ", "CC-ZZ", "FBP", "KK-NoZZ",
"KK-ZZ"), class = "factor"), src = structure(c(1L, 1L, 1L, 2L,
2L, 3L, 3L, 4L, 4L, 4L), .Label = c("alfred1.mov", "alfred2.mov",
"claire1.mov", "claire2.mov"), class = "factor"), class = structure(c(1L,
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L), .Label = c("alfred's class",
"claire's class"), class = "factor"), start = c(0L, 2L, 6L, 0L,
10L, 1L, 5L, 0L, 6L, 14L), end = c(2L, 4L, 8L, 4L, 12L, 3L, 9L,
4L, 10L, 20L)), .Names = c("code", "src", "class", "start", "end"
), class = "data.frame", row.names = c(NA, -10L))


Example code

src = ""
class = ""
delta = 0
db$corr.start = NA
db$corr.end = NA
db$delta = NA

for(i in 1:nrow(db)) {
row

Example output

code src class start end corr.start corr.end delta
1 KK-NoZZ alfred1.mov alfred's class 0 2 0 2 0
2 FBP alfred1.mov alfred's class 2 4 2 4 0
3 CC-NoZZ alfred1.mov alfred's class 6 8 6 8 0
4 CC-NoZZ alfred2.mov alfred's class 0 4 8

Solution

R encourages vector-based operations instead of loops. But in this case, I don't think there's a good way around tracking the state of delta.

This might be a slightly better way to create a vector delta:

delta <- 0
vdelta <- c(0)
for (i in 2:nrow(db)) {
  row <- db[i,]
  prev <- db[i-1,]
  if (row$class != prev$class) {
    delta <- 0
  } else if (row$src != prev$src) {
    delta <- prev$end + delta
  }
  vdelta <- c(vdelta, delta)
}


Based on vdelta you can easily create the columns you need:

db$corr.start <- db$start + vdelta
db$corr.end <- db$end + vdelta
db$delta <- vdelta

Code Snippets

delta <- 0
vdelta <- c(0)
for (i in 2:nrow(db)) {
  row <- db[i,]
  prev <- db[i-1,]
  if (row$class != prev$class) {
    delta <- 0
  } else if (row$src != prev$src) {
    delta <- prev$end + delta
  }
  vdelta <- c(vdelta, delta)
}
db$corr.start <- db$start + vdelta
db$corr.end <- db$end + vdelta
db$delta <- vdelta

Context

StackExchange Code Review Q#51910, answer score: 2

Revisions (0)

No revisions yet.