0

I have a dataframe:df <- data.frame(id = c('1','2','3'), b = c('b1', 'NA', 'b3'), c = c('c1', 'c2', 'NA'), d = c('d1', 'NA', 'NA'))

id b   c   d
1  b1  c1  d1
2  NA  c2  NA
3  b3  NA  NA

I have extracted values with id = 1 from df to another dataframe say df2 so df2 has 1 row

id b c d
1 b1 c1 d1

I need to copy all values from df2 to df1 wherever there is not an NA in df1 Result Table:

id b   c   d
1  b1  c1  d1
2  b1  c2  d1
3  b3  c1  d1

Thank you in advance. I asked similar question before but deleting it.

Digvijay Sawant
  • 1,049
  • 3
  • 16
  • 32
  • Do you mean wherever there IS a `NA` in a row? – rpanai Jun 20 '18 at 01:58
  • 1
    What is the rule being followed here? Why is `df2[3,3]` `c1` instead of `c2`? – hpesoj626 Jun 20 '18 at 02:01
  • maybe related: https://stackoverflow.com/questions/14205583/filtering-data-in-a-dataframe-based-on-criteria – Ray Tayek Jun 20 '18 at 02:03
  • Isn't this just https://stackoverflow.com/questions/50937431/copy-rows-of-dataframes-in-r/50937532 with an `is.na` test instead of `==""` ? – thelatemail Jun 20 '18 at 03:33
  • @thelatemail I have tried with is.na and get an error saying `Error in if (length(o)%%N != 0L) warning("number of items to replace is not a multiple of replacement length"): missing value where TRUE/FALSE needed` I just replaced line `idx <- which(is.na(df[-1]), arr.ind=TRUE)` – Digvijay Sawant Jun 20 '18 at 17:02
  • @user32185 Yes. Just replace the NA and if there exists a value in that cell keep it as it is. – Digvijay Sawant Jun 20 '18 at 18:36
  • @hpesoj626 Yes you are correct. Sorry it was a typo – Digvijay Sawant Jun 20 '18 at 18:37
  • `"NA"` is not the same as `NA` - which makes this confusing. Try `df[-1]=='NA'` and it will work perfectly. You should try to work with actual `NA` / missing values though, as they have special features that the string `"NA"` does not. – thelatemail Jun 21 '18 at 08:15

2 Answers2

1

Assuming that there is a mistake in your question -> df2 will be equal to b1-c1-d1 not b1-c2-d1, here is the solution :

Initialize dataframe

df <- data.frame(id = c('1','2','3'), b = c('b1', 'NA', 'b3'), c = c('c1', 'c2', 'NA'), d = c('d1', 'NA', 'NA'))

Converting string NAs to actual detectable NAs

df <- data.frame(lapply(df, function(x) { gsub("NA", NA, x) }))

Obtaining default value row

df2<-df[df$id==1,]

For all rows, check if the column cell is na, then fill it with the df2 cell of the same column

for (r in 1:nrow(df)) for( c in colnames(df)) df[r,c]<-ifelse(is.na(df[r,c]),as.character(df2[1,c]),as.character(df[r,c]))
1

Based on your last comment that df2[3,3] should be c2 and not c1, a straightforward answer is to use zoo::na.locf.

library(zoo)
df2 <- na.locf(df)

#   id  b  c  d
# 1  1 b1 c1 d1
# 2  2 b1 c2 d1
# 3  3 b3 c2 d1

Data

df <- structure(list(id = c(1, 2, 3), b = c("b1", NA, "b3"), c = c("c1", 
"c2", NA), d = c("d1", NA, NA)), class = "data.frame", row.names = c(NA, 
-3L))
hpesoj626
  • 3,529
  • 1
  • 17
  • 25