2015-06-25 3 views
1

У меня есть dataframe, который содержит информацию о нескольких категориях и некоторых связанных переменных. Она имеет вид:Индексирование подгрупп по отсортированным позициям в R dataframe

ID  category  sales score 
    227   A   109  21 
    131   A   410  24 
    131   A   509  1 
    123   B   2  61 
    545   B   19  5 
    234   C   439  328 
    654   C   765  41 

То, что я хотел бы сделать, это быть в состоянии ввести две новые колонки, salesRank и scoreRank, где найти индекс элемента в каждой категории, если бы они были заказаны sales и score, соответственно. Я могу решить общий случай, как это:

dF <- dF[order(-dF$sales),] 
dF$salesRank<-seq.int(nrow(dF)) 

, но это не учитывает категорий и до сих пор я решил только это, разбивая dataframe. То, что я хочу, приведет к следующему:

ID  category sales score salesRank scoreRank 
    227   A   109  21   3   2 
    131   A   410  24   2   1 
    131   A   509  1   1   3 
    123   B   2  61   2   1 
    545   B   19  5   1   2 
    234   C   439  328   2   1 
    654   C   765  41   1   2 

Большое спасибо!

ответ

3

Try:

library(dplyr) 
df %>% 
    group_by(category) %>% 
    mutate(salesRank = row_number(desc(sales)), 
     scoreRank = row_number(desc(score))) 

Что дает:

#Source: local data frame [7 x 6] 
#Groups: category 
# 
# ID category sales score salesRank scoreRank 
#1 227  A 109 21   3   2 
#2 131  A 410 24   2   1 
#3 131  A 509  1   1   3 
#4 123  B  2 61   2   1 
#5 545  B 19  5   1   2 
#6 234  C 439 328   2   1 
#7 654  C 765 41   1   2 

С помощью:

  • row_number(): эквивалентном rank(ties.method = "first")
  • min_rank(): эквивалентном rank(ties.method = "min")
  • desc(): преобразовать вектор в формат, который будет сортироваться по убыванию заказать.

Как @thelatemail отметил, для этого конкретного набора данных вы можете использовать min_rank() вместо row_number() который будет приходиться на связи в продажах/счет более адекватно:

> row_number(c(1,2,2,4)) 
#[1] 1 2 3 4 
> min_rank(c(1,2,2,4)) 
#[1] 1 2 2 4 
+1

Perfect - спасибо. В качестве последующего вопроса можно ли группировать по нескольким категориям? Я посмотрю документацию dplyr, чтобы попытаться ответить и на это тоже :) – anthr

+0

Да. вы можете сделать 'group_by (ID, category)' например. См. '? Group_by' –

+0

Вы также можете использовать' rank', который будет учитывать связи в продажах/оценке более подходящим образом. – thelatemail

3

Использование ave в базовый R с rank (- - это изменение рейтинга от низкого до высокого до высокого до низкого):

dF$salesRank <- with(dF, ave(-sales, category, FUN=rank)) 
#[1] 3 2 1 2 1 2 1 
dF$scoreRank <- with(dF, ave(-score, category, FUN=rank)) 
#[1] 2 1 3 1 2 1 2 
+1

Мне любопытно, есть ли причина, чтобы предпочесть это над 'внутри (df, { \t salesRank = ave (-sales, category, FUN = rank); \t scoreRank = ave (-score, category, FUN = rank) }) 'Кажется, что меньше набрав. – Frank

+1

@Frank - большая часть muchness, вы можете сделать все это в одном случае, и «внутри» довольно аккуратно. Это скопирует весь файл данных, хотя я думаю, что может быть менее эффективным, чем просто выполнять вычисления столбцов по столбцам. Который мог бы скопировать все это тоже ... Я не знаю. Не моя сильная сторона. – thelatemail

+0

@Frank, плюс в 'in', вам нужно сделать' <-' не '=' - вы могли бы использовать 'transform' с' = 'хотя – thelatemail

1

У меня только базовое решение R с tapply.

salesRank <- tapply(dat$sales, dat$category, order, decreasing = T) 
scoreRank <- tapply(dat$score, dat$category, order, decreasing = T) 

cbind(dat, salesRank = unlist(salesRank), scoreRank= unlist(scoreRank)) 

    ID category sales score salesRank scoreRank 
A1 227  A 109 21   3   2 
A2 131  A 410 24   2   1 
A3 131  A 509  1   1   3 
B1 123  B  2 61   2   1 
B2 545  B 19  5   1   2 
C1 234  C 439 328   2   1 
C2 654  C 765 41   1   2 
+4

Это зависит от 'dat', сортируемого по' category', правильно? – Frank

+2

@Frank прав - 'ave' предпочтительно' unlist (tapply()) 'как' tapply' сортирует результаты. Первоначальные данные необходимо сначала отсортировать. – thelatemail

+1

'tapply' - это первые функции, которые я думал, но я до сих пор новичок в R, я изучаю. @Frank. Я согласен с вами, большое спасибо за ваш комментарий, потому что на первый взгляд я не думал о случае несортированной «категории». – SabDeM