Я хотел бы сопоставить последнее вхождение «,» в строке, чтобы иметь возможность правильно separate
столбца.
Образец данных
tibble(
name = c("John", "James"),
company_num = c("Apple, Inc, 1000",
"Microsoft, 1200")
)
Желаемый результат:
# A tibble: 2 x 3
name company num
<chr> <chr> <dbl>
1 John Apple, Inc 1000
2 James Microsoft 1200
Что я пробовал
df %>%
separate(col = company_num,
into = c("company", "num"),
sep = ", ")
Я уверен, что здесь есть однострочное решение tidyverse, но вот базовый метод R:
# Get location of last comma
widths <- regexpr(",[^,]*$", df$company_num)
# Treat company_num as fixed width format file
df[c("Company", "Number")] <- read.fwf(
textConnection(df$company_num),
widths,
col.names = c("Company", "Number")
)
# Remove trailing comma/space
df$Company <- sub(",\\s?$", "", df$Company)
df
# A tibble: 2 x 4
# name company_num Company Number
# <chr> <chr> <chr> <int>
# 1 John Apple, Inc, 1000 Apple, Inc 1000
# 2 James Microsoft, 1200 Microsoft 1200
Если это должно быть tidyverse, то, в значительной степени заимствуя ответ на этот вопрос, вы можете сделать:
df |>
separate(
col = company_num,
into = c("company", "num"),
sep = "(?=[[:digit:]])", extra = "merge"
) |>
mutate(
company = sub(",\\s?$", "", company),
num = as.numeric(num)
)
# # A tibble: 2 x 3
# name company num
# <chr> <chr> <dbl>
# 1 John Apple, Inc 1000
# 2 James Microsoft 1200
С пакетом stringr
и регулярным выражением, в частности с положительным просмотром вперед или назад, с (?=lookahead)
и (?<=lookbehind)
.
Предполагая, что ваш фрейм данных или табличка df
:
df %>% mutate(
company = stringr::str_extract(company_num, ".*(?=,.*$)"),
# ↑ capture the text BEFORE a comma that is followed by one or several character ".*" at the end of the string "$"
num = stringr::str_extract(company_num, "(?<=, )[0-9]*$")) %>%
# ↑ capture one or several digits at the end of the string ($), preceded by ','
select(-company_num)
# ↑ drop the "company_num" col
Вы можете поставить лайк sub
.
data.frame(x[1],
company = sub(",[^,]*$", "", x$company_num),
num = sub(".*, ", "", x$company_num))
# name company num
#1 John Apple, Inc 1000
#2 James Microsoft 1200
Данные
x <- data.frame(name = c("John", "James"),
company_num = c("Apple, Inc, 1000", "Microsoft, 1200") )
С правильным регулярным выражением вы можете использовать separate
в одной строке.
Это помещает запятую в группу захвата (, )
, где за этой запятой не может стоять другая запятая (?!.*,)
.
library(tidyr)
library(dplyr)
df %>% separate(company_num, into = c("company", "num"), sep = "(, )(?!.*,)")
# A tibble: 2 × 3
name company num
<chr> <chr> <chr>
1 John Apple, Inc 1000
2 James Microsoft 1200
Большое спасибо! К сожалению, для спокойствия команд - мне очень нужно решение tidyverse/tidyr с
separate