我有一个包含非分隔字符串的1列数据表,如此
d1 = data.table(x = c("2728661941-1945", "2657461921-1925", "2786161921-1925"))
d1
#> x
#> 1: 2728661941-1945
#> 2: 2657461921-1925
#> 3: 2786161921-1925
我有另一个表格
的数据表dic = data.table(field = c("ID","group","year"),start=c(1,6,7), length=c(5,1,9))
dic
#> field start length
#> 1: ID 1 5
#> 2: group 6 1
#> 3: year 7 9
我想使用dic中的信息拆分数据表d1中的字符串,最后得到一个新形式的数据框
d2 = data.table(ID = c("27286", "26574", "27861"),
group = c(6, 6, 6),
year = c("1941-1945", "1921-1925", "1921-1925")
d2
#> ID group year
#> 1: 27286 6 1941-1945
#> 2: 26574 6 1921-1925
#> 3: 27861 6 1921-1925
我试过了
d2 = copy(d1)[,(dic$field) := transpose(
lapply(x, stri_sub, from = dic$start, length = dic$length))]
但是,下面的数据是列表形式,而不是表格形式。我希望能够将创建的字段称为列。
我必须承认我并不完全确定我在做什么,而且我不必为此使用数据表,但我无法想到另一种方法。我所拥有的最简单的数据集包含79个字符的字符串,并且将生成25个字段,因此我不希望单独拉出每个字段。
我希望这是有道理的。任何建议都表示赞赏。
答案 0 :(得分:3)
1)read.fwf 尝试read.fwf
。没有包使用。
read.fwf(textConnection(d1$x), dic$length, col.names = dic$field)
,并提供:
ID group year
1 27286 6 1941-1945
2 26574 6 1921-1925
3 27861 6 1921-1925
2)分开这也有效并给出了相同的答案:
library(tidyr)
d1 %>%
separate(x, sep = dic$start - 1, into = dic$field, remove = TRUE)
答案 1 :(得分:2)
regex在这里非常有用,特别是因为您可以通过编程方式定义要搜索和输出的模式
d1 %>%
mutate(x=gsub(paste0("(.{", dic$length, "})", collapse=""), paste0("\\", seq_along(dic$length), collapse=" "), x)) %>%
separate(x, into=dic$field, sep=" ")
# ID group year
# 1 27286 6 1941-1945
# 2 26574 6 1921-1925
# 3 27861 6 1921-1925
解释
# Pattern to search for
paste0("(.{", dic$length, "})", collapse="")
# "(.{5})(.{1})(.{9})"
# (.{5}) - group that contains any 5 characters - will be group 1
# (.{1}) - group that contains any 1 character - will be group 2
# (.{9}) - group that contains any 9 characters - will be group 3
# Pattern to output
paste0("\\", seq_along(dic$length), collapse=" ")
# "\\1 \\2 \\3"
# \\1 - output group 1
# \\2 - output group 2
# each group is separated by a space
使用tidyr::separate
将生成的以空格分隔的字符串拆分为不同的字段
答案 2 :(得分:2)
未使用c this line is a comment
a = 1 $ anything on a line after a dollar sign is a comment
表,但可以使用dic
中的extract
轻松完成此操作:
tidyr
<强>结果:强>
library(tidyr)
extract(d1, x, c("ID", "group", "year"), "^(.{5})(.{1})(.{9})$")
答案 3 :(得分:0)
使用dic
表作为参考:
library(dplyr)
breaks <- setNames(as.list(paste0("substr(x", ", ", dic$start, ", ", dic$start+dic$length-1, ")")), dic$field)
d1 %>%
mutate_(.dots = breaks)
答案 4 :(得分:0)
setNames(data.frame(do.call(rbind, lapply(d1$x, function(X) sapply(1:NROW(dic),
function(i) c(substring(X, dic$start[i], dic$start[i] + dic$length[i])))))), dic$field)
# ID group year
#1 272866 61 1941-1945
#2 265746 61 1921-1925
#3 278616 61 1921-1925
答案 5 :(得分:0)
我们可以使用基础R中的strcapture
函数来技术上捕获字符串。我们将在已预定义的数据框中输入它。
strcapture("(\\d{5})(\\d)(.*)",d1$x,data.frame(Id=numeric(),group=numeric(),year=character()))
Id group year
1 27286 6 1941-1945
2 26574 6 1921-1925
3 27861 6 1921-1925
说明:(\\d{5})
捕获前5位数字,然后(\\d)
捕获下一个数字,(.*)
捕获其他所有数字。