J'essaie de séparer ma colonne VEHICLE_TYPE par modèle et moteur. Le code peut être un code SQL ou R normal.

Mes données ressemblent à ceci:

       MODEL           VEHICLE_TYPE
77        Bora               Bora 1.6
79      Ducato Ducato 15 120 Multijet
80      Ducato Ducato 15 120 Multijet
87       Astra         Astra 1.7 CDTI
88         406            406 2.0 HDi
89         406            406 2.0 HDi
90 Focus C-MAX   Focus C-MAX 1.6 TDCi
91 Focus C-MAX   Focus C-MAX 1.6 TDCi
92 Focus C-MAX   Focus C-MAX 1.6 TDCi
93 Focus C-MAX   Focus C-MAX 1.6 TDCi
94 Focus C-MAX   Focus C-MAX 1.6 TDCi
97    S-Klasse              S 320 CDI
98    S-Klasse              S 320 CDI
99    S-Klasse              S 320 CDI

J'aimerais recevoir quelque chose comme ceci:

MODEL         VEHICLE TYPE
Bora          1.6
Ducato 15     120 Multijet
...           ...
Focus C-Max   1.6 TDCi

Le problème est que VEHICLE_TYPE peut avoir différentes longueurs et différents nombres d'espaces, que je pourrais séparer.

Je l'ai essayé avec gsub et regex , cela n'a pas fonctionné, mais strsplit a fonctionné. Loin de ce que je voulais réellement, je suis à court d'idées et j'ai besoin d'aide maintenant.

> strsplit(as.character(test$VEHICLE_TYPE)," ")

[[1]]
[1] "Bora" "1.6"

[[2]]
[1] "Ducato"   "15"       "120"      "Multijet"

[[3]]
[1] "Ducato"   "15"       "120"      "Multijet"

[[4]]
[1] "Astra" "1.7"   "CDTI" 

[[5]]
[1] "406" "2.0" "HDi"

[[6]]
[1] "406" "2.0" "HDi"

[[7]]
[1] "Focus" "C-MAX" "1.6"   "TDCi" 

[[8]]
[1] "Focus" "C-MAX" "1.6"   "TDCi" 

[[9]]
[1] "Focus" "C-MAX" "1.6"   "TDCi" 

[[10]]
[1] "Focus" "C-MAX" "1.6"   "TDCi" 

[[11]]
[1] "Focus" "C-MAX" "1.6"   "TDCi" 

[[12]]
[1] "S"   "320" "CDI"
0
rayray 26 janv. 2017 à 07:42

4 réponses

Meilleure réponse

Voici une solution alternative utilisant gsub

df$VEHICLE_TYPE <- gsub(".+ ([0-9.]+(?: [^ ]+)?)$", "\\1", df$VEHICLE_TYPE)

> df

#           MODEL VEHICLE_TYPE
#  1         Bora          1.6
#  2       Ducato 120 Multijet
#  3       Ducato 120 Multijet
#  4        Astra     1.7 CDTI
#  5          406      2.0 HDi
#  6          406      2.0 HDi
#  7  Focus C-MAX     1.6 TDCi
#  8  Focus C-MAX     1.6 TDCi
#  9  Focus C-MAX     1.6 TDCi
#  10 Focus C-MAX     1.6 TDCi
#  11 Focus C-MAX     1.6 TDCi
#  12    S-Klasse      320 CDI
#  13    S-Klasse      320 CDI
#  14    S-Klasse      320 CDI

Je suppose que le type de véhicule est toujours à la fin et suit ce modèle: (1) groupe de caractères numériques (0 à 9 et point), par ex. 1.6 OU (2) combinaison de caractère numérique de groupe et groupe de tout autre caractère, séparés par un espace (par exemple 120 Multijet, 2.0 HDi)

MISE À JOUR : faites affaire avec 308 1.6i Flex et Cherokee 2.8 CRD 4x4

df$VEHICLE_TYPE <- gsub(".+ ([0-9.]+[a-z]?(?: [^ ]+)?(?: [^ ]+)?)$", "\\1", df$VEHICLE_TYPE)

# OR, simply grep "number" and everything after
# df$VEHICLE_TYPE <- gsub(".+ ([0-9.]+[a-z]? .+)$", "\\1", df$VEHICLE_TYPE)


> df

#          MODEL VEHICLE_TYPE
# 1         Bora          1.6
# 2       Ducato 120 Multijet
# 3       Ducato 120 Multijet
# 4        Astra     1.7 CDTI
# 5          406      2.0 HDi
# 6          406      2.0 HDi
# 7  Focus C-MAX     1.6 TDCi
# 8  Focus C-MAX     1.6 TDCi
# 9  Focus C-MAX     1.6 TDCi
# 10 Focus C-MAX     1.6 TDCi
# 11 Focus C-MAX     1.6 TDCi
# 12    S-Klasse      320 CDI
# 13    S-Klasse      320 CDI
# 14    S-Klasse      320 CDI
# 15         308    1.6i Flex
# 16    Cherokee  2.8 CRD 4x4
0
nurandi 26 janv. 2017 à 09:29

Je suppose que quelqu'un saura un moyen de faire cela avec regex d'une manière plus simple que celle-ci, mais puisque je suis un cancre regex, voici ma tentative. Fractionner par espace, puis tout réduire à partir de et après la première valeur «numérique».

library( magrittr )
df[['VEHICLE_TYPE']] %<>%
    strsplit( " " ) %>%
    sapply( function(x) paste(
        x[ grep( "[[:digit:]]", x )[1] : length(x) ],
        collapse = " " )
    )

Résultat

> df
# # A tibble: 14 × 2
# MODEL    VEHICLE_TYPE
# <chr>           <chr>
# 1         Bora             1.6
# 2       Ducato 15 120 Multijet
# 3       Ducato 15 120 Multijet
# 4        Astra        1.7 CDTI
# 5          406     406 2.0 HDi
# 6          406     406 2.0 HDi
# 7  Focus C-MAX        1.6 TDCi
# 8  Focus C-MAX        1.6 TDCi
# 9  Focus C-MAX        1.6 TDCi
# 10 Focus C-MAX        1.6 TDCi
# 11 Focus C-MAX        1.6 TDCi
# 12    S-Klasse         320 CDI
# 13    S-Klasse         320 CDI
# 14    S-Klasse         320 CDI

Ou, si vous préférez diviser par la dernière valeur numérique, au lieu de la première :

df[['VEHICLE_TYPE']] %<>%
    strsplit( " " ) %>%
    sapply( function(x) paste(
        x[ tail( grep( "[[:digit:]]", x ), 1 ) : length(x) ],
        collapse = " " )
    )

> df
# # A tibble: 14 × 2
# MODEL VEHICLE_TYPE
# <chr>        <chr>
# 1         Bora          1.6
# 2       Ducato 120 Multijet
# 3       Ducato 120 Multijet
# 4        Astra     1.7 CDTI
# 5          406      2.0 HDi
# 6          406      2.0 HDi
# 7  Focus C-MAX     1.6 TDCi
# 8  Focus C-MAX     1.6 TDCi
# 9  Focus C-MAX     1.6 TDCi
# 10 Focus C-MAX     1.6 TDCi
# 11 Focus C-MAX     1.6 TDCi
# 12    S-Klasse      320 CDI
# 13    S-Klasse      320 CDI
# 14    S-Klasse      320 CDI

EDIT: Si vous avez des lignes sans aucune valeur numérique, vous devrez peut-être un peu de bricolage supplémentaire:

df[['VEHICLE_TYPE']] %<>%
    strsplit( " " ) %>%
    sapply( function(x) paste(
        if( length( grep( "[[:digit:]]", x ) ) > 1L ) {
            x[ tail( grep( "[[:digit:]]", x ), 1 ) : length(x) ]
        } else { x },
        collapse = " " )
    )
1
rosscova 26 janv. 2017 à 09:49

Exemple avec regex

with s(id,model,type) as (
select 77,'Bora','Bora 1.6' from dual union all
select 79,'Ducato','Ducato 15 120 Multijet' from dual union all
select 80 ,'Ducato','Ducato 15 120 Multijet' from dual union all
select 87 ,'Astra','Astra 1.7 CDTI' from dual union all
select 88 ,'406','406 2.0 HDi' from dual union all
select 89 ,'406','406 2.0 HDi' from dual union all
select 90 ,'Focus C-MAX','Focus C-MAX 1.6 TDCi' from dual union all
select 91 ,'Focus C-MAX','Focus C-MAX 1.6 TDCi' from dual union all
select 92 ,'Focus C-MAX','Focus C-MAX 1.6 TDCi' from dual union all
select 93 ,'Focus C-MAX','Focus C-MAX 1.6 TDCi' from dual union all
select 94 ,'Focus C-MAX','Focus C-MAX 1.6 TDCi' from dual union all
select 97  ,'S-Klasse','S 320 CDI' from dual union all
select 98  ,'S-Klasse','S 320 CDI' from dual union all
select 99  ,'S-Klasse','S 320 CDI' from dual 
)
select regexp_substr(type,'\d+(\.\d+)?\s*\w*$') /*cut part with model*/
from s 
0
Michael Piankov 26 janv. 2017 à 06:26

Dans Oracle, vous pouvez utiliser les premier et deuxième groupes correspondants de l'expression régulière ^(.*?)\s+(\d.*)$:

SELECT REGEXP_SUBSTR( vehicle_type, '^(.*?)\s+(\d.*)$', 1, 1, NULL, 1 )
         AS model,
       REGEXP_SUBSTR( vehicle_type, '^(.*?)\s+(\d.*)$', 1, 1, NULL, 2 )
         AS vehicle_type
FROM   your_table;
0
MT0 26 janv. 2017 à 10:15