Необходимо разделить строки на несколько переменных на основе числовых c по сравнению с нечисловыми - PullRequest
0 голосов
/ 26 января 2020

У меня есть фрейм данных с одной переменной. Это выглядит примерно так:

df <- data.frame(c("25 Edgemont 52 Sioux County", "57 Burke 88 Papillion-LaVista South"))

Чтобы обеспечить больше контекста, каждое наблюдение / строка представляет собой результат игры в баскетбол. Я хотел бы разделить на четыре столбца фрейма данных, который разделяет числа и названия команд. Так, например, первая строка будет иметь вид «25» в первом столбце, «Edgemont» во втором столбце, «52» в третьем столбце и «Sioux City» в четвертом столбце.

Я пробовал ниже и различные предложения SO, но не могу получить желаемые результаты:

df2 <- strsplit(gsub("([0-9]*)([a-z]*)([0-9]*)([a-z]*)", "\\1 \\2 \\3 \\4", df), " ")

Ответы [ 2 ]

1 голос
/ 26 января 2020

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 Мы можем использовать тот же gsub, что и в (1), но затем отделить его с помощью 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 Мы можем использовать strcapture из базы R:

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
0 голосов
/ 26 января 2020

1) Один из вариантов - extract из tidyr, где мы извлекаем одну или несколько цифр ((\\d+)) в начале (^) строки как группу захвата, затем через пробел, затем на один или несколько символов, которые представляют собой буквы с пробелом, затем пробел, затем одну или несколько цифр в группе захвата, за которыми следуют пробел и остальные символы в качестве 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) Или с separate из tidyr, где мы указываем регулярное выражение для разбиения в пространстве

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) Или используя tstrsplit из data.table

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) Или используя read.csv из base R (пакеты не используются ...)

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) Или с strsplit из base R (пакеты не используются ...)

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

data

df <- data.frame(col1 = c("25 Edgemont 52 Sioux County", 
             "57 Burke 88 Papillion-LaVista South"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...