43

文字と数字を含むデータフレームを取得し、各行のすべての要素を1つの文字列に連結して、ベクトルに1つの要素として格納したいと思います。例として、文字と数字のデータフレームを作成し、貼り付け関数を使用して最初の行を連結し、値「A1」を返すことを望みます。

df <- data.frame(letters = LETTERS[1:5], numbers = 1:5)
df

##   letters numbers
## 1       A       1
## 2       B       2
## 3       C       3
## 4       D       4
## 5       E       5

paste(df[1,], sep =".")
## [1] "1" "1"

したがって、pasteは、行の各要素を、「対応するレベルのインデックス」に対応する整数に、それが因子であるかのように変換し、長さ2のベクトルを保持します。(文字に強制された因子はこのように動作することを私は知っています/信じていますが、Rはdf [1、]を因子としてまったく保存していないため(is.factor()でテスト済み)、それを確認できません実際にはレベルのインデックスです)

is.factor(df[1,])
## [1] FALSE
is.vector(df[1,])
## [1] FALSE

したがって、それがベクトルでない場合、それが奇妙に動作していることは理にかなっていますが、私はそれをベクトルに強制することはできません

> is.vector(as.vector(df[1,]))
[1] FALSE

使用as.characterすることは私の試みに役立たなかったようです

誰かがこの振る舞いを説明できますか?

4

4 に答える 4

67

他の人はあなたのコードが機能しない理由とそれを改善する方法に焦点を合わせていますが、私はあなたが望む結果を得ることにもっと焦点を合わせようとしています。あなたの説明から、あなたはペーストを使ってあなたが望むものを簡単に達成できるようです:

df <- data.frame(letters = LETTERS[1:5], numbers = 1:5, stringsAsFactors=FALSE)
paste(df$letters, df$numbers, sep=""))

## [1] "A1" "B2" "C3" "D4" "E5"

引数を使用したくない場合は、を使用しdf$lettersて文字に変更できます。df$letters <- as.character(df$letters)stringsAsFactors

しかし、それがあなたが望むものではないと仮定しましょう。何百もの列があり、それらをすべて一緒に貼り付けたいとしましょう。私たちはあなたの最小限の例でもそれを行うことができます:

df_args <- c(df, sep="")
do.call(paste, df_args)

## [1] "A1" "B2" "C3" "D4" "E5"

編集:代替方法と説明:

私はあなたが抱えている問題は、あなたが因子を使用しているという事実と、sep代わりに引数を使用しているという事実の組み合わせであることcollapseに気づきました(@adibenderが拾ったように)。違いは、sep2つの別々のベクトルの間にセパレーターを与えcollapse、ベクトル内にセパレーターを与えることです。を使用する場合はdf[1,]、に単一のベクトルを指定するため、引数pasteを使用する必要があります。collapseすべての行を取得して連結するというアイデアを使用すると、次のコード行で目的どおりに実行できます。

apply(df, 1, paste, collapse="")

さて、説明のために:

なぜ機能しないas.listのですか?

as.listオブジェクトをリストに変換します。だからそれは機能します。データフレームをリストに変換し、その後引数を無視しsep=""ます。cオブジェクトを結合します。技術的には、データフレームはすべての列が要素であり、すべての要素が同じ長さである必要がある単なるリストです。したがって、これをと組み合わせるとsep=""、データフレームの列を要素として持つ通常のリストになります。

なぜ使用するのdo.callですか?

do.call名前付きリストを引数として使用して関数を呼び出すことができます。データフレームが好きではないので、リストを直接に投げ込むことはできませpasteん。ベクトルを連結するために設計されています。dfargsしたがって、これは文字のベクトル、数字のベクトル、および「」のみを含む長さ1のベクトルであるsepを含むリストであることを忘れないでください。を使用するdo.callと、結果の貼り付け関数は基本的にpaste(letters, numbers, sep)です。
しかし、元のデータフレームに列が"letters", "numbers", "squigs", "blargs"あり、その後に以前と同じようにセパレータを追加した場合はどうなりますか?次に、貼り付け関数は次のdo.callようになります。

paste(letters, numbers, squigs, blargs, sep)

したがって、任意の数の列で機能することがわかります。

于 2012-12-19T01:32:54.033 に答える
5

を使用している場合は、関数library(tidyverse)を使用するだけですunite

 new.df <- df%>%
 unite(together, letters, numbers, sep="")

togetherこれにより、A1、B2などで呼び出される新しい列が表示されます。

于 2017-05-11T19:04:28.873 に答える
4

これは確かに少し奇妙ですが、これはまた起こることになっていることです。作成したとおりに作成するdata.frameと、列lettersはとして保存されfactorます。当然、因子には順序がありません。したがってas.numeric()、因子に適用されると、因子の順序が返されます。例えば:

> df[, 1]
[1] A B C D E
Levels: A B C D E
> as.numeric(df[, 1])
[1] 1 2 3 4 5

Aは係数の最初のレベルであるdf[, 1]ため、が適用されるAと値に変換されます。これは、を呼び出すときに発生することです。列1と列2はクラスが異なるため、貼り付けは最初に行1の両方の要素を数値に変換してから文字に変換します。1as.numericpaste(df[1, ])

両方の列を連結する場合は、最初に最初の行を文字に変換する必要があります。

df[, 1] <- as.character(df[, 1])
paste(df[1,], collapse = "")

@ sebastian-cが指摘したようstringsAsFactors = FALSEに、data.frameの作成にも使用でき、その場合はこの手順を省略できますas.character()

于 2012-12-19T01:28:41.200 に答える
1

から始めたい場合

df <- data.frame(letters = LETTERS[1:5], numbers = 1:5, stringsAsFactors=TRUE)

..その場合 df$letters、特定の関数によってどのように解釈されるかについての一般的な規則はありません。これは、関数をモデル化するための要素であり、一部の場合は文字、その他の場合は整数です。貼り付けなどの同じ関数でも、使用方法によっては解釈が異なる場合があります。

paste(df[1,], collapse="") # "11"
apply(df, 1, paste, collapse="") # "A1" "B2" "C3" "D4" "E5"

すべての関数の内部を理解すればおそらく意味があることを除いて、ロジックはありません。

引数がベクトルに変換されると、因子は整数に変換されるように見えます(ご存知のように、データフレームは同じ長さのベクトルのリストであるため、データフレームの最初の行もリストであり、強制的にベクトル、このようなことが起こります:)

df[1,]
#    letters numbers
# 1       A       1
unlist(df[1,])
# letters numbers 
#  1       1 

applyそれが何をするのか(つまり、因子は文字値で表される)をどのように達成するのかわかりません-興味があれば、そのソースコードを見てください。applyただし、(この特定の意味で) (この特定の機会に)信頼できることを知っておくと便利な場合があります。より一般的には、すべてのデータを適切な形式で保存すると便利です。これには、文字列を文字列として保存することも含まれます。つまり、を使用しstringsAsFactors=FALSEます。

ところで、すべての入門的なRの本は、サブタイトルにこのアイデアを持っている必要があります。たとえば、私の引退の計画は、「Rを使用した禅のデータ漁業の(そうではない)穏やかな紹介、stringsAsFactors=FALSEの方法」と書くことです。

于 2018-01-19T09:36:48.597 に答える