2015-10-26 1 views
2

Это продолжение вопроса:R: сравнить значение строки для значений группы, с условием

R data table: compare row value to group values

У меня сейчас:

x = data.table(id=c(1,1,1,1,1,1,1,1), price = c(10, 10, 12, 12, 12, 15, 
8, 11), subgroup = c(1, 1, 1, 1, 1, 1, 2, 2)) 

    id price subgroup 
1: 1 10  1 
2: 1 10  1 
3: 1 12  1 
4: 1 12  1 
5: 1 12  1 
6: 1 15  1 
7: 1  8  2 
8: 1 11  2 

и хотел бы вычислить количество строк с более низкими ценами на идентификатор, но только считая их в подгруппе 1.

Если я использую:

x[,cheaper := rank(price, ties.method="min")-1, by=id] 

результаты как:

> x 
    id price subgroup cheaper 
1: 1 10  1  1 # only 1 is cheaper (row 7) 
2: 1 10  1  1 # only 1 is cheaper (row 7) 
3: 1 12  1  4 # 4 frows are cheaper (row 1,2,7,8) 
4: 1 12  1  4 # etc 
5: 1 12  1  4 
6: 1 15  1  7 
7: 1  8  2  0 
8: 1 11  2  3 

, но я хотел бы результат быть:

> x 
    id price subgroup cheaper_in_subgroup_1 
1: 1 10  1  0 # nobody in subgroup 1 is cheaper 
2: 1 10  1  0 # nobody in subgroup 1 is cheaper 
3: 1 12  1  2 # only row 1 and 2 are cheaper in subgroup 1 
4: 1 12  1  2 
5: 1 12  1  2 
6: 1 15  1  5 
7: 1  8  2  0 # nobody in subgroup 1 is cheaper 
8: 1 11  2  2 # only row 1 and 2 are cheaper in subgroup 1 
+0

Я думаю, что ваша последняя строка неверна, поскольку вы должны сравнивать каждую подгруппу, нет? Я думал что-то вроде 'x [, дешевле: = sapply (цена, функция (x) sum (цена

+0

@DavidArenburg Нет. Я не хочу сравнивать в подгруппах. Я хочу сравнить все строки с подгруппой 1. Я знаю, что это не обычный способ, но это то, что мне нужно. – tucson

+1

Хорошо, это работает 'x [, дешевле: = sapply (цена, функция (x) сумма (цена [подгруппа == 1]

ответ

2

Там, наверное, более data.table иш способ достижения это, но здесь попытка с использованием vapply в каждом id

x[, cheaper := vapply(price, 
         function(x) sum(price[subgroup == 1L] < x), 
         FUN.VALUE = integer(1L)), 
       by = id] 
x 
# id price subgroup cheaper 
# 1: 1 10  1  0 
# 2: 1 10  1  0 
# 3: 1 12  1  2 
# 4: 1 12  1  2 
# 5: 1 12  1  2 
# 6: 1 15  1  5 
# 7: 1  8  2  0 
# 8: 1 11  2  2 
2

Вот еще один способ, используя небольшой трюк с качению присоединяется:

y = x[subgroup==1L, .N, keyby=.(id, price+1L)][, N := cumsum(N)][] 
# id price N 
# 1: 1 11 2 
# 2: 1 13 5 
# 3: 1 16 6 
x[, cheaper := y[x, N, roll=TRUE, rollends=FALSE, on=c("id", "price")]] 
# id price subgroup cheaper 
# 1: 1 10  1  NA 
# 2: 1 10  1  NA 
# 3: 1 12  1  2 
# 4: 1 12  1  2 
# 5: 1 12  1  2 
# 6: 1 15  1  5 
# 7: 1  8  2  NA 
# 8: 1 11  2  2 

Идея заключается в том, чтобы получить накопленную сумму для каждого id,price, но хранить его price+1L. Это приведет к значениям в x, получающим подсчет, соответствующий последнему наблюдению, при выполнении скользящего соединения.


PS: Если price не является целым числом типа, то он был бы price * (1 + eps) вместо price + 1L при получении y.

+1

Приятно, я пытался что-то сделать, используя скользящие соединения, но у меня не хватило мозгов, я думаю. –

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