r - 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
逻辑是:
- ColA 在第一个逗号之前有字符串;
- ColB 包含第一个和第二个逗号之间的所有内容;
- ColD 在最后一个逗号后面有字符串;
- ColC 在中间部分有字符串(它可能包含额外的逗号)。
如何实现上面的逻辑?
编辑_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 将逗号视为分隔符的原因)。
解决方案
这是一种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"
用于捕获数字字符组将不再成功。
推荐阅读
- c# - 如何在VS C#中按下回车键时启用自动完成
- reactjs - 除了使用 cookie 通过 express 和 react 将请求-响应从后端传递到前端之外,还有其他解决方案吗?
- json - jq:添加嵌套数字?
- angular - Angular 8 NgFor 仅支持绑定到 Iterables,例如 Arrays error 和 Access Control Allow origin
- assembly - 如何通过获取指令类型细分来表征工作负载?
- oop - OCP 是否违反了 Clean Architecture 中的 SRP?
- c++ - Boost FFT 示例 - 编译时出错,这段代码在做什么?
- python - 协助在 Python 3 中使用文件
- windows - 如何解决 Windows 服务自动启动失败的问题
- swift - 如何在 Swift 中创建快速排序实现?