Reputation: 317
I have dataframe that looks like this:
df <- data.frame(matrix(c(1,351,NA,1,0,2,585,0,1,1,3,321,NA,0,1,4,964,NA,NA,NA,5,556,0,1,NA), ncol = 5, byrow = TRUE))
colnames(df) <- c('id','value','v1','v2','v3')
Now I want to replace all NA's in the subset c('v1', 'v2', 'v3')
with 0 (zero) for all rows that are not all NA's.
So I want this:
R> df
id value v1 v2 v3
1 1 351 NA 1 0
2 2 585 0 1 1
3 3 321 NA 0 1
4 4 964 NA NA NA
5 5 556 0 1 NA
to end up like this:
R> df
id value v1 v2 v3
1 1 351 0 1 0
2 2 585 0 1 1
3 3 321 0 0 1
4 4 964 NA NA NA
5 5 556 0 1 0
Note that df[4, ]
still have NA's for c('v1', 'v2', 'v3')
.
Upvotes: 4
Views: 69
Reputation: 1983
A simple dplyr
solution:
library(tidyverse)
df %>%
mutate_at(vars(v1:v3), ~ifelse(is.na(v1) & is.na(v2) & is.na(v3), NA, replace_na(., 0)))
Upvotes: 1
Reputation: 40171
With dplyr
, you can try:
cols <- c("v1", "v2", "v3")
df %>%
mutate(row_na = rowSums(is.na(select(., one_of(cols)))) == length(cols)) %>%
mutate_at(vars(one_of(cols)), ~ ifelse(!row_na, replace(., is.na(.), 0), .)) %>%
select(-row_na)
id value v1 v2 v3
1 1 351 0 1 0
2 2 585 0 1 1
3 3 321 0 0 1
4 4 964 NA NA NA
5 5 556 0 1 0
Upvotes: 1
Reputation: 297
As simple as possible:
df[ !(is.na(df$v1) & is.na(df$v2) & is.na(df$v3)) & is.na(df) ] <- 0
Upvotes: 0
Reputation: 389325
In base R , here is one way
#columns to check for NA
cols <- c("v1", "v2", "v3")
#rows which needs to be replaced
rows <- which(rowSums(is.na(df[cols])) != length(cols))
#Replace values which are NA to 0
df[rows, cols] <- replace(df[rows, cols], is.na(df[rows, cols]), 0)
df
# id value v1 v2 v3
#1 1 351 0 1 0
#2 2 585 0 1 1
#3 3 321 0 0 1
#4 4 964 NA NA NA
#5 5 556 0 1 0
Upvotes: 2
Reputation: 1116
Here is a solution with good old loop:
for (r in 1:nrow(df))
{
# check that not the all row is na but that there are some na
if(!all(is.na(df[r,3:5])) && sum(is.na(df[r,3:5]>0)))
{
df[r,which(is.na(df[r,3:5]))+2]=0
}
}
Upvotes: 2