Присвоение идентификатора группы с помощью ddply

Довольно простой вопрос производительности от новичка 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

Хотя это хорошо работает для фреймов данных с относительно небольшим количеством строк или небольшим количеством групп, я столкнулся с проблемами производительности с большими наборами данных ( > 100000 строк), которые имеют много уникальных групп.

Любые предложения по улучшению скорости этой задачи? Возможно, с экспериментальной idata.frame() plyr? Или я все об этом говорю не так?

Заранее спасибо за помощь.

2 ответа

Решение

Попробуйте использовать id функция (также в plyr):

df$id <- id(df[c("st.num", "st.name")], drop = TRUE)

Обновить:

id функция считается устаревшей, начиная с версии 0.5.0 dplyr. Функция 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())
Другие вопросы по тегам