Diviser une colonne de chaîne de caractères dataframe en plusieurs colonnes différentes

ce que j'essaie d'accomplir c'est diviser une colonne en plusieurs colonnes. Je préférerais que la première colonne contienne "F", la deuxième colonne "US", la troisième "CA6" ou "DL", et la quatrième "Z13" ou "U13" etc. Mon df entier suit le même modèle de X. XX.XXXX.XXX ou X. XX.XXX.XXX ou X. XX.XX.XXX et je sais que la troisième colonne est là que mon problème se situe à cause des longueurs différentes. Je n'ai utilisé substr que dans le passé et je pourrais l'utiliser ici avec quelques déclarations if mais je voudrais pour apprendre à utiliser le paquet stringr et POSIX pour le faire (à moins qu'il y ait une meilleure option). Je vous remercie à l'avance.

Voici mon 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"
)
22
demandé sur smci 2013-09-05 20:57:08

3 réponses

Une façon très directe est d'utiliser read.table sur votre vecteur de caractères:

> 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 doit être spécifié, sinon F conversion FALSE (qui est quelque chose que j'ai besoin de fixer dans "splitstackshape", sinon je l'aurais recommandé que :) )


mise à Jour (> un an plus tard)...

Alternativement, vous pouvez utiliser mon cSplit function, comme ceci:

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

Ou separate à partir de "tidyr", comme ceci:

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
45
répondu A5C1D2H2I1M1N2O1R2T1 2014-10-12 16:26:55

Est-ce que vous essayez de faire?

# 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
15
répondu Simon O'Hanlon 2013-09-05 17:01:24

par unlist et matrix semble un peu alambiqué, et nécessite que vous codiez dur le nombre d'éléments (c'est en fait un assez gros non-go. Bien sûr, vous pouvez contourner le codage dur ce nombre et le déterminer à l'exécution)

je suivrais un chemin différent, et construirais une base de données directement à partir de la liste qui strsplit retourne. Pour moi, c'est conceptuellement plus simple. Il y a essentiellement deux façons de faire cela:

  1. as.data.frame – mais, puisque la liste est exactement le mauvais sens (nous avons une liste de lignes plutôt qu'une liste de colonnes), nous avons de transposer le résultat. Nous dégageons également le rownames depuis qu'ils sont laids par défaut (mais c'est strictement inutile!):

    `rownames<-`(t(as.data.frame(strsplit(text, '\.'))), NULL)
    
  2. vous pouvez également utiliser rbind construire une base de données à partir de la liste des lignes. Nous utilisons do.call appeler rbind avec toutes les lignes comme distincts des arguments:

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

les Deux façons de rendement de l' même résultat:

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

Clairement, la deuxième méthode est beaucoup plus simple que la première.

6
répondu Konrad Rudolph 2013-09-05 17:18:59