2016-05-16 2 views
2

У меня есть большой кадр данных с группами и подгруппами. Я хотел бы определить индекс подгруппы в каждой группе, как показано в колонке OUTPUT следующего кадра данных:Определить индекс подгруппы

df <- data.frame(
    Group = factor(c("A","A","A","A","A","B","B","B","B")), 
    Subgroup = factor(c("a","a","b","b","b","a","a","b","b")), 
    OUTPUT = c(1,1,2,2,2,1,1,2,2) 
) 

Я пробовал несколько вариантов с без какого-либо успеха. Я хотел бы работать с dplyr, но я не уверен, как это сделать. Следующий код возвращает неожиданный результат.

require(dplyr) 

df <- df %>% 
    group_by(Group) %>% 
    mutate(
    OUTPUT_2 = dplyr::id(Subgroup) 
) 

#df 
# Group Subgroup OUTPUT_2 
# (fctr) (fctr) (int) 
#1  A  a  8 
#2  A  a  8 
#3  A  b  8 
#4  A  b  8 
#5  A  b  8 
#6  B  a  4 
#7  B  a  4 
#8  B  b  4 
#9  B  b  4 

У меня такое чувство, что я рядом, но не добираюсь туда. Может ли кто-нибудь помочь?

+1

ли вам нужно что-то вроде ' as.numeric (Подгруппа) '? – aosmith

ответ

2

Мы можем использовать factor маршрут с dplyr

library(dplyr) 
df %>% 
    group_by(Group) %>% 
    mutate(OUTPUT = as.numeric(factor(Subgroup, levels= unique(Subgroup)))) 
# Group Subgroup OUTPUT 
# <fctr> <fctr> <dbl> 
#1  A  a  1 
#2  A  a  1 
#3  A  b  2 
#4  A  b  2 
#5  A  b  2 
#6  B  a  1 
#7  B  a  1 
#8  B  b  2 
#9  B  b  2 

Или другой вариант match с unique элементами «Подгруппа» после того, как группировка по «Группа»

df %>% 
    group_by(Group) %>% 
    mutate(OUTPUT = match(Subgroup, unique(Subgroup))) 
# Group Subgroup OUTPUT 
# <fctr> <fctr> <int> 
#1  A  a  1 
#2  A  a  1 
#3  A  b  2 
#4  A  b  2 
#5  A  b  2 
#6  B  a  1 
#7  B  a  1 
#8  B  b  2 
#9  B  b  2 
+1

очень приятно, большое вам спасибо! Вы принимаете, потому что это просто и на самом деле вовлекает dplyr, как я надеялся, что это будет :-) – Ratnanil

1
library(data.table) 
dt = as.data.table(df) # or setDT to convert in place 

unique(dt[, .(Group, Subgroup)])[, idx := 1:.N, by = Group][dt, on = c('Group', 'Subgroup')] 
# Group Subgroup idx OUTPUT 
#1:  A  a 1  1 
#2:  A  a 1  1 
#3:  A  b 2  2 
#4:  A  b 2  2 
#5:  A  b 2  2 
#6:  B  a 1  1 
#7:  B  a 1  1 
#8:  B  b 2  2 
#9:  B  b 2  2 

Перевод на dplyr должен быть простым.


Другой метод, следуя идею использования факторов от комментариев aosmith, является:

dt[, idx := as.integer(factor(Subgroup, unique(Subgroup))), by = Group][] 

Это создаст фактор с правильным уровнем в группу, которая является индексирования вы после этого.

2

Вот решение с data.table без агрегации:

dt[order(Subgroup), Output := cumsum(!duplicated(Subgroup)) , by = .(Group)] 

Это будет гораздо быстрее по сравнению с методами, основанными на агрегацию.

+0

это не будет работать, если элементы подгруппы перетасовываются вокруг - например. измените 'dt [6, Subgroup: = 'b']' на данные OP и повторите попытку – eddi

+0

@eddi, это правда, но оно легко разрешимо с помощью 'setkey' – Bulat

+2

Булат, это правда, но даже лучше было бы иметь ' order (Subgroup) 'в аргументе' i', который не нарушает первоначальный порядок 'dt' * и *, очень эффективен, поскольку он позволяет избежать переупорядочения (что дорого). – Arun

Смежные вопросы