2015-01-15 3 views
4

У меня есть кадр данных с двумя столбцами: первый столбец содержит группу, к которой принадлежит каждый человек, а второй идентификатор человека. Смотрите ниже:Создайте новый столбец в фрейме данных: индекс в группе (не уникален между группами)

df <- data.frame(group=c('G1','G1','G1','G1','G2','G2','G2','G2'), 
     indiv=c('indiv1','indiv1','indiv2','indiv2','indiv3', 
       'indiv3','indiv4','indiv4')) 

    group indiv 
1  G1 indiv1 
2  G1 indiv1 
3  G1 indiv2 
4  G1 indiv2 
5  G2 indiv3 
6  G2 indiv3 
7  G2 indiv4 
8  G2 indiv4 

Я хотел бы создать новый столбец в моем кадре данных (сохраняя длинный формат) с индексом каждого индивида в группе, то есть:

group indiv Ineed 
1  G1 indiv1  1 
2  G1 indiv1  1 
3  G1 indiv2  2 
4  G1 indiv2  2 
5  G2 indiv3  1 
6  G2 indiv3  1 
7  G2 indiv4  2 
8  G2 indiv4  2 

У меня есть пробовал с методами data.table .N или .GRP, без успеха (хорошая работа на data.table, кстати!).

Любая помощь очень ценится!

ответ

4

Вы можете использовать новую функцию rleid здесь (с версией развития у> = 1.9.5)

setDT(df)[, Ineed := rleid(indiv), group][] 
# group indiv Ineed 
# 1: G1 indiv1  1 
# 2: G1 indiv1  1 
# 3: G1 indiv2  2 
# 4: G1 indiv2  2 
# 5: G2 indiv3  1 
# 6: G2 indiv3  1 
# 7: G2 indiv4  2 
# 8: G2 indiv4  2 

Или вы могли бы преобразовать факторы (для того, чтобы создать уникальные группы), а затем преобразовать их обратно на числовой (если вы используете CRAN стабильную версию V < = 1.9.4)

setDT(df)[, Ineed := as.numeric(factor(indiv)), group][] 
# group indiv Ineed 
# 1: G1 indiv1  1 
# 2: G1 indiv1  1 
# 3: G1 indiv2  2 
# 4: G1 indiv2  2 
# 5: G2 indiv3  1 
# 6: G2 indiv3  1 
# 7: G2 indiv4  2 
# 8: G2 indiv4  2 
+0

@DavidArenburg Хорошие варианты. Я забыл про метод 'as.numeric (factor'. Не знал о' rleid' – akrun

+0

@akrun 'rleid' является одной из 5 новых функций, добавленных Аруном всего неделю назад. –

4

в 1.9.5 (текущая версия разработки), функция frankfrankv) экспортируются. При том, что вы можете сделать:

require(data.table) ## 1.9.5+ 
setDT(df)[, col := frank(indiv, ties.method="dense"), by=group] 
df 
# group indiv col 
# 1: G1 indiv1 1 
# 2: G1 indiv1 1 
# 3: G1 indiv2 2 
# 4: G1 indiv2 2 
# 5: G2 indiv3 1 
# 6: G2 indiv3 1 
# 7: G2 indiv4 2 
# 8: G2 indiv4 2 

Вы можете установить его, следуя инструкциям here.

2

Другой вариант использования base R

df$Ineed <- with(df, ave(as.numeric(indiv), group, 
        FUN=function(x) cumsum(!duplicated(x)))) 
df 
# group indiv Ineed 
#1 G1 indiv1  1 
#2 G1 indiv1  1 
#3 G1 indiv2  2 
#4 G1 indiv2  2 
#5 G2 indiv3  1 
#6 G2 indiv3  1 
#7 G2 indiv4  2 
#8 G2 indiv4  2 

The data.table версия будет

setDT(df)[, Ineed := cumsum(!duplicated(indiv)), group][] 
Смежные вопросы