Разделение строк на число и строку (с пропусками) - PullRequest
6 голосов
/ 16 апреля 2019

Я пытаюсь разделить цифры и символы в столбце строк.До сих пор я использовал tidyr::separate для этого, но я сталкиваюсь с ошибками для «необычных» случаев.

Предположим, у меня есть следующие данные

df <- data.frame(c1 = c("5.5K", "2M", "3.1", "M"))

И я хочу получить фрейм данных со столбцами

data.frame(c2 = c("5.5", "2", "3.1", NA),
c3 = c("K", "M", NA, "M))

До сих пор я использовал tidyr::separate

df %>%
separate(c1, into =c("c2", "c3"), sep = "(?<=[0-9])(?=[A-Za-z])")

Но это работает только для первых трех случаев.Я понимаю, что это потому, что ?<=... и ?=... требуют присутствия регулярного выражения.Как изменить этот код, чтобы зафиксировать случаи, когда перед буквами отсутствуют цифры?Я тоже пытался использовать функцию extract, но безуспешно.

Редактировать: Полагаю, одним из решений было бы разбить это на

df$col2 <- as.numeric(str_extract(df$col1, "[0-9]+"))
df$col3 <- (str_extract(df$col1, "[aA-zZ]+"))

Но мне было любопытно, были ли другие способысправиться с этим.

Ответы [ 4 ]

2 голосов
/ 16 апреля 2019
extract(df, c1, into =c("c2", "c3"), "([\\.\\d]*)([a-zA-Z]*)")
#    c2 c3
# 1 5.5  K
# 2   2  M
# 3 3.1   
# 4      M

Вы можете использовать seperate просто таким способом, но должен быть более элегантный метод ..

df %>% separate(c1, into =c("c2", "c3"), sep = "(?=[A-Za-z])")
#    c2   c3
# 1 5.5    K
# 2   2    M
# 3 3.1 <NA>
# 4        M
1 голос
/ 16 апреля 2019

Мы можем использовать базу R sub для удаления символов и цифр соответственно, чтобы получить разные столбцы.

df$c2 <- sub("[A-Za-z]+", "", df$c1)
df$c3 <- sub("\\d*\\.?\\d*", "", df$c1)

df
#    c1  c2 c3
#1 5.5K 5.5  K
#2   2M   2  M
#3  3.1 3.1   
#4    M      M

Вы можете удалить столбец c1, если позже он не понадобится, выполнив df$c1 <- NULL.

0 голосов
/ 16 апреля 2019

Мы можем использовать extract от tidyr

library(tidyr)
extract(df, c1, into = c("c2", "c3"), "^([0-9.]*)([A-Z]*)",
        convert = TRUE, remove = FALSE)
#    c1  c2 c3
#1 5.5K 5.5  K
#2   2M 2.0  M
#3  3.1 3.1   
#4    M  NA  M

Или с read.csv из base R

read.csv(text= sub("^([0-9.]*)", "\\1,", df$c1), 
   header = FALSE, stringsAsFactors = FALSE, col.names = c("c2", "c3"))
0 голосов
/ 16 апреля 2019

Вы также можете использовать regex группирование \1 и \2. Это очень похоже на ответ @Ronak Shah и адаптировано к нему, но с группировкой регулярных выражений

# data
df <- data.frame(c1 = c("5.5K", "2M", "3.1", "M"))

# keep only numeric
df$c2 <- sub("(\\d*\\.?\\d*)([A-Za-z]*)", "\\1", df$c1)

# keep only alphabets
df$c3 <- sub("(\\d*\\.?\\d*)([A-Za-z]*)", "\\2", df$c1)
df[df == ""] = NA

df
#>     c1   c2   c3
#> 1 5.5K  5.5    K
#> 2   2M    2    M
#> 3  3.1  3.1 <NA>
#> 4    M <NA>    M

Создано в 2019-04-16 пакетом Представления (v0.2.1)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...