подавлять НС в пасте ()

Что касается щедрости

Вставка past2 от Ben Bolker создает "" когда вставляемые строки содержат NA в одной позиции. Как это,

 > paste2(c("a","b", "c", NA), c("A","B", NA, NA)) [1] "a, A" "b, B" "c" "" 

Четвертый элемент – это "" вместо NA Подобно этому,

 [1] "a, A" "b, B" "c" NA 

Я предлагаю эту небольшую наgradleу для всех, кто может это исправить.

Оригинальный вопрос

Я прочитал страницу справки, но я не понимаю, как R игнорировать NA . Я делаю следующее:

 foo <- LETTERS[1:4] foo[4] <- NA foo [1] "A" "B" "C" NA paste(1:4, foo, sep = ", ") 

и получить

 [1] "1, A" "2, B" "3, C" "4, NA" 

Что бы я хотел получить,

 [1] "1, A" "2, B" "3, C" "4" 

Я мог бы так:

 sub(', NA$', '', paste(1:4, foo, sep = ", ")) [1] "1, A" "2, B" "3, C" "4" 

но это похоже на объезд.

Для цели «истина-NA»: Кажется, самый прямой маршрут – это просто изменить значение, возвращаемое paste2 как NA когда значение равно ""

  paste3 <- function(...,sep=", ") { L <- list(...) L <- lapply(L,function(x) {x[is.na(x)] <- ""; x}) ret <-gsub(paste0("(^",sep,"|",sep,"$)"),"", gsub(paste0(sep,sep),sep, do.call(paste,c(L,list(sep=sep))))) is.na(ret) <- ret=="" ret } val<- paste3(c("a","b", "c", NA), c("A","B", NA, NA)) val #[1] "a, A" "b, B" "c" NA 

Функция, которая следует за ответом @ ErikShilt и комментарием @ agstudy. Он слегка обобщает ситуацию, позволяя указать sep и обрабатывать случаи, когда любой элемент (первый, последний или промежуточный) является NA . (Это может сломаться, если в строке есть несколько значений NA , или в других сложных случаях …) Кстати, обратите внимание, что эта ситуация описана точно во втором абзаце раздела « Details » ?paste , Что указывает на то, что на по крайней мере, авторы R знают о ситуации (хотя решения не предлагаются).

 paste2 <- function(...,sep=", ") { L <- list(...) L <- lapply(L,function(x) {x[is.na(x)] <- ""; x}) gsub(paste0("(^",sep,"|",sep,"$)"),"", gsub(paste0(sep,sep),sep, do.call(paste,c(L,list(sep=sep))))) } foo <- c(LETTERS[1:3],NA) bar <- c(NA,2:4) baz <- c("a",NA,"c","d") paste2(foo,bar,baz) # [1] "A, a" "B, 2" "C, 3, c" "4, d" 

Это не относится к предложениям @ agstudy о (1) включении необязательного аргумента collapse ; (2) сделать NA -removal необязательным, добавив аргумент na.rm (и установив по умолчанию FALSE чтобы сделать paste2 обратно совместимым с paste2 ). Если бы кто-то хотел сделать это более сложным (т. Е. Удалить несколько последовательных NA ) или быстрее, может возникнуть смысл записать его на C ++ через Rcpp (я мало знаю о строковой обработке C ++, но это может быть не слишком сложно - - см. преобразование Rcpp :: CharacterVector в std :: string и Конкатенация строк не работает так, как ожидалось для начала ...)

Как заметил Бен Болкер, вышеупомянутые подходы могут упасть, если в строке есть несколько НС. Я попробовал другой подход, который, кажется, преодолел это.

 paste4 <- function(x, sep = ", ") { x <- gsub("^\\s+|\\s+$", "", x) ret <- paste(x[!is.na(x) & !(x %in% "")], collapse = sep) is.na(ret) <- ret == "" return(ret) } в paste4 <- function(x, sep = ", ") { x <- gsub("^\\s+|\\s+$", "", x) ret <- paste(x[!is.na(x) & !(x %in% "")], collapse = sep) is.na(ret) <- ret == "" return(ret) } 

Вторая строка выделяет лишние пробелы, введенные при конкатенации текста и чисел. Вышеприведенный код может использоваться для конкатенации нескольких столбцов (или строк) фрейма данных с использованием команды apply или переупаковки, чтобы сначала принудительно вставить данные в фреймворк данных, если это необходимо.

 EDIT 

Спустя еще несколько часов я подумал, что следующий код содержит приведенные выше предложения, чтобы уточнить параметры коллапса и na.rm.

 paste5 <- function(..., sep = " ", collapse = NULL, na.rm = F) { if (na.rm == F) paste(..., sep = sep, collapse = collapse) else if (na.rm == T) { paste.na <- function(x, sep) { x <- gsub("^\\s+|\\s+$", "", x) ret <- paste(na.omit(x), collapse = sep) is.na(ret) <- ret == "" return(ret) } df <- data.frame(..., stringsAsFactors = F) ret <- apply(df, 1, FUN = function(x) paste.na(x, sep)) if (is.null(collapse)) ret else { paste.na(ret, sep = collapse) } } } в paste5 <- function(..., sep = " ", collapse = NULL, na.rm = F) { if (na.rm == F) paste(..., sep = sep, collapse = collapse) else if (na.rm == T) { paste.na <- function(x, sep) { x <- gsub("^\\s+|\\s+$", "", x) ret <- paste(na.omit(x), collapse = sep) is.na(ret) <- ret == "" return(ret) } df <- data.frame(..., stringsAsFactors = F) ret <- apply(df, 1, FUN = function(x) paste.na(x, sep)) if (is.null(collapse)) ret else { paste.na(ret, sep = collapse) } } } 

Как и выше, na.omit(x) можно заменить на (x[!is.na(x) & !(x %in% "") чтобы по желанию также удалить пустые строки. Обратите внимание, что с помощью коллапса с na.rm = T возвращает строку без какого-либо «NA», хотя это можно было бы изменить, заменив последнюю строку кода paste(ret, collapse = collapse) .

 nth <- paste0(1:12, c("st", "nd", "rd", rep("th", 9))) mnth <- month.abb nth[4:5] <- NA mnth[5:6] <- NA paste5(mnth, nth) [1] "Jan 1st" "Feb 2nd" "Mar 3rd" "Apr NA" "NA NA" "NA 6th" "Jul 7th" "Aug 8th" "Sep 9th" "Oct 10th" "Nov 11th" "Dec 12th" paste5(mnth, nth, sep = ": ", collapse = "; ", na.rm = T) [1] "Jan: 1st; Feb: 2nd; Mar: 3rd; Apr; 6th; Jul: 7th; Aug: 8th; Sep: 9th; Oct: 10th; Nov: 11th; Dec: 12th" paste3(c("a","b", "c", NA), c("A","B", NA, NA), c(1,2,NA,4), c(5,6,7,8)) [1] "a, A, 1, 5" "b, B, 2, 6" "c, , 7" "4, 8" paste5(c("a","b", "c", NA), c("A","B", NA, NA), c(1,2,NA,4), c(5,6,7,8), sep = ", ", na.rm = T) [1] "a, A, 1, 5" "b, B, 2, 6" "c, 7" "4, 8" 

Я знаю, что этот вопрос много лет, но он по-прежнему является лучшим результатом google для r paste na . Я искал быстрое решение того, что я считал простой проблемой, и был несколько ошеломлен сложностью ответов. Я выбрал другое решение, и я размещаю его здесь, если кто-то еще заинтересован.

 bar <- apply(cbind(1:4, foo), 1, function(x) paste(x[!is.na(x)], collapse = ", ")) bar [1] "1, A" "2, B" "3, C" "4" 

В случае, если это не очевидно, это будет работать на любом количестве vecotrs с NA в любых позициях.

ИМХО, преимущество этого над существующими ответами - parsingчивость. Это однострочный лайнер, который всегда хорош, и он не полагается на кучу регулярных выражений и if / else-высказываний, которые могут повлиять на ваших коллег или будущее. Ответ Эрика Шиттса в основном разделяет эти преимущества, но предполагает, что существует только два вектора, и только последний из них содержит НС.

Мое решение не удовлетворяет требованиям в вашем редактировании, потому что мой проект имеет противоположное требование. Однако вы можете легко решить эту проблему, добавив вторую строку, взятую из ответа 42-го :

 is.na(bar) <- bar == "" 

Вы можете использовать ifelse , векторную конструкцию if-else, чтобы определить, является ли значение NA и заменить пробел. Затем вы будете использовать gsub, чтобы вырезать конечную «,», если за ней не будет следовать какая-либо другая строка.

 gsub(", $", "", paste(1:4, ifelse(is.na(foo), "", foo), sep = ", ")) 

Ваш ответ правильный. Нет лучшего способа сделать это. Эта проблема явно упоминается в документации пасты в разделе «Подробности».

Или сделайте мутацию после paste () и удалите NA:

 data <- data.frame(col1= c(rep(NA, 5)), col2 = c(2:6)) %>% mutate(col3 = paste(col1, col2)) %>% mutate(col3 = gsub('NA', '', col3)) 
  • Цикл «для» добавляет только последний слой ggplot
  • Разделите строки с разделителями в столбце и вставьте в качестве новых строк
  • Создание фиктивных переменных в R data.table
  • Есть ли способ использовать два оператора «...» в функции из R?
  • Ошибка при установке пакета R
  • Подсчитайте количество нhive в строке и удалите строки с более чем n нулями
  • График рассеяния с ошибками
  • Объединить строки и выражения в заголовок сюжета
  • Заказать бары в гистограмме ggplot2
  • График временных рядов смещается на 2 часа, если используется scale_x_datetime
  • Как `poly ()` генерирует ортогональные полиномы? Как понять, что «коэф.» Вернулись?
  • Давайте будем гением компьютера.