首页 > 解决方案 > regexp R - 提取逗号之间的字符串

问题描述

因为我的 csv 文件已损坏,我正在使用以下命令将其读入 R:

dataDT <- data.table::fread(".../test.csv", sep = NULL)

它提供了一个数据集,例如:

dataDT <- data.table("ColA,ColB,ColC,ColD" = c("1,10,some text... , some text,,20190801",
                                               "2,22,some text... , some text,,20190801",
                                               "3,30,some text... , some text,,20170601"))
dataDT
> dataDT
                       ColA,ColB,ColC,ColD
1: 1,10,some text... , some text,,20190801
2: 2,22,some text... , some text,,20190801
3: 3,30,some text... , some text,,20170601

现在,我想要的是将每一行中的字符串拆分为 4 个新列

targetDT <- data.table(ColA = c(1,2,3), 
                       ColB = c(10,22,30), 
                       ColC = c("some text... , some text,", "some text... , some text,", "some text... , some text,"),
                       ColD = c("20190801","20190801",'20170601'))
targetDT
> targetDT
   ColA ColB                      ColC     ColD
1:    1   10 some text... , some text, 20190801
2:    2   22 some text... , some text, 20190801
3:    3   30 some text... , some text, 20170601

逻辑是:

如何实现上面的逻辑?

编辑_1:

敏感数据,抱歉我不能提供准确的数据。看起来像:

        ID,Code1,Project_Name,Report_Date
1:     123123,1, A & B,20100101
2:     1413,2, C, D and E,20120101
3: 53163,333, F, G,20140303
4: 23453,44,This is a name,20160801
5: 12645,555,5th test, to continue,20190501

因此,第一个逗号之前的所有内容肯定是数字,第一个和第二个逗号之间的所有内容也是如此。最后一个逗号之后的所有内容绝对是一个类似日期的 8 位数字。中间部分可以包含多个逗号但没有引号(我猜这就是 fread 将逗号视为分隔符的原因)。

标签: rregexdata.tablegsub

解决方案


这是一种regex模式,可让您替换与前导二和终端数值相邻的逗号字符,并将它们彼此分隔,并用空格分隔周围的文本。使用非空格字符进行分隔可能更安全,因为我的下一步是使用其中一个read.*函数或可能fread再次读取这些“行”。也许使用“|” 作为分隔符?

sub("(\\d+)[,](\\d+)[,](.+)[,](\\d+)$", 
    "\\1 \\2 '\\3' \\4", 
    dataDT$"ColA,ColB,ColC,ColD" )

[1] "1 10 'some text... , some text,' 20190801" "2 22 'some text... , some text,' 20190801"
[3] "3 30 'some text... , some text,' 20170601"

模式中的括号用于创建“捕获类”,并且在每种情况下,我都使用“\d+”模式“捕获”了任意数量的数字或小数分隔符。我还在替换模式上用单引号将文本(用“.+”捕获)括起来,因此第三列想要成为的“内部空间”不会被读取为分隔符。,等是对每个捕获类中捕获的字符的引用"\\1""\\2"按照它们在模式中出现的顺序排列。见?regex。但是,如果您使用不同的分隔符,则不需要单引号。

这是一个使用“|”的测试 作为一个sep.

fread(text =sub("(\\d+)[,](\\d+)[,](.+)[,](\\d+)", "\\1|\\2|'\\3'|\\4", dataDT$"ColA,ColB,ColC,ColD" ) ,sep="|")
   V1 V2                          V3       V4
1:  1 10 'some text... , some text,' 20190801
2:  2 22 'some text... , some text,' 20190801
3:  3 30 'some text... , some text,' 20170601

注意:如果您的数值有逗号或有前导或尾随货币,您需要更改您的示例,因为"\\d"用于捕获数字字符组将不再成功。


推荐阅读