问题
Sample data
dfData <- data.frame(ID = c(1, 2, 3, 4, 5),
DistA = c(10, 8, 15, 22, 15),
DistB = c(15, 35, 40, 33, 20),
DistC = c(20,40,50,45,30),
DistD = c(60,55,55,48,50))
ID DistA DistB DistC DistD
1 1 10 15 20 60
2 2 8 35 40 55
3 3 15 40 50 55
4 4 22 33 45 48
5 5 15 20 30 50
I have some IDs for which there are four columns which measure cumulative distance. I want to create new column that gives the actual distance for each column i.e. subtract the next column from previous column. For e.g. the table should look like this:
ID DistA DistB DistC DistD
1 1 10 5 5 40
2 2 8 27 5 15
3 3 15 25 10 5
4 4 22 11 12 3
5 5 15 5 10 20
The longer way to do this is
dfData$disA <- dfData$DistA
dfData$disB <- dfData$DistB - dfData$DistA
dfData$disC <- dfData$DistC - dfData$DistB
dfData$disD <- dfData$DistD - dfData$DistC
Is there a shorter way to do this something like:
apply(dfData,1,function(x) ???)
回答1:
Yes, you want diff
...
dfData[,-c(1:2)] <- t(apply(dfData[,-1], 1, diff))
dfData
ID DistA DistB DistC DistD
1 1 10 5 5 40
2 2 8 27 5 15
3 3 15 25 10 5
4 4 22 11 12 3
5 5 15 5 10 20
回答2:
We can use vectorized option
dfData[3:5] <- dfData[-(1:2)] - dfData[-c(1, 5)]
dfData
# ID DistA DistB DistC DistD
#1 1 10 5 5 40
#2 2 8 27 5 15
#3 3 15 25 10 5
#4 4 22 11 12 3
#5 5 15 5 10 20
If the updated values are used for sequential calculation, then a for
loop will be useful
nm1 <- names(dfData)[-1]
for(i in 1:3) dfData[[nm1[i+1]]] <- dfData[[nm1[i+1]]] - dfData[[nm1[i]]]
回答3:
A simple way could be as:
dfData[3:5] = dfData[3:5] - dfData[(3:5) - 1]
# ID DistA DistB DistC DistD
# 1 1 10 5 5 40
# 2 2 8 27 5 15
# 3 3 15 25 10 5
# 4 4 22 11 12 3
# 5 5 15 5 10 20
Quite similar to one option provided by @akrun.
来源:https://stackoverflow.com/questions/49552469/subtract-one-column-from-previous-column