R: replace NA with item from vector

2020-02-08 21:41发布

问题:

I am trying to replace some missing values in my data with the average values from a similar group.

My data looks like this:

   X   Y
1  x   y
2  x   y
3  NA  y
4  x   y

And I want it to look like this:

  X   Y
1  x   y
2  x   y
3  y   y
4  x   y

I wrote this, and it worked

for(i in 1:nrow(data.frame){
   if( is.na(data.frame$X[i]) == TRUE){
       data.frame$X[i] <- data.frame$Y[i]
   }
  }

But my data.frame is almost half a million lines long, and the for/if statements are pretty slow. What I want is something like

is.na(data.frame$X) <- data.frame$Y

But this gets a mismatched size error. It seems like there should be a command that does this, but I cannot find it here on SO or on the R help list. Any ideas?

回答1:

ifelse is your friend.

Using Dirk's dataset

df <- within(df, X <- ifelse(is.na(X), Y, X))


回答2:

Just vectorise it -- the boolean index test is one expression, and you can use that in the assignment too.

Setting up the data:

R> df <- data.frame(X=c("x", "x", NA, "x"), Y=rep("y",4), stringsAsFactors=FALSE)
R> df
     X Y
1    x y
2    x y
3 <NA> y
4    x y

And then proceed by computing an index of where to replace, and replace:

R> ind <- which( is.na( df$X ) )
R> df[ind, "X"] <- df[ind, "Y"]

which yields the desired outcome:

R> df
  X Y
1 x y
2 x y
3 y y
4 x y
R> 


回答3:

Unfortunately I cannot comment, yet, but while vectorizing some code where strings aka characters were involved the above seemd to not work. The reason being explained in this answer. If characters are involved stringsAsFactors=FALSE is not enough because R might already have created factors out of characters. One needs to ensure that the data also becomes a character vector again, e.g., data.frame(X=as.character(c("x", "x", NA, "x")), Y=as.character(rep("y",4)), stringsAsFactors=FALSE)