smgds
smgds

Reputation: 107

Create new column based on values from three other columns in R

I have a dataframe:

df <- data.frame('a'=c(1,NA,3,NA,NA), 'b'=c(NA,NA,NA,4,50), 'c'=c(NA,5,NA,NA,NA))
df
   a  b  c
1  1 NA NA
2 NA NA  5
3  3 NA NA
4 NA  4 NA
5 NA 50 NA

I need to create a new column d that combines only the values without the NAs:

  a  b  c  d
1  1 NA NA 1
2 NA NA  5 5
3  3 NA NA 3
4 NA  4 NA 4
5 NA 50 NA 50

Upvotes: 3

Views: 1139

Answers (4)

AndrewGB
AndrewGB

Reputation: 16856

Another option is to use fcoalesce from data.table, which takes a dataframe and allows you to forgo having to add the column names.

library(data.table)

df$d <- fcoalesce(df)

Output

   a  b  c  d
1  1 NA NA  1
2 NA NA  5  5
3  3 NA NA  3
4 NA  4 NA  4
5 NA 50 NA 50

Or we could use do.call and pmax:

df$d <- do.call(pmax, c(df, list(na.rm=TRUE)))

Upvotes: 1

akrun
akrun

Reputation: 887058

A vectorized option in base R is max.col to get the column index of non-NA, cbind with row sequence and extract the element

df$d <- df[cbind(seq_len(nrow(df)), max.col(!is.na(df)))]

-output

> df
   a  b  c  d
1  1 NA NA  1
2 NA NA  5  5
3  3 NA NA  3
4 NA  4 NA  4
5 NA 50 NA 50

Upvotes: 1

Fujibayashi Kyou
Fujibayashi Kyou

Reputation: 79

You can simply do the following without using any libraries:

df$d <- apply(df, MARGIN=1, function(x) x[!is.na(x)])
   a  b  c  d
1  1 NA NA  1
2 NA NA  5  5
3  3 NA NA  3
4 NA  4 NA  4
5 NA 50 NA 50

It works as: The function, function(x) x[!is.na(x)], which takes a vector as input and return the non-na element from it, is applied to every row (margin=1).

Upvotes: 1

TarJae
TarJae

Reputation: 78927

Additional to the solution by @r2evans in the comment section:

We could use coalesce from dplyr package:

df %>% 
  mutate(d = coalesce(a, b, c))
   a  b  c  d
1  1 NA NA  1
2 NA NA  5  5
3  3 NA NA  3
4 NA  4 NA  4
5 NA 50 NA 50

OR

We could use unite from tidyr package with na.rm argument:

library(tidyr)
library(dplyr)

df %>% 
  unite(d, a:c, na.rm = TRUE, remove = FALSE)
   d  a  b  c
1  1  1 NA NA
2  5 NA NA  5
3  3  3 NA NA
4  4 NA  4 NA
5 50 NA 50 NA

Upvotes: 4

Related Questions