dww*_*dww 5 string r data.table
我有一个看起来像这样的data.table(dt)
# id value
# 1: 1 {1:3.2,2:14.2}
# 2: 2 {1:14.0,2:3.0}
# 3: 3 {1:3.4,2:3.9,3:0.1}
# 4: 4 {1:2.1}
Run Code Online (Sandbox Code Playgroud)
该value列包含值列表,其中每个值由其在列表中的位置(1,2,3 ...)开头,后跟a :,然后是值本身。列表值用逗号分隔,整个列表用大括号括起来{...}。
我想将其转换为长格式(dt.all),例如
# id N value
# 1: 1 1 3.2
# 2: 1 2 14.2
# 3: 2 1 14.0
# 4: 2 2 3.0
# 5: 3 1 3.4
# 6: 3 2 3.9
# 7: 3 3 0.1
# 8: 4 1 2.1
Run Code Online (Sandbox Code Playgroud)
各种失败的尝试包括:
stingr::str_extract(string = dt$value, pattern = "(?<=:).*(?=,)")
gsub(".*: *(.*?) *,.*", "\\1", dt$value)
gsubfn:strapplyc(dt$value, ":(.*?),", simplify = c)
Run Code Online (Sandbox Code Playgroud)
关于如何做到这一点的任何建议? data.table首选解决方案,但如果失败,将接受tidyverse或其他方法。
数据:
dt = structure(list(id = 1:4, value = c("{1:3.2,2:14.2}", "{1:14.0,2:3.0}",
"{1:3.4,2:3.9,3:0.1}", "{1:2.1}")), row.names = c(NA, -4L), class = c("data.table",
"data.frame"))
dt.all = structure(list(id = c(1L, 1L, 2L, 2L, 3L, 3L, 3L, 4L), N = c(1L,
2L, 1L, 2L, 1L, 2L, 3L, 1L), value = c(3.2, 14.2, 14, 3, 3.4,
3.9, 0.1, 2.1)), row.names = c(NA, -8L), class = c("data.table",
"data.frame"))
Run Code Online (Sandbox Code Playgroud)
使用tidyverse函数的一种方法是{}从字符串中删除引号(),用于str_extract_all获取冒号(:)之前和之后的数字以及unnest这些值。
library(dplyr)
dt %>%
mutate(value = gsub("\\{|\\}", "", value),
N = stringr::str_extract_all(value, "\\d+(?=:)"),
value = stringr::str_extract_all(value, "(?<=:)\\d+\\.\\d+")) %>%
tidyr::unnest(N, value)
# id N value
#1 1 1 3.2
#2 1 2 14.2
#3 2 1 14.0
#4 2 2 3.0
#5 3 1 3.4
#6 3 2 3.9
#7 3 3 0.1
#8 4 1 2.1
Run Code Online (Sandbox Code Playgroud)
我发现,如果我gsub习惯将项目编号括在引号中,那么可以使用将其解析为json表达式library(jsonlite)。
dt[, .(value = {v1 <- unlist(fromJSON(gsub("([0-9]+):", '"\\1":', value)))},
N = names(v1)),by=id]
# id value N
# 1: 1 3.2 1
# 2: 1 14.2 2
# 3: 2 14.0 1
# 4: 2 3.0 2
# 5: 3 3.4 1
# 6: 3 3.9 2
# 7: 3 0.1 3
# 8: 4 2.1 1
Run Code Online (Sandbox Code Playgroud)