Reputation: 353
I have a data table with two columns: "id" and "prevId". I want to find all instances where one row has a "prevId" value equivalent to the "id" value of a row that comes after it. I then want to swap the order of those rows in the data table.
So far, I have tried messing around with the logic below:
data[, index:=.I]
data[, priorMatch:=index[1L], by = cumsum(prevId == id)]
apply(records, 1, FUN = function(x) {
if (!is.na(priorMatch)) {
records[x[["index"]],] <- records[x[["index"]] - 1,]
records[x[["index"]] - 1,] <- x
}
})
However, cumsum() does not actually take me the earliest prior row with a "prevId" equivalent to the present row's "id".
An example of desired results:
id prevId
ef cd
cd ab
Would be transformed to:
id prevId
cd ab
ef cd
Any assistance is appreciated. Thanks!
Upvotes: 1
Views: 778
Reputation: 9081
Use -
df <- data.frame(id=c("ef", "cd"), "prevId"=c("cd", "ab"))
rows <- which(as.character(df[,"id"]) == as.character(shift(df[,"prevId"])))
for(i in 1:length(rows)){
index <- rows[i]
swap_index <- index - 1
temp <- df[index, ]
df[index, ] <- df[swap_index, ]
df[swap_index, ] <- temp
}
Output
id prevId
1 cd ab
2 ef cd
Upvotes: 0
Reputation: 27732
This will do the trick (at least for the sample data provided)
dt <- fread("id prevId
ef cd
cd ab")
#get rownumbers
dt[, row := .I]
#create a column with 'new' rownumbers to order on, using shift
dt[ prevId == shift(id, 1, type = "lead") , row := row + 1]
dt[ id == shift(prevId, 1, type = "lag") , row := row - 1]
#reorder
setkey(dt, row)
#drop the row-column
dt[, row := NULL][]
# id prevId
# 1: cd ab
# 2: ef cd
Upvotes: 1