用数字分隔一个字符串

时间:2017-01-26 04:42:56

标签: sql r regex oracle strsplit

我正在尝试按模型和引擎分隔我的列VEHICLE_TYPE。代码可以是普通的 SQL R 代码。

我的数据如下:

       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

我想收到这样的信息:

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

问题是,VEHICLE_TYPE可以有不同的长度和不同的空格数,我可以将它们分开。

我尝试使用 gsub 正则表达式,但没有工作,但 strsplit 有效。远离我真正想要的东西,我已经没有想法,现在需要一些帮助。

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

4 个答案:

答案 0 :(得分:1)

我猜测有人会用比这更简单的方式知道正则表达式的方法,但由于我是一个正则表达式,这是我的尝试。按空格拆分,然后折叠第一个“数字”值之后的所有内容。

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

结果

> 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

或者,如果您希望按 last 数值进行拆分,而不是 first

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

编辑:如果你有一些没有任何数值的行,你可能需要一些额外的修补:

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 :(得分:0)

正则表达式的示例

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 

答案 2 :(得分:0)

以下是使用 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

我假设车辆类型总是在最后并且遵循这种模式:(1)数字字符组(0到9和点),例如1.6或(2)组合数字字符和组合任何其他字符,以空格分隔(例如120 Multijet2.0 HDi

更新:处理308 1.6i Flex和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

答案 3 :(得分:0)

在Oracle中,您可以使用正则表达式^(.*?)\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;