I have a partially filled in table, there are NAs at the top and bottom of the table (column X in the table below). I want to fill in the table using a rate (0.3) to get the results in the Goal column. This is similar to the fill up/down function in Excel used to copy a formula and fill cells.
df <- data.frame(X = matrix(nrow = 10, ncol = 1, NA))
df [3:5,1] <- 2:4
X Goal
1 NA 1.4
2 NA 1.7
3 2 2
4 3 3
5 4 4
6 NA 4.3
7 NA 4.6
8 NA 4.9
9 NA 5.2
10 NA 5.9
Essentially what I want the code to do is this:
1.4 (X2 answer - 0.3)
1.7 (2 - 0.3)
2
3
4
4.3 (4 0.3)
4.6 (X6 answer 0.3)
4.9 (X7 answer 0.3)
5.2 (X8 answer 0.3)
5.5 (X9 answer 0.3)
I know this can probably be done using loops, but I find them intimidating given my skill level, so I'm looking for a solution that avoids them (if that's even possible).
Thanks in advance
CodePudding user response:
Avoiding loops with nafill()
and fcoalesce()
from data.table
.
library(data.table)
loc = range(which(!is.na(df$X)))
df$Goal =
fcoalesce(nafill(df$X, "locf"), nafill(df$X, "nocb"))
c( -((loc[1] - 1):1)*0.3, rep(0, diff(loc) 1), (1:(nrow(df) - loc[2]))*0.3 )
Still, it is (arguably) much easier to keep track of what is happening in each case with a loop:
# Preallocate
df$Goal = 0
for (i in 1:nrow(df)) {
if (i < loc[1]) df$Goal[i] = df$X[loc[1]] - (loc[1] - i) * 0.3
else if (i > loc[2]) df$Goal[i] = df$X[loc[2]] (i - loc[2]) * 0.3
else df$Goal[i] = df$X[i ]
}
# X Goal
# 1 NA 1.4
# 2 NA 1.7
# 3 2 2.0
# 4 3 3.0
# 5 4 4.0
# 6 NA 4.3
# 7 NA 4.6
# 8 NA 4.9
# 9 NA 5.2
# 10 NA 5.5