Как мне векторизовать функцию ecdf в R?
У меня есть фрейм данных, который выглядит следующим образом:
set.seed(42)
data <- runif(1000)
utility <- sample(c("abc","bcd","cde","def"),1000,replace=TRUE)
stage <- sample(c("vwx","wxy","xyz"),1000,replace=TRUE)
x <- data.frame(data,utility,stage)
head(x)
data utility stage
1 0.9148060 def xyz
2 0.9370754 abc wxy
3 0.2861395 def xyz
4 0.8304476 cde xyz
5 0.6417455 bcd xyz
6 0.5190959 abc xyz
и я хочу создать кумулятивные функции распределения для уникальных комбинаций полезности и стадии. В моем реальном приложении я получу около 100 cdf, но эти случайные данные будут иметь 12 (4x3) уникальных комбинаций. Но я буду использовать каждый из этих cdf-файлов тысячи раз, поэтому я не хочу каждый раз вычислять cdf-файл на лету. Функция ecdf() работает именно так, как мне хотелось бы, за исключением того, что мне нужно было бы ее векторизовать. Следующий код не работает, но это суть того, что я пытаюсь сделать:
ecdf_multiple <- function(x)
{
i=0
utilities <- levels(x$utilities)
stages <- levels(x$stages)
for(utility in utilities)
{
for(stage in stages)
{
i <- i + 1
y <- ecdf(x[x$utilities == utility & x$stage == stage,1])
# calculate ecdf for the unique util/stage combo
z[i] <- list(y,utility,stage)
# then assign it to a data element (list, data frame, json, whatever) note-this doesn't actually work
}
}
z # return value
}
поэтому после запуска ecdf_multiple и присвоения его переменной я бы как-то ссылался на эту переменную, передавая значение (для которого я хотел cdf), утилиту и этап.
Есть ли способ векторизовать функцию ecdf (или использовать / построить другую), чтобы я мог выводить несколько раз без необходимости генерировать распределения снова и снова?
------- Добавлено в ответ на превосходное предложение @Pascal.-------
Как можно расширить это до более общего случая принятия "n" измерений категорий? Это мой удар, основанный на примере двух измерений Паскаля. Обратите внимание, как я пытался присвоить "y":
set.seed(42)
data <- runif(1000)
utility <- sample(c("abc","bcd","cde","def"),1000,replace=TRUE)
stage <- sample(c("vwx","wxy","xyz"),1000,replace=TRUE)
openclose <- sample(c("open","close"),1000,replace=TRUE)
x <- data.frame(data,utility,stage,openclose)
numlabels <- length(names(x))-1
y <- split(x, list(x[,2:(numlabels+1)]))
l <- lapply(y,function(x) ecdf(x[,"data"]))
#execute
utility <- "abc"
stage <- "xyz"
openclose <- "close"
comb <- paste(utility, stage, openclose, sep = ".")
# call the function
l[[comb]](.25)
Во время назначения "y" выше, я получаю это сообщение об ошибке:
"Error in sort.list(y) : 'x' must be atomic for 'sort.list'
Have you called 'sort' on a list?"
1 ответ
Следующее может помочь:
# we create a list of criteria by excluding
# the first column of the data.frame
y <- split(x, as.list(x[,-1]))
l <- lapply(y, function(x) ecdf(x[,"data"]))
utility <- "abc"
stage <- "xyz"
comb <- paste(utility, stage, sep = ".")
l[[comb]](0.25)
# [1] 0.2613636
plot(l[[comb]])