Extend a dataframe based on the last known value

Viewed 83

Is it possible to extend a database based on the last value?

For example:

 x <- c(1, 2, 3, 4, 5)
 y <- c(0.4, 0.6, 0.2, 0.2, 0.1)
 df <- cbind(x, y)

I would like to be able to extend x to 10 and just use the last y value (0.1) to be populated all the way (i.e. in all the missing fields x = 6, 7, 8, 9, 10). Is it possible?

5 Answers

Here is a base R idea,

rbind(df, setNames(data.frame(x = seq(6, 10), y = df$y[nrow(df)]), names(df)))

#    x   y
#1   1 0.4
#2   2 0.6
#3   3 0.2
#4   4 0.2
#5   5 0.1
#6   6 0.1
#7   7 0.1
#8   8 0.1
#9   9 0.1
#10 10 0.1

You can use complete and fill from tidyr :

library(tidyr)
df %>% complete(x = 1:10) %>% fill(y)

# A tibble: 10 x 2
#       x     y
#   <dbl> <dbl>
# 1     1   0.4
# 2     2   0.6
# 3     3   0.2
# 4     4   0.2
# 5     5   0.1
# 6     6   0.1
# 7     7   0.1
# 8     8   0.1
# 9     9   0.1
#10    10   0.1

Make data as dataframe :

df <- data.frame(x, y)

Not as elegant as the other answer, but you can use zoo::na.locf (last observation carried forward) for similar problems:

library(zoo)
x <- 1:5
y <- c(0.4, 0.6, 0.2, 0.2, 0.1)
df <- data.frame(
  x = 1:10,
  y = NA_real_
)
df[1:length(x), ]$y <- y
df$y <- na.locf(df$y)

Continuing with @RonakShah's answer, you can also use the fill argument in complete() to replace missing values.

library(tidyr)

df %>% complete(x = 1:10, fill = list(y = y[nrow(.)]))

# # A tibble: 10 x 2
#        x     y
#    <dbl> <dbl>
#  1     1   0.4
#  2     2   0.6
#  3     3   0.2
#  4     4   0.2
#  5     5   0.1
#  6     6   0.1
#  7     7   0.1
#  8     8   0.1
#  9     9   0.1
# 10    10   0.1

or

df %>% complete(x = 1:10, fill = list(y = dplyr::last(y)))

A base R option using approx

data.frame(with(df, approx(x, y, xout = 1:10, rule = 2)))

such that

> data.frame(with(df, approx(x, y, xout = 1:10, rule = 2)))
    x   y
1   1 0.4
2   2 0.6
3   3 0.2
4   4 0.2
5   5 0.1
6   6 0.1
7   7 0.1
8   8 0.1
9   9 0.1
10 10 0.1
Related