Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pasting together subsetted columns

I want to paste together some columns with some text where they are combined only if at least one is not NA and the current solution I have works, but is cumbersome. So I am wondering if there is a neater way to do this (to create the "combine" column below). I would like to have used tidyr but there doesn't seem to be a way to specify how to treat missing values in unite()

Thanks and I hope I haven't missed something obvious.

df = data.frame(num=c(1,2,NA,NA),place=c("Rome",NA,"Paris",NA))

df$combine[!is.na(df$num)|!is.na(df$place)] = 
  paste(df$num[!is.na(df$num)|!is.na(df$place)],
        "days in",df$place[!is.na(df$num)|!is.na(df$place)]) 

# df
#   num place          combine
# 1   1  Rome   1 days in Rome
# 2   2  <NA>     2 days in NA
# 3  NA Paris NA days in Paris
# 4  NA  <NA>             <NA>
like image 496
Impossible9 Avatar asked Mar 12 '23 08:03

Impossible9


2 Answers

Whenever you find yourself computing the same thing (here: index) again, try to store it and reuse that object to avoid redundant computation. For your example, you could compute the non-NA index as follows:

idx <- rowSums(!is.na(df)) > 0

Then, you can use that to paste the relevant rows together:

df[idx, "combine"] <- with(df[idx, ], paste(num, "days in", place))
like image 107
talat Avatar answered Mar 24 '23 00:03

talat


We can use mutate with ifelse from dplyr

library(dplyr)
df %>%
   mutate(combine = ifelse(rowSums(!is.na(.))>0, paste(num, "days in", place), NA))
#    num place          combine
#1   1  Rome   1 days in Rome
#2   2  <NA>     2 days in NA
#3  NA Paris NA days in Paris
#4  NA  <NA>      <NA>

Or using data.table

library(data.table)
setDT(df)[df[, !Reduce(`&`, lapply(.SD, is.na))], combine := paste(num, "days in", place)]
df
#   num place          combine
#1:   1  Rome   1 days in Rome
#2:   2    NA     2 days in NA
#3:  NA Paris NA days in Paris
#4:  NA    NA               NA
like image 23
akrun Avatar answered Mar 24 '23 01:03

akrun