Довольно основной вопрос о производительности от новичка R. Я хотел бы присвоить идентификатор группы каждой строке в кадре данных уникальными комбинациями полей. Вот мой текущий подход:
> # An example data frame
> df <- data.frame(name=c("Anne", "Bob", "Chris", "Dan", "Erin"),
st.num=c("101", "102", "105", "102", "150"),
st.name=c("Main", "Elm", "Park", "Elm", "Main"))
> df
name st.num st.name
1 Anne 101 Main
2 Bob 102 Elm
3 Chris 105 Park
4 Dan 102 Elm
5 Erin 150 Main
>
> # A function to generate a random string
> getString <- function(size=10) return(paste(sample(c(0:9, LETTERS, letters), size, replace=TRUE), collapse=''))
>
> # Assign a random string for each unique street number + street name combination
> df <- ddply(df,
c("st.num", "st.name"),
function(x) transform(x, household=getString()))
> df
name st.num st.name household
1 Anne 101 Main 1EZWm4BQel
2 Bob 102 Elm xNaeuo50NS
3 Dan 102 Elm xNaeuo50NS
4 Chris 105 Park Ju1NZfWlva
5 Erin 150 Main G2gKAMZ1cU
В то время как это работает хорошо на кадры данных с относительно немногими строками или небольшим количеством групп, я сталкиваюсь с проблемами производительности с большими наборами данных (> 100 000 строк), которые имеют многие уникальные группы.
Какие-либо предложения для улучшения скорости этой задачи? Возможно с экспериментальным idata.frame plyr ()? Или я иду об этом неправильно?
Заранее спасибо за Вашу справку.
Попробуйте использовать функция id
(также в plyr):
df$id <- id(df[c("st.num", "st.name")], drop = TRUE)
Обновление:
Функция id
считается устаревшей, начиная с версии dplyr 0.5.0.
Функция group_indices
обеспечивает ту же функциональность.
Обязательно ли, чтобы идентификатор представлял собой случайную строку из 10 символов? Если нет, почему бы просто не склеить столбцы фрейма данных. Если идентификаторы должны быть одинаковой длины в символах, преобразовать коэффициенты в числовые, а затем вставить их вместе:
df$ID <- paste(as.numeric(df$st.num), as.numeric(df$st.name), sep = "")
Затем, если вам действительно нужно иметь идентификаторы из 10 символов, я бы сгенерировал только n идентификаторов и переименовал уровни идентификатора с ними
df$ID <- as.factor(df$ID)
n <- nlevels(df$ID)
getID <- function(n, size=10){
out <- {}
for(i in 1:n){
out <- c(paste(sample(c(0:9, LETTERS, letters), size, replace=TRUE), collapse=''))
}
return(out)
}
newLevels <- getID(n = n)
levels(df$ID) <- newLevels
Кроме того, вам не нужно использовать function (x)
с ddply таким образом с transform ()
. Этот код будет работать точно так же:
ddply(df, c("st.num", "st.name"), transform, household=getString())