0

normally when I want to update a variable in R I perform the normal assignment:

df[var] <- new_vector

But let's say new_vector has many NAs and non-NAs values. I would like to only change values of df[var] for which new_vector is not NA and leave them unchanged for those rows if new_vector is NA

new_vector <- c(0, NA, NA, 0, 1)
df <- data.frame(1:5,11:15)
colnames(df) <- c("A", "B")
df
#  A  B
#1 1 11
#2 2 12
#3 3 13
#4 4 14
#5 5 15
df["B"] <- new_vector
df
#got:
#  A  B
#1 1  0
#2 2 NA
#3 3 NA
#4 4  0
#5 5  1
#
#but I intend:
#  A  B
#1 1  0
#2 2 12
#3 3 13
#4 4  0
#5 5  1
gota
  • 2,338
  • 4
  • 25
  • 45
  • Possible duplicate https://stackoverflow.com/q/19253820/680068 – zx8754 Sep 01 '21 at 12:24
  • 2
    This is marked as a duplicate, however I would never know that this operation has a name: coalesce. Therefore I would never arrive at the original question. I think leaving this question is useful for the future and I wonder how many similar questions have been marked as duplicates and deleted but would have otherwise allowed me to find the answer quicker – gota Sep 01 '21 at 12:34
  • 1
    Duplicate posts **are** useful. This post has an accepted upvoted answer, so it will not be [auto-deleted](https://stackoverflow.com/help/roomba). – zx8754 Sep 01 '21 at 20:26

4 Answers4

1

You can use -

df$B[!is.na(new_vector)] <- na.omit(new_vector)
df

#  A  B
#1 1  0
#2 2 12
#3 3 13
#4 4  0
#5 5  1
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
1

I would store the positions where new_vector is not NA and use it to subset both, df$B and new_vector.

i <- !is.na(new_vector)
#i <- which(!is.na(new_vector)) #Sometimes more efficient variant
df$B[i] <- new_vector[i]
df
#  A  B
#1 1  0
#2 2 12
#3 3 13
#4 4  0
#5 5  1
GKi
  • 37,245
  • 2
  • 26
  • 48
1

Here is a tidyverse solution:

library(dplyr)

df %>%
  mutate(B = coalesce(new_vector, B))

  A  B
1 1  0
2 2 12
3 3 13
4 4  0
5 5  1
Anoushiravan R
  • 21,622
  • 3
  • 18
  • 41
1

You can use the coalesce function from dplyr:

new_vector <- c(0, NA, NA, 0, 1)
df <- data.frame(1:5,11:15)
colnames(df) <- c("A", "B")
df$B <- dplyr::coalesce(new_vector, df$B)
df
#>   A  B
#> 1 1  0
#> 2 2 12
#> 3 3 13
#> 4 4  0
#> 5 5  1

Created on 2021-09-01 by the reprex package (v2.0.1)

Claudio
  • 1,229
  • 6
  • 11