需要根据数字与非数字将字符串分成多个变量

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) 一个选项是 extracttidyr 我们在开头提取一个或多个数字 ((\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