将列分成单列并格式化条目
Separating column into single column and formating the entries
我有一个包含两列(id
和 info
)的庞大数据 table,我想将 separate/split 列 info
分成单列并格式化它们。
这是一个示例,我的数据 table 的条目如下所示:
id <- c(8750, 3048, 3593, 8475, 9921)
info <- c("[J/B][10,00/10,00][1,500/1,500][1,00]", "[J*/POP][0,00/0,00/0,00/0,00][2,210/2,210/2,210/2,210][1,50]", "S", "KEINE",
"[Q*/B][5,00/5,00][1,500/1,500][0,70]")
dt.test <- data.table(id, info)
dt.test
# id info
# 8750 [J/B][10,00/10,00][1,500/1,500][1,00]
# 3048 [J*/POP][0,00/0,00/0,00/0,00][2,210/2,210/2,210/2,210][1,50]
# 3593 S
# 8475 KEINE
# 9921 [Q*/B][5,00/5,00][1,500/1,500][0,70]
最后我需要一个 table,其中 info
列被分成六个单独的列(id
、type
、pBu
、 pBo
、zTBu
、zTBo
和 zV
) 并将它们格式化如下:
# id type pBu pBo zTBu zTBo zV
# 8750 J/B 10 10 1.50 1.50 1.0
# 3048 J*/POP 0 0 2.21 2.21 1.5
# 3593 S NA NA NA NA NA
# 8475 KEINE NA NA NA NA NA
# 9921 Q*/B 5 5 1.50 1.50 0.7
只是对开头的 info
专栏和结尾数据 table 的一些解释:
info
列中的所有逗号 ,
必须替换为点 .
(请参阅我的最终数据 table)。
- 第一个括号
[]
的输入定义了我的新type
列,此外,如果info
列用“S”或“KEINE”填充,这也必须是 type
列的条目。
- 第二个括号
[]
的输入定义了新列 pBu
(第一个元素)和 pBo
(最后一个元素)。
- 第三个括号
[]
的输入正在定义新列 zTBu
(第一个元素)和 zTBo
(最后一个元素)。
- 第四个括号
[]
的输入定义了zV
列。
- 当
type
列有条目“S”或“KEINE”时,则其余列必须填写 NA
s。
separate
括号
- 取第一部分和最后一部分(
mutate
和 word
)
- 从
,
到 .
(map_df
)
- 清理左括号(第二个
map_df
)
select
保持正确的顺序
列
library(tidyr)
library(stringr)
library(purrr)
dt.test %>%
separate(info, into = c('type', 'pBu - pBo', 'zTBu - zTBo', 'zV'),
sep = "\]|\/ " ,
remove = T) %>%
mutate('pBu' = word(`pBu - pBo`,1, sep = "\/"),
'pBo' = word(`pBu - pBo`,-1, sep = "\/"),
'pBu - pBo' = NULL,
'zTBu' = word(`zTBu - zTBo`,1, sep = "\/"),
'zTBo' = word(`zTBu - zTBo`,-1, sep = "\/"),
'zTBu - zTBo' = NULL) %>%
map_df(~ gsub(",", ".", .x)) %>%
map_df(~ gsub("\[", "", .x)) %>%
select(id , type, pBu, pBo, zTBu, zTBo, zV) ## %>% as.data.table
output
# A tibble: 5 x 7
id type pBu pBo zTBu zTBo zV
<chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 8750 J/B 10.00 10.00 1.500 1.500 1.00
2 3048 J*/POP 0.00 0.00 2.210 2.210 1.50
3 3593 S NA NA NA NA NA
4 8475 KEINE NA NA NA NA NA
5 9921 Q*/B 5.00 5.00 1.500 1.500 0.70
%>% as.data.table
最后,允许你保持data.table形式
您的代码可以组合内置函数 gsub
和 data.table
中的函数 tstrsplit
。如果您想按照评论 中的要求将缺失值设置为 0,您只需将函数 tstrsplit
中的参数 fill
设置为 0。假设您保留了 data.table 很大,请注意这个答案比@dy_by 提出的答案要快得多(在我的机器上大约快 23 倍)。
此解决方案需要 R 版本 4.1.0
cols <- c("type", "pBu", "pBo", "zTBu", "zTBo", "zV")
dt.test[, (cols) := gsub(",", ".", info, fixed=TRUE) |>
gsub(pattern="^\[|\]$", replacement="") |>
gsub(pattern="/[0-9./]+/", replacement="/") |>
tstrsplit("\]\[|/(?=\d)", perl=TRUE, type.convert=TRUE)]
dt.test[, !"info"]
# id type pBu pBo zTBu zTBo zV
# 1: 8750 J/B 10 10 1.50 1.50 1.0
# 2: 3048 J*/POP 0 0 2.21 2.21 1.5
# 3: 3593 S NA NA NA NA NA
# 4: 8475 KEINE NA NA NA NA NA
# 5: 9921 Q*/B 5 5 1.50 1.50 0.7
更新
这是要纳入评论的更新。它旨在用于早于 4.1.0
的 R 版本
dt.test[, (cols) := {x <- gsub(",", ".", info, fixed=TRUE)
x <- gsub("^\[|\]$", "", x)
x <- gsub("/[0-9./]+/", "/", x)
tstrsplit(x, "\]\[|/(?=\d)", perl=TRUE, type.convert=TRUE)}]
我有一个包含两列(id
和 info
)的庞大数据 table,我想将 separate/split 列 info
分成单列并格式化它们。
这是一个示例,我的数据 table 的条目如下所示:
id <- c(8750, 3048, 3593, 8475, 9921)
info <- c("[J/B][10,00/10,00][1,500/1,500][1,00]", "[J*/POP][0,00/0,00/0,00/0,00][2,210/2,210/2,210/2,210][1,50]", "S", "KEINE",
"[Q*/B][5,00/5,00][1,500/1,500][0,70]")
dt.test <- data.table(id, info)
dt.test
# id info
# 8750 [J/B][10,00/10,00][1,500/1,500][1,00]
# 3048 [J*/POP][0,00/0,00/0,00/0,00][2,210/2,210/2,210/2,210][1,50]
# 3593 S
# 8475 KEINE
# 9921 [Q*/B][5,00/5,00][1,500/1,500][0,70]
最后我需要一个 table,其中 info
列被分成六个单独的列(id
、type
、pBu
、 pBo
、zTBu
、zTBo
和 zV
) 并将它们格式化如下:
# id type pBu pBo zTBu zTBo zV
# 8750 J/B 10 10 1.50 1.50 1.0
# 3048 J*/POP 0 0 2.21 2.21 1.5
# 3593 S NA NA NA NA NA
# 8475 KEINE NA NA NA NA NA
# 9921 Q*/B 5 5 1.50 1.50 0.7
只是对开头的 info
专栏和结尾数据 table 的一些解释:
info
列中的所有逗号,
必须替换为点.
(请参阅我的最终数据 table)。- 第一个括号
[]
的输入定义了我的新type
列,此外,如果info
列用“S”或“KEINE”填充,这也必须是type
列的条目。 - 第二个括号
[]
的输入定义了新列pBu
(第一个元素)和pBo
(最后一个元素)。 - 第三个括号
[]
的输入正在定义新列zTBu
(第一个元素)和zTBo
(最后一个元素)。 - 第四个括号
[]
的输入定义了zV
列。 - 当
type
列有条目“S”或“KEINE”时,则其余列必须填写NA
s。
separate
括号- 取第一部分和最后一部分(
mutate
和word
) - 从
,
到.
(map_df
) - 清理左括号(第二个
map_df
) select
保持正确的顺序 列
library(tidyr)
library(stringr)
library(purrr)
dt.test %>%
separate(info, into = c('type', 'pBu - pBo', 'zTBu - zTBo', 'zV'),
sep = "\]|\/ " ,
remove = T) %>%
mutate('pBu' = word(`pBu - pBo`,1, sep = "\/"),
'pBo' = word(`pBu - pBo`,-1, sep = "\/"),
'pBu - pBo' = NULL,
'zTBu' = word(`zTBu - zTBo`,1, sep = "\/"),
'zTBo' = word(`zTBu - zTBo`,-1, sep = "\/"),
'zTBu - zTBo' = NULL) %>%
map_df(~ gsub(",", ".", .x)) %>%
map_df(~ gsub("\[", "", .x)) %>%
select(id , type, pBu, pBo, zTBu, zTBo, zV) ## %>% as.data.table
output
# A tibble: 5 x 7
id type pBu pBo zTBu zTBo zV
<chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 8750 J/B 10.00 10.00 1.500 1.500 1.00
2 3048 J*/POP 0.00 0.00 2.210 2.210 1.50
3 3593 S NA NA NA NA NA
4 8475 KEINE NA NA NA NA NA
5 9921 Q*/B 5.00 5.00 1.500 1.500 0.70
%>% as.data.table
最后,允许你保持data.table形式
您的代码可以组合内置函数 gsub
和 data.table
中的函数 tstrsplit
。如果您想按照评论 tstrsplit
中的参数 fill
设置为 0。假设您保留了 data.table 很大,请注意这个答案比@dy_by 提出的答案要快得多(在我的机器上大约快 23 倍)。
此解决方案需要 R 版本 4.1.0
cols <- c("type", "pBu", "pBo", "zTBu", "zTBo", "zV")
dt.test[, (cols) := gsub(",", ".", info, fixed=TRUE) |>
gsub(pattern="^\[|\]$", replacement="") |>
gsub(pattern="/[0-9./]+/", replacement="/") |>
tstrsplit("\]\[|/(?=\d)", perl=TRUE, type.convert=TRUE)]
dt.test[, !"info"]
# id type pBu pBo zTBu zTBo zV
# 1: 8750 J/B 10 10 1.50 1.50 1.0
# 2: 3048 J*/POP 0 0 2.21 2.21 1.5
# 3: 3593 S NA NA NA NA NA
# 4: 8475 KEINE NA NA NA NA NA
# 5: 9921 Q*/B 5 5 1.50 1.50 0.7
更新
这是要纳入评论的更新。它旨在用于早于 4.1.0
的 R 版本dt.test[, (cols) := {x <- gsub(",", ".", info, fixed=TRUE)
x <- gsub("^\[|\]$", "", x)
x <- gsub("/[0-9./]+/", "/", x)
tstrsplit(x, "\]\[|/(?=\d)", perl=TRUE, type.convert=TRUE)}]