r语言 - 使用 tidyr::extract 正则表达式将字符串分成几列



我正在尝试使用R中的正则表达式将字符串向量分解为多个变量,最好是使用tidyr::extract命令以dplyr-tidyr方式。对于矢量波纹管中的指示:

sasdic <- data.frame(a=c(
  '@1   ANO_CENSO   5.  /*Ano do Censo*/',
  '@71  TP_SEXO $Char1. /*Sexo*/',
  '@72  TP_COR_RACA $Char1. /*Cor/raça*/',
  '@74  FK_COD_PAIS_ORIGEM  4.  /*Código País de origem*/' )) 

我想要:

  • 第一个数字 ([0-9]+) 转到变量 "int_pos"
  • 由下行 ([a-zA-Z_]+) 连接的变量名称,用于转到变量 "var_name"
  • 第二个数字或术语 $Char 1(可以是 $Char 2 等)转到 var "x"。我想([0-9]+|$Char[0-9]+)可以选择这个吗?
  • 最后,无论"/* .../"转到变量"标签"(不知道正则表达式)。所有其他中间字符(应不考虑空格、"."、"/"、"

这将是结果

d <- data.frame(int_pos=c(1,72,72,74),
                var_name=c('ANO_CENSO','TP_SEXO','TP_COR_RACA','FK_COD_PAIS_ORIGEM'),
                x=c('5','Chart1','$Char1','4'),
                label=c('Ano do Censo','Sexo','Cor/raça','Código País de origem') )

我试图为此构造一个正则表达式。这是我到目前为止得到的:

sasdic %>% extract(a, c('int_pos','var_name','x','label'), 
                   "([0-9]+)([a-zA-Z_]+)([0-9]+|$Char[0-9]+)(something to get the label") 
             -> d

上面的正则表达式不完整。另外,我不知道在提取命令语法中明确说明哪些部分是要恢复的,哪些部分是要省略的。

在所使用的正则表达式中,我们再匹配一个标点字符([[:punct:]]+),即 @捕获数字部分((\d+) - 这将是我们感兴趣的第一列),然后是一个或多个空格(\s+),然后是第二个捕获组(\S+ - 一个或多个非空格字符,即第一行的"ANO_CENSO"),然后是空格(\s+),然后我们捕获第三组(([[:alum:]$]+) - 即一个或多个包含字母数字以及$的字符至于匹配$Char1),接下来我们匹配一个或多个不是字母的字符([^A-Za-z]+ - 这应该去掉空格和*),最后一部分我们捕获一个或多个不*字符(([^*]+) .

sasdic %>% 
      extract(a, into=c('int_pos', 'var_name', 'x', 'label'),
   "[[:punct:]](\d+)\s+(\S+)\s+([[:alnum:]$]+)[^A-Za-z]+([^*]+)")
#  int_pos           var_name      x                 label
#1       1          ANO_CENSO      5          Ano do Censo
#2      71            TP_SEXO $Char1                  Sexo
#3      72        TP_COR_RACA $Char1              Cor/raça
#4      74 FK_COD_PAIS_ORIGEM      4 Código País de origem

这是另一个选项,尽管它使用 data.table 包而不是 tidyr:

library(data.table)
setDT(sasdic)
# split label
sasdic[, c("V1","label") := tstrsplit(a, "/\*|\*/")]                   
# remove leading "@", split remaining parts
sasdic[, c("int_pos","var_name","x") := tstrsplit(gsub("^@","",V1)," +")]
# remove unneeded columns
sasdic[, c("a","V1") := NULL]                                            
sasdic
#                    label int_pos           var_name       x
# 1:          Ano do Censo       1          ANO_CENSO      5.
# 2:                  Sexo      71            TP_SEXO $Char1.
# 3:              Cor/raça      72        TP_COR_RACA $Char1.
# 4: Código País de origem      74 FK_COD_PAIS_ORIGEM      4.

这假设"其余部分"(标签除外)是空格分隔的。


这也可以在一个块中完成(这就是我会做的):

sasdic[, c("a","label","int_pos","var_name","x") := {
  x   = tstrsplit(a, "/\*|\*/")
  x1s = tstrsplit(gsub("^@","",x[[1]])," +")
  c(list(NULL), x1s, x[2])
}]

您可以使用包解胶

library(unglue)
unglue_unnest(sasdic, a, "@{int_pos}{=\s+}{varname}{=\s+}{x}.{=\s+}/*{label}*/")
#>   int_pos            varname      x                       label
#> 1       1          ANO_CENSO      5                Ano do Censo
#> 2      71            TP_SEXO $Char1                        Sexo
#> 3      72        TP_COR_RACA $Char1                 Cor/ra<e7>a
#> 4      74 FK_COD_PAIS_ORIGEM      4 C<f3>digo Pa<ed>s de origem

最新更新