51

懸賞金について

Ben Bolkerの-solutionは、貼り付けられた文字列の同じ位置にが含まれている場合にpaste2を生成します。このような、""NA

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

4 番目の要素は、""このNAように、

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

これを修正できる人のために、この小さな報奨金を提供します。

元の質問

ヘルプ ページを読みましたが、?pasteR に s を無視させる方法がわかりません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"

しかし、それは回り道のようです。

4

13 に答える 13

48

「真のNA」の目的のために:最も直接的なルートは、によって返される値を変更してpaste2NA値が""

 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    
于 2013-03-28T02:23:57.703 に答える
42

この質問が何年も前のものであることは知っていますが、それでも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"

明らかでない場合、これはNAs が任意の位置にある任意の数のベクトルで機能します。

私見、既存の回答に対するこれの利点は読みやすさです。これは常に素晴らしいワンライナーであり、同僚や将来の自分をつまずかせる可能性のある一連の正規表現や if/else ステートメントに依存しません。Erik Shitts の回答は、これらの利点をほとんど共有していますが、ベクトルは 2 つしかなく、最後のベクトルだけにNAs が含まれていると想定しています。

私のプロジェクトには反対の要件があるため、私のソリューションは編集の要件を満たしていません。ただし、 42-'s answerから借用した 2 行目を追加することで、これを簡単に解決できます。

is.na(bar) <- bar == ""
于 2018-03-09T20:06:08.113 に答える
15

@ErikShiltの回答と@agstudyのコメントをフォローアップする関数。これは、指定を許可し、任意の要素(最初、最後、または中間)がでsepある場合を処理することにより、状況をわずかに一般化します。(行に複数の値がある場合、またはその他のトリッキーな場合は破損する可能性があります...)ちなみに、この状況はのセクションの2番目の段落に正確に記述されていることに注意してください。これは、少なくともRの作成者を示しています。状況を認識しています(ただし、解決策は提供されていません)。NANADetails?paste

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"   

collapseこれは、(1)オプションの引数を組み込むという@agstudyの提案を処理しません。(2)引数NAを追加して-removalをオプションにしna.rmます(そして、デフォルトをに設定しFALSEpaste2下位互換性を持たせますpaste)。これをより洗練されたもの(つまり、複数のシーケンシャルを削除するNA)またはより高速にしたい場合は、Rcppを介してC ++で記述するのが理にかなっているかもしれません(C ++の文字列処理についてはよくわかりませんが、それほど難しくはないかもしれません- Rcpp::CharacterVectorをstd::stringに変換するを参照してください。文字列の連結は、開始時に期待どおりに機能しません...)

于 2012-12-02T22:52:35.183 に答える
13

Ben Bolkerが述べたように、複数の NA が連続している場合、上記のアプローチは失敗する可能性があります。これを克服すると思われる別のアプローチを試みました。

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)
  }

2 行目は、テキストと数値を連結するときに導入された余分な空白を取り除きます。上記のコードは、コマンドを使用してデータフレームの複数の列 (または行) を連結するために使用しapplyたり、必要に応じて最初にデータをデータフレームに強制するために再パッケージ化することができます。

EDIT

さらに数時間考えた後、次のコードには上記の提案が組み込まれており、collapse オプションと 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)
      }
    }
}

上記のように、必要に応じて空の文字列もドロップ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" 
于 2015-07-20T04:16:35.470 に答える
6

ifelseベクトル化された if-else 構文である を使用して、値が NA であるかどうかを判断し、空白に置き換えることができます。その後、他の文字列が続いていない場合は、gsub を使用して末尾の「,」を取り除きます。

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

あなたの答えは正しいです。それを行うより良い方法はありません。この問題は、貼り付けドキュメントの詳細セクションに明示的に記載されています。

于 2012-12-02T21:21:34.197 に答える
2

または、貼り付け後に str_replace_all で NA を削除します

data$1 <- str_replace_all(data$1, "NA", "")
于 2019-04-25T10:05:37.230 に答える