web-dev-qa-db-ja.com

データフレーム文字列列を複数の異なる列に分割する

私が達成しようとしているのは、列を複数の列に分割することです。最初の列には「F」、2番目の列には「US」、3番目には「CA6」または「DL」、4番目には「Z13」または「U13」などを含めます。 X.XX.XXXX.XXXまたはX.XX.XXX.XXXまたはX.XX.XX.XXXで、長さが異なるために3番目の列が問題のある場所であることを知っています。私は過去にsubstrのみを使用しており、ここでいくつかのifステートメントでそれを使用できましたが、これを行うためのストリンガーパッケージとPOSIXの使用方法を学びたいです(より良いオプションがない限り)。前もって感謝します。

ここに私のdfがあります:

c("F.US.CLE.V13", "F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13", 
"F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13", 
"F.US.DL.U13", "F.US.DL.U13", "F.US.DL.U13", "F.US.DL.Z13", "F.US.DL.Z13"
)
27
Tim

非常に直接的な方法は、単にread.tableあなたの文字ベクトル:

> read.table(text = text, sep = ".", colClasses = "character")
   V1 V2  V3  V4
1   F US CLE V13
2   F US CA6 U13
3   F US CA6 U13
4   F US CA6 U13
5   F US CA6 U13
6   F US CA6 U13
7   F US CA6 U13
8   F US CA6 U13
9   F US  DL U13
10  F US  DL U13
11  F US  DL U13
12  F US  DL Z13
13  F US  DL Z13

colClassesを指定する必要があります。そうでない場合、FFALSEに変換されます(これは「splitstackshape」で修正する必要があります。


更新(> 1年後)...

または、次のように my cSplit function を使用できます。

cSplit(as.data.table(text), "text", ".")
#     text_1 text_2 text_3 text_4
#  1:      F     US    CLE    V13
#  2:      F     US    CA6    U13
#  3:      F     US    CA6    U13
#  4:      F     US    CA6    U13
#  5:      F     US    CA6    U13
#  6:      F     US    CA6    U13
#  7:      F     US    CA6    U13
#  8:      F     US    CA6    U13
#  9:      F     US     DL    U13
# 10:      F     US     DL    U13
# 11:      F     US     DL    U13
# 12:      F     US     DL    Z13
# 13:      F     US     DL    Z13

または、「tidyr」のseparateは、次のようになります。

library(dplyr)
library(tidyr)

as.data.frame(text) %>% separate(text, into = paste("V", 1:4, sep = "_"))
#    V_1 V_2 V_3 V_4
# 1    F  US CLE V13
# 2    F  US CA6 U13
# 3    F  US CA6 U13
# 4    F  US CA6 U13
# 5    F  US CA6 U13
# 6    F  US CA6 U13
# 7    F  US CA6 U13
# 8    F  US CA6 U13
# 9    F  US  DL U13
# 10   F  US  DL U13
# 11   F  US  DL U13
# 12   F  US  DL Z13
# 13   F  US  DL Z13
52

これはあなたがやろうとしていることですか?

# Our data
text <- c("F.US.CLE.V13", "F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13", 
"F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13", 
"F.US.DL.U13", "F.US.DL.U13", "F.US.DL.U13", "F.US.DL.Z13", "F.US.DL.Z13"
)

#  Split into individual elements by the '.' character
#  Remember to escape it, because '.' by itself matches any single character
elems <- unlist( strsplit( text , "\\." ) )

#  We know the dataframe should have 4 columns, so make a matrix
m <- matrix( elems , ncol = 4 , byrow = TRUE )

#  Coerce to data.frame - head() is just to illustrate the top portion
head( as.data.frame( m ) )
#  V1 V2  V3  V4
#1  F US CLE V13
#2  F US CA6 U13
#3  F US CA6 U13
#4  F US CA6 U13
#5  F US CA6 U13
#6  F US CA6 U13
18
Simon O'Hanlon

unlistmatrixを経由する方法は少し複雑で、要素の数をハードコーディングする必要があります(これは実際にはかなり大きな問題です。もちろん、ハード回避することもできます。その番号をコーディングし、実行時に決定します)

別の方法で、strsplitが返すリストから直接データフレームを作成します。私にとって、これは概念的に簡単です。これを行うには、本質的に2つの方法があります。

  1. as.data.frame –しかし、リストはまったく間違った方法であるため(列のリストではなく行のリストがあります)、結果を転置する必要があります。 rownamesもデフォルトでいのでクリアします(しかし、それは厳密には不要です!):

    `rownames<-`(t(as.data.frame(strsplit(text, '\\.'))), NULL)
    
  2. または、rbindを使用して、行のリストからデータフレームを作成します。を使用しております do.callすべての行を個別の引数としてrbindを呼び出す:

    do.call(rbind, strsplit(text, '\\.'))
    

どちらの方法でも同じ結果が得られます。

     [,1] [,2] [,3]  [,4]
[1,] "F"  "US" "CLE" "V13"
[2,] "F"  "US" "CA6" "U13"
[3,] "F"  "US" "CA6" "U13"
[4,] "F"  "US" "CA6" "U13"
[5,] "F"  "US" "CA6" "U13"
[6,] "F"  "US" "CA6" "U13"
…

明らかに、2番目の方法は最初の方法よりもはるかに簡単です。

8
Konrad Rudolph