1

I am trying to get my R code to fill in the missing names. I have looked and did not see this question is on here. I have a 502 X 3 data frame. Of which, I am only doing one column at a time. The logic should read, if the the field is not NA, then store the name and move on to the next row. If the field is NA, then fill in that field with the last stored name. Data and code snippet below. I am not certain what I am doing wrong here. Any assistance would be wonderful. Thank you in advance for your time.

The Actual Data set is located: https://pe.usps.com/text/pub28/28apc_002.htm

Basically, I copied the file into an excel document and am trying to find a quick way to fill in the blanks. I have other files that are larger that need to have this done so it would be very beneficial to be able to do it very quickly. Also a good way to learn. :)

In this example, I would like the final list to read: "lodge", "lodge", "loop", "loop", "loop", "mall", "mall", "manor", "manor", "manor", "manor"


    data <- c("lodge", "lodge", "loop", NA, NA,  "mall", NA, "manor", NA, NA, NA)

    i = 1
    data[i]
    name <- data[i]
    len <- length(data)

    for (i in len) {

      name <- data[i]

      if_else(is.na(name), 
              data[i] <- name,
              name <- data[i])


      i <- i + 1
    }

    data
M--
  • 25,431
  • 8
  • 61
  • 93
Sven
  • 301
  • 2
  • 18
  • 2
    Try `na.locf(data)` from `library(zoo)` – akrun Dec 13 '19 at 15:59
  • Duplicate of [Replacing NAs in R with nearest value](https://stackoverflow.com/questions/10077415/replacing-nas-in-r-with-nearest-value) – M-- Dec 13 '19 at 18:23

4 Answers4

2

Using tidyr:fill:

as.character(tidyr::fill(as.data.frame(data), data, .direction="down")$data)

 ## [1] "lodge" "lodge" "loop"  "loop"  "mall"  "manor"
M--
  • 25,431
  • 8
  • 61
  • 93
  • Would this work if there are multiple NA in a row? For example, the add another NA to the OP so it would be ...loop loop loop... – Sven Dec 13 '19 at 17:37
  • @Chris would you edit question and show what you need – M-- Dec 13 '19 at 17:41
  • @M I have expanded the initial data set and results for the more complex case. I am realizing that the initial case was too basic for the actual data set. Thanks – Sven Dec 13 '19 at 17:46
2

We can also do na.locf from zoo

library(zoo)
na.locf(data)
#[1] "lodge" "lodge" "loop"  "loop"  "mall"  "manor"
akrun
  • 874,273
  • 37
  • 540
  • 662
1

There could be an easier way to do it, but I've just modified your code to make it working. You can actually define a variable that stores the last name, as follows:

data <- c("lodge", "lodge", "loop", NA, "mall", "manor")

i = 1
data[i]
name <- data[i]
len <- length(data)

last.name <- ''
for (i in 1:len) {

  name <- data[i]

  ifelse(is.na(name), 
          data[i] <- last.name,
          name <- data[i])


  i <- i + 1
  last.name <- name
}

data
#[1] "lodge" "lodge" "loop"  "loop"  "mall"  "manor"

Hope it helps.

Taher A. Ghaleb
  • 5,120
  • 5
  • 31
  • 44
1

I tried to keep your structure of for loop, so you can read it easily

data <- c("lodge", "lodge", "loop", NA, "mall", "manor")

name <- c()
for (i in data) {
  if (!is.na(i)) {
    name <- c(name,i)
  } else {
    name <- c(name,tail(name,1))
  }
}

such that

> name
[1] "lodge" "lodge" "loop"  "loop"  "mall"  "manor"
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81