R将列中的特定文本提取到多列中
R Extract specific text from column into multiple columns
我有一个以这种格式从网络导出的数据框
id vals
1 {7,12,58,1}
2 {1,2,5,7}
3 {15,12}
我想像这样只将数字(忽略卷曲和逗号)提取到多个列中
id val_1 val_2 val_3 val_4 val_5
1 7 12 58 1
2 1 2 5 7
3 15 12
尽管我们得到的最大值是 4,但我希望始终达到值 val_5。
谢谢!
我们可以为此使用 str_extract_all
:
library(dplyr)
library(stringr)
df %>%
mutate(vals = str_extract_all(vals, '\d+', ''))
或@akrun 在评论中建议
df %>%
mutate(vals = str_extract_all(vals, '\d+', '')) %>%
do.call(data.frame, .)
id vals.1 vals.2 vals.3 vals.4
1 1 7 12 58 1
2 2 1 2 5 7
3 3 15 12 <NA> <NA>
数据:
df <- structure(list(id = 1:3, vals = c("{7,12,58,1}", "{1,2,5,7}",
"{15,12}")), class = "data.frame", row.names = c(NA, -3L))
另一个可能的 tidyverse
选项,我们删除大括号,然后分隔 ,
上的行,然后转向宽格式。然后,我们可以根据列名中的最大值(在本例中为 4)创建附加列(使用 tibble
中的 add_column
),然后可以创建 val_5
。
library(tidyverse)
df %>%
mutate(vals = str_replace_all(vals, "\{|\}", "")) %>%
separate_rows(vals, sep=",") %>%
group_by(id) %>%
mutate(ind = row_number()) %>%
pivot_wider(names_from = ind, values_from = vals, names_prefix = "val_") %>%
add_column(!!(paste0("val_", parse_number(names(.)[ncol(.)])+1)) := NA)
输出
id val_1 val_2 val_3 val_4 val_5
1 1 7 12 58 1 NA
2 2 1 2 5 7 NA
3 3 15 12 <NA> <NA> NA
数据
df <- read.table(text = "id vals
1 {7,12,58,1}
2 {1,2,5,7}
3 {15,12} ", header = T)
使用data.table
library(data.table)
library(stringi)
result <- setDT(df)[, stri_match_all_regex(vals, '\d+')[[1]], by=.(id)]
result[, item:=paste('val', 1:.N, sep='_'), by=.(id)] # defines column names
dcast(result, id~item, value.var = 'V1') # convert from long to wide
## id val_1 val_2 val_3 val_4
## 1: 1 7 12 58 1
## 2: 2 1 2 5 7
## 3: 3 15 12 <NA> <NA>
我有一个以这种格式从网络导出的数据框
id vals
1 {7,12,58,1}
2 {1,2,5,7}
3 {15,12}
我想像这样只将数字(忽略卷曲和逗号)提取到多个列中
id val_1 val_2 val_3 val_4 val_5
1 7 12 58 1
2 1 2 5 7
3 15 12
尽管我们得到的最大值是 4,但我希望始终达到值 val_5。
谢谢!
我们可以为此使用 str_extract_all
:
library(dplyr)
library(stringr)
df %>%
mutate(vals = str_extract_all(vals, '\d+', ''))
或@akrun 在评论中建议
df %>%
mutate(vals = str_extract_all(vals, '\d+', '')) %>%
do.call(data.frame, .)
id vals.1 vals.2 vals.3 vals.4
1 1 7 12 58 1
2 2 1 2 5 7
3 3 15 12 <NA> <NA>
数据:
df <- structure(list(id = 1:3, vals = c("{7,12,58,1}", "{1,2,5,7}",
"{15,12}")), class = "data.frame", row.names = c(NA, -3L))
另一个可能的 tidyverse
选项,我们删除大括号,然后分隔 ,
上的行,然后转向宽格式。然后,我们可以根据列名中的最大值(在本例中为 4)创建附加列(使用 tibble
中的 add_column
),然后可以创建 val_5
。
library(tidyverse)
df %>%
mutate(vals = str_replace_all(vals, "\{|\}", "")) %>%
separate_rows(vals, sep=",") %>%
group_by(id) %>%
mutate(ind = row_number()) %>%
pivot_wider(names_from = ind, values_from = vals, names_prefix = "val_") %>%
add_column(!!(paste0("val_", parse_number(names(.)[ncol(.)])+1)) := NA)
输出
id val_1 val_2 val_3 val_4 val_5
1 1 7 12 58 1 NA
2 2 1 2 5 7 NA
3 3 15 12 <NA> <NA> NA
数据
df <- read.table(text = "id vals
1 {7,12,58,1}
2 {1,2,5,7}
3 {15,12} ", header = T)
使用data.table
library(data.table)
library(stringi)
result <- setDT(df)[, stri_match_all_regex(vals, '\d+')[[1]], by=.(id)]
result[, item:=paste('val', 1:.N, sep='_'), by=.(id)] # defines column names
dcast(result, id~item, value.var = 'V1') # convert from long to wide
## id val_1 val_2 val_3 val_4
## 1: 1 7 12 58 1
## 2: 2 1 2 5 7
## 3: 3 15 12 <NA> <NA>