Количество значений, разделенных запятой в символьной строке
У меня есть этот пример данных
d<-"30,3"
class(d)
У меня есть эти объекты символа в одном столбце в моем рабочем фрейме данных, и мне нужно определить, сколько у него чисел.
Я попытался использовать length(d)
, но он говорит 1
После поиска решения здесь я пробовал
eval(parse(text='d'))
as.numeric(d)
as.vector.character(d)
Но это все еще не работает.
Любой простой подход для решения этой проблемы?
Ответы
Ответ 1
Эти два подхода кажутся короткими, работают над векторами строк, не требуют затрат на явное построение разделительной строки и не используют никаких пакетов. Здесь d
- вектор строк, таких как d <- c("1,2,3", "5,2")
:
1) count.fields
count.fields(textConnection(d), sep = ",")
2) gregexpr
lengths(gregexpr(",", d)) + 1
Ответ 2
Вы можете использовать scan
.
v1 <- scan(text=d, sep=',', what=numeric(), quiet=TRUE)
v1
#[1] 30 3
Или используя stri_split
из stringi
. Это должно принимать как классы character
, так и factor
без прямого преобразования символа с помощью as.character
library(stringi)
v2 <- as.numeric(unlist(stri_split(d,fixed=',')))
v2
#[1] 30 3
Вы можете сделать count
с помощью base R
на
length(v1)
#[1] 2
или
nchar(gsub('[^,]', '', d))+1
#[1] 2
Визуализируйте regex
[^,]
![Regular expression visualization]()
Демоверсия Debuggex
Update
Если d
- это столбец в наборе данных df
и хочет подмножество строк с числом цифр равно 2
d<-c("30,3,5","30,5")
df <- data.frame(d,stringsAsFactors=FALSE)
df[nchar(gsub('[^,]', '',df$d))+1==2,,drop=FALSE]
# d
#2 30,5
Просто проверить
df[nchar(gsub('[^,]', '',df$d))+1==10,,drop=FALSE]
#[1] d
#<0 rows> (or 0-length row.names)
Ответ 3
Вот возможность
> as.numeric(unlist(strsplit("30,3", ",")))
# 30 3
Ответ 4
Вы также можете попробовать stringi
пакет stri_count_*
funcitons (должен быть очень эффектным)
library(stringi)
stri_count_regex(d, "\\d+")
## [1] 2
stri_count_fixed(d, ",") + 1
## [1] 2
stringr
пакет имеет аналогичную функциональность
library(stringr)
str_count(d, "\\d+")
## [1] 2
Update:
Если вы хотите подмножить набор данных по векторам длины 2, можете попробовать
df[stri_count_regex(df$d, "\\d+") == 2,, drop = FALSE]
# d
# 2 30,5
Или проще
subset(df, stri_count_regex(d, "\\d+") == 2)
# d
# 2 30,5
Обновление # 2
Здесь приведен пример, который иллюстрирует, почему следует учитывать использование внешних пакетов (ответ @rengis не был включен, поскольку он не отвечает на вопрос)
library(microbenchmark)
library(stringi)
d <- rep("30,3", 1e4)
microbenchmark( akrun = nchar(gsub('[^,]', '', d))+1,
GG1 = count.fields(textConnection(d), sep = ","),
GG2 = sapply(gregexpr(",", d), length) + 1,
DA1 = stri_count_regex(d, "\\d+"),
DA2 = stri_count_fixed(d, ",") + 1)
# Unit: microseconds
# expr min lq mean median uq max neval
# akrun 8817.950 9479.9485 11489.7282 10642.4895 12480.845 46538.39 100
# GG1 55451.474 61906.2460 72324.0820 68783.9935 78980.216 150673.72 100
# GG2 33026.455 43349.5900 60960.8762 51825.6845 72293.923 203126.27 100
# DA1 4730.302 5120.5145 6206.8297 5550.7930 7179.536 10507.09 100
# DA2 380.147 418.2395 534.6911 448.2405 597.259 2278.11 100