需要根据数字与非数字将字符串分成多个变量
Need to separate strings into multiple variables based on numeric versus non-numeric
我有一个只有一个变量的数据框。它看起来像这样:
df <- data.frame(c("25 Edgemont 52 Sioux County", "57 Burke 88 Papillion-LaVista South"))
为了提供更多背景信息,每个 observation/row 都是篮球比赛的比分。我想分成四个数据框列,将数字和团队名称分开。因此,例如,第一行在第一列中最终为“25”,在第二列中为 "Edgemont",在第三列中为“52”,在第四列中为苏城。
我尝试了以下和各种 SO 建议,但无法获得所需的结果:
df2 <- strsplit(gsub("([0-9]*)([a-z]*)([0-9]*)([a-z]*)", "\1 \2 \3 \4", df), " ")
1) 一个选项是 extract
从 tidyr
我们在开头提取一个或多个数字 ((\d+)
) (^
) 的字符串作为捕获组,后跟一个 space,然后是一个或多个带有 space 的字母字符,后跟一个 space,然后是一个或多个捕获组中的数字,后跟 space 和其余字符作为第 4 列
library(stringr)
library(dplyr)
library(tidyr)
df %>%
extract(col1, into = str_c('col', 1:4),
'^(\d+) ([A-Za-z ]+) (\d+) (.*)', convert = TRUE)
# col1 col2 col3 col4
#1 25 Edgemont 52 Sioux County
#2 57 Burke 88 Papillion-LaVista South
2) 或使用 tidyr
中的 separate
,我们在其中指定要在 space
处拆分的正则表达式环视
df %>%
separate(col1, into = str_c('col', 1:4), sep = '(?<=\d) | (?=\d)')
# col1 col2 col3 col4
#1 25 Edgemont 52 Sioux County
#2 57 Burke 88 Papillion-LaVista South
3) 或使用 data.table
中的 tstrsplit
library(data.table)
setDT(df)[, tstrsplit(col1, "(?<=\d) | (?=\d)", perl = TRUE)]
# V1 V2 V3 V4
#1: 25 Edgemont 52 Sioux County
#2: 57 Burke 88 Papillion-LaVista South
4) 或使用 base R
中的 read.csv
(未使用包 ...)
read.csv(text = gsub("(?<=\d) | (?=\d)", ",", df$col1,
perl = TRUE), header = FALSE)
# V1 V2 V3 V4
#1 25 Edgemont 52 Sioux County
#2 57 Burke 88 Papillion-LaVista South
5) 或使用 base R
中的 strsplit
(未使用包 ...)
type.convert(as.data.frame(do.call(rbind,
strsplit(as.character(df$col1), "(?<=\d) | (?=\d)",
perl = TRUE))), as.is = TRUE)
# V1 V2 V3 V4
#1 25 Edgemont 52 Sioux County
#2 57 Burke 88 Papillion-LaVista South
数据
df <- data.frame(col1 = c("25 Edgemont 52 Sioux County",
"57 Burke 88 Papillion-LaVista South"))
1) dplyr/tidyr 用分号替换每个数字,该数字和另一个分号,然后用分号分隔,加上可选的周围空格。
library(dplyr)
library(tidyr)
# input
df <- data.frame(V1 = c("25 Edgemont 52 Sioux County",
"57 Burke 88 Papillion-LaVista South"))
df %>%
mutate(V1 = gsub("(\d+)", ";\1;", V1)) %>%
separate(V1, c(NA, "No1", "Let1", "No2", "Let2"), sep = " *; *")
## No1 Let1 No2 Let2
## 1 25 Edgemont 52 Sioux County
## 2 57 Burke 88 Papillion-LaVista South
1a) read.table 我们可以使用与 (1) 中相同的 gsub
,然后使用 read.table
将其分开。没有使用包。
read.table(text = gsub("(\d+)", ";\1;", df$V1), sep = ";", as.is = TRUE,
strip.white = TRUE, col.names = c(NA, "No1", "Let1", "No2", "Let2"))[-1]
## No1 Let1 No2 Let2
## 1 25 Edgemont 52 Sioux County
## 2 57 Burke 88 Papillion-LaVista South
2) strcapture 我们可以使用来自 base R:
的 strcapture
proto <- list(No1 = integer(0), Let1 = character(0),
No2 = integer(0), Let2 = character(0))
strcapture("(\d+) (.*) (\d+) (.*)", df$V1, proto)
## No1 Let1 No2 Let2
## 1 25 Edgemont 52 Sioux County
## 2 57 Burke 88 Papillion-LaVista South
2a) read.pattern 我们可以使用 read.pattern 与 (2) 中相同的模式:
library(gsubfn)
read.pattern(text = format(df$V1), pattern = "(\d+) (.*) (\d+) (.*)",
col.names = c("No1", "Let1", "No2", "Let2"), as.is = TRUE, strip.white = TRUE)
## No1 Let1 No2 Let2
## 1 25 Edgemont 52 Sioux County
## 2 57 Burke 88 Papillion-LaVista South
我有一个只有一个变量的数据框。它看起来像这样:
df <- data.frame(c("25 Edgemont 52 Sioux County", "57 Burke 88 Papillion-LaVista South"))
为了提供更多背景信息,每个 observation/row 都是篮球比赛的比分。我想分成四个数据框列,将数字和团队名称分开。因此,例如,第一行在第一列中最终为“25”,在第二列中为 "Edgemont",在第三列中为“52”,在第四列中为苏城。
我尝试了以下和各种 SO 建议,但无法获得所需的结果:
df2 <- strsplit(gsub("([0-9]*)([a-z]*)([0-9]*)([a-z]*)", "\1 \2 \3 \4", df), " ")
1) 一个选项是 extract
从 tidyr
我们在开头提取一个或多个数字 ((\d+)
) (^
) 的字符串作为捕获组,后跟一个 space,然后是一个或多个带有 space 的字母字符,后跟一个 space,然后是一个或多个捕获组中的数字,后跟 space 和其余字符作为第 4 列
library(stringr)
library(dplyr)
library(tidyr)
df %>%
extract(col1, into = str_c('col', 1:4),
'^(\d+) ([A-Za-z ]+) (\d+) (.*)', convert = TRUE)
# col1 col2 col3 col4
#1 25 Edgemont 52 Sioux County
#2 57 Burke 88 Papillion-LaVista South
2) 或使用 tidyr
中的 separate
,我们在其中指定要在 space
df %>%
separate(col1, into = str_c('col', 1:4), sep = '(?<=\d) | (?=\d)')
# col1 col2 col3 col4
#1 25 Edgemont 52 Sioux County
#2 57 Burke 88 Papillion-LaVista South
3) 或使用 data.table
tstrsplit
library(data.table)
setDT(df)[, tstrsplit(col1, "(?<=\d) | (?=\d)", perl = TRUE)]
# V1 V2 V3 V4
#1: 25 Edgemont 52 Sioux County
#2: 57 Burke 88 Papillion-LaVista South
4) 或使用 base R
中的 read.csv
(未使用包 ...)
read.csv(text = gsub("(?<=\d) | (?=\d)", ",", df$col1,
perl = TRUE), header = FALSE)
# V1 V2 V3 V4
#1 25 Edgemont 52 Sioux County
#2 57 Burke 88 Papillion-LaVista South
5) 或使用 base R
中的 strsplit
(未使用包 ...)
type.convert(as.data.frame(do.call(rbind,
strsplit(as.character(df$col1), "(?<=\d) | (?=\d)",
perl = TRUE))), as.is = TRUE)
# V1 V2 V3 V4
#1 25 Edgemont 52 Sioux County
#2 57 Burke 88 Papillion-LaVista South
数据
df <- data.frame(col1 = c("25 Edgemont 52 Sioux County",
"57 Burke 88 Papillion-LaVista South"))
1) dplyr/tidyr 用分号替换每个数字,该数字和另一个分号,然后用分号分隔,加上可选的周围空格。
library(dplyr)
library(tidyr)
# input
df <- data.frame(V1 = c("25 Edgemont 52 Sioux County",
"57 Burke 88 Papillion-LaVista South"))
df %>%
mutate(V1 = gsub("(\d+)", ";\1;", V1)) %>%
separate(V1, c(NA, "No1", "Let1", "No2", "Let2"), sep = " *; *")
## No1 Let1 No2 Let2
## 1 25 Edgemont 52 Sioux County
## 2 57 Burke 88 Papillion-LaVista South
1a) read.table 我们可以使用与 (1) 中相同的 gsub
,然后使用 read.table
将其分开。没有使用包。
read.table(text = gsub("(\d+)", ";\1;", df$V1), sep = ";", as.is = TRUE,
strip.white = TRUE, col.names = c(NA, "No1", "Let1", "No2", "Let2"))[-1]
## No1 Let1 No2 Let2
## 1 25 Edgemont 52 Sioux County
## 2 57 Burke 88 Papillion-LaVista South
2) strcapture 我们可以使用来自 base R:
的strcapture
proto <- list(No1 = integer(0), Let1 = character(0),
No2 = integer(0), Let2 = character(0))
strcapture("(\d+) (.*) (\d+) (.*)", df$V1, proto)
## No1 Let1 No2 Let2
## 1 25 Edgemont 52 Sioux County
## 2 57 Burke 88 Papillion-LaVista South
2a) read.pattern 我们可以使用 read.pattern 与 (2) 中相同的模式:
library(gsubfn)
read.pattern(text = format(df$V1), pattern = "(\d+) (.*) (\d+) (.*)",
col.names = c("No1", "Let1", "No2", "Let2"), as.is = TRUE, strip.white = TRUE)
## No1 Let1 No2 Let2
## 1 25 Edgemont 52 Sioux County
## 2 57 Burke 88 Papillion-LaVista South