2016-08-25 2 views
4

Я хочу вставить несколько столбцов с некоторым текстом, где они объединены, только если хотя бы один из них не является NA, а текущее решение у меня есть, но оно громоздко. Поэтому мне интересно, есть ли более простой способ сделать это (создать столбец «комбинировать» ниже). Я бы хотел использовать tidyr, но, похоже, не существует способа указать, как обрабатывать недостающие значения в unite()Вставка поднаборных столбцов

Спасибо, и я надеюсь, что я не пропустил что-то очевидное.

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> 
+0

Сочетание столбцов звучит как задание для 'cbind()'. –

+0

Почему вам нужны строки, где все значения равны NA? Разве вы не можете просто удалить строки со всеми NA и просто «вставить» остальные? – Sotos

+1

«2 дня в NA» или «Дни NA в Париже» как результат имеет смысл? – zx8754

ответ

6

Всякий раз, когда вы оказываетесь вычисления то же самое (здесь: индекс) снова, попробуйте сохранить его и повторно использовать этот объект, чтобы избежать избыточных вычислений. Для примера, можно вычислить не-NA индекс следующим образом:

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

Затем, вы можете использовать, чтобы вставить соответствующие строки вместе:

df[idx, "combine"] <- with(df[idx, ], paste(num, "days in", place)) 
+1

Если у вас больше двух этих столбцов в исходных данных, измените первую строку на 'idx <- rowSums (! Is.na (df [, c (" num "," place ")]))> 0' –

1

Мы можем использовать mutate с ifelse из 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> 

Или с помощью 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 
Смежные вопросы