нумерация по группам

Предположим, у нас есть следующая firebase database:

ID Shoot hit 1 10 2 1 9 3 1 8 1 2 10 8 2 8 8 2 11 10 2 7 2 3 9 2 4 6 6 4 6 5 . . 

И я хотел бы иметь его с номерами, назначенными в каждой группе, в этом случае для каждого идентификатора, например:

 ID Shoot hit number.in.group 1 10 2 1 1 9 3 2 1 8 1 3 2 10 8 1 2 8 8 2 2 11 10 3 2 7 2 4 3 9 2 1 4 6 6 1 4 6 5 2 . . 

Я мог бы сделать это легко, используя цикл. Что-то вроде этого будет работать:

 df$number.in.group = rep(1,nrow(df)) for(i in 2:nrow(df)) if(df$ID[i]==df$ID[i-1]){ df$number.in.group[i] = df$number.in.group[i-1] + 1 } 

Мой вопрос в том, есть ли какая-либо функция или более элегантный способ сделать это, кроме использования цикла?

Использование dplyr

 dat <- data.frame(ID = rep(1:3, c(2, 3, 5)), val = rnorm(10)) library(dplyr) dat %>% group_by(ID) %>% mutate(number.in.group = 1:n()) 

Если вам нужен один лайнер, что-то вроде

 df$number.in.group = unlist(lapply(table(df$ID),seq.int)) 

Вы можете просто использовать rle и sequence :

 dat <- read.table(text = "ID Shoot hit + 1 10 2 + 1 9 3 + 1 8 1 + 2 10 8 + 2 8 8 + 2 11 10 + 2 7 2 + 3 9 2 + 4 6 6 + 4 6 5",sep = "",header = TRUE) > sequence(rle(dat$ID)$lengths) [1] 1 2 3 1 2 3 4 1 1 2 

Действительно, я думаю, что sequence предназначена именно для этой цели.

 > dat$number.in.group <- ave(dat$ID,dat$ID, FUN=seq_along) > dat ID Shoot hit number.in.group 1 1 10 2 1 2 1 9 3 2 3 1 8 1 3 4 2 10 8 1 5 2 8 8 2 6 2 11 10 3 7 2 7 2 4 8 3 9 2 1 9 4 6 6 1 10 4 6 5 2 

Есть, вероятно, лучшие способы, но можно использовать наклейки на идентификаторах и бросить в функцию, которая возвращает последовательность.

 # Example data dat <- data.frame(ID = rep(1:3, c(2, 3, 5)), val = rnorm(10)) # Using tapply with a function that returns a sequence dat$number.in.group <- unlist(tapply(dat$ID, dat$ID, function(x){seq(length(x))})) dat 

что приводит к

 > dat ID val number.in.group 1 1 -0.454652118 1 2 1 -2.391824247 2 3 2 0.530832021 1 4 2 -1.671043812 2 5 2 -0.045261549 3 6 3 2.311162484 1 7 3 -0.525635803 2 8 3 0.008588811 3 9 3 0.078942033 4 10 3 0.324156111 5 
 df$number.in.group <- unlist(lapply(as.vector(unlist(rle(df$ID)[1])), function(x) 1:x)) 

Вот еще одно решение

 require(plyr) ddply(dat, .(ID), transform, num_in_grp = seq_along(hit)) 

Я сравнивал ваших собеседников, и IShouldBuyABoat является самым обещающим. Я обнаружил, что функция ave может применяться, даже если dataset не сортируется в соответствии с переменной группировки.

Рассмотрим dataset:

 dane<-data.frame(g1=c(-1,-2,-2,-2,-3,-3,-3,-3,-3), g2=c('reg','pl','reg','woj','woj','reg','woj','woj','woj')) 

Joran anwser и применил к моему примеру:

 > sequence(rle(as.character(dane$g2))$lengths) [1] 1 1 1 1 2 1 1 2 3 

Предложение Саймона Урбанека и его результаты:

 > unlist(lapply(table(dane$g2),seq.int)) pl reg1 reg2 reg3 woj1 woj2 woj3 woj4 woj5 1 1 2 3 1 2 3 4 5 

Код IShouldBuyABoat дает правильный ответ:

 > as.numeric(ave(as.character(dane$g1),as.character(dane$g1),FUN=seq_along)) [1] 1 1 2 3 1 2 3 4 5 
  • Изменение имени переменной в цикле for с использованием R
  • Программируемая версия подмножества - для оценки ее состояния при вызове из другой функции
  • Как изменить строку в R
  • Есть ли такой «colsd» в R?
  • Как я могу прерывать текущий код в R с помощью команды клавиатуры?
  • Создание вектора, разделенного запятыми
  • Какой самый полезный трюк?
  • Как создать пример данных из частных данных (заменяя имена переменных и уровни владельцами неинформативных мест)?
  • Преобразовать значения в столбце в имена строк в существующем кадре данных в R
  • Найдите, сколько раз повторяющиеся строки повторяются в кадре данных R
  • Как вы читаете в нескольких файлах .txt в R?
  • Давайте будем гением компьютера.