将数据框字符串列拆分为多个不同的列

时间:2013-09-05 16:57:09

标签: r split dataframe stringr

我想要完成的是将列拆分为多个列。我希望第一列包含“F”,第二列“US”,第三列“CA6”或“DL”,第四列是“Z13”或“U13”等等。我的整个df遵循相同的模式X.XX.XXXX.XXX或X.XX.XXX.XXX或X.XX.XX.XXX我知道第三列是我的问题所在,因为长度不同。我过去只使用了substr,我可以在这里使用一些if语句,但是想学习如何使用stringr包和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"
)

4 个答案:

答案 0 :(得分:49)

一种非常直接的方法是在你的角色向量上使用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,否则F会转换为FALSE(这是我需要在“splitstackshape”中修复的内容,否则我会建议:))< / p>


更新(&gt;一年后)......

或者,您可以使用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

答案 1 :(得分:17)

这是你想要做的吗?

# 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

答案 2 :(得分:8)

通过unlistmatrix的方式似乎有点复杂,并且要求您对元素的数量进行硬编码(这实际上是一个非常大的禁忌。当然,你可以绕开困难 - 编码该数字并在运行时确定它)

我会选择不同的路径,直接从strsplit返回的列表构建数据框。对我来说,这在概念上更简单。实际上有两种方法:

  1. as.data.frame - 但由于列表完全是错误的方式(我们有一个行列表而不是列列表),我们必须转置结果。我们也清除了rownames,因为它们在默认情况下很丑陋(但这绝对不必要!):

    `rownames<-`(t(as.data.frame(strsplit(text, '\\.'))), NULL)
    
  2. 或者,使用rbind从行列表构造数据框。我们使用do.call来调用rbind,将所有行作为单独的参数:

    do.call(rbind, strsplit(text, '\\.'))
    
  3. 两种方式都会产生相同的结果:

         [,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"
    …
    

    显然,第二种方式比第一种方式简单得多。

答案 3 :(得分:0)

我们可以使用tidyr::extract()

x <- 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"
)


library(tidyr)
extract(tibble(data=x),"data", regex = "^(.*?)\\.(.*?)\\.(.*?)\\.(.*?)$",into = LETTERS[1:4])
#> # A tibble: 13 x 4
#>    A     B     C     D    
#>    <chr> <chr> <chr> <chr>
#>  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

另一种选择是使用unglue::unglue_data()

# remotes::install_github("moodymudskipper/unglue")
library(unglue)
unglue_data(x,"{A}.{B}.{C}.{D}")
#>    A  B   C   D
#> 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

reprex package(v0.3.0)于2019-09-14创建