2015-12-01 4 views
1

У меня есть таблица данных с ключом и около 1000 строк, два из которых установлены на ключ. Я хотел бы создать новую переменную с именем разницей, которая содержит разницу между числовыми строками, сгруппированными по ключу.Как рассчитать разницу в списке различных ключей?

Например, простые данные: ID и Закон устанавливаются в качестве ключевого

ID ValueDate Act Volume 
    1 2015-01-01 EUR  21 
    1 2015-02-01 EUR  22 
    1 2015-01-01 MAD  12 
    1 2015-02-01 MAD  11 
    2 2015-01-01 EUR  5 
    2 2015-02-01 EUR  7 
    3 2015-01-01 EUR  4 
    3 2015-02-01 EUR  2 
    3 2015-03-01 EUR  6 

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

ID ValueDate Act Volume Difference 
    1 2015-01-01 EUR  21 0 
    1 2015-02-01 EUR  22 1 
    1 2015-01-01 MAD  12 0 
    1 2015-02-01 MAD  11 -1 
    2 2015-01-01 EUR  5 0 
    2 2015-02-01 EUR  7 2 
    3 2015-01-01 EUR  4 0 
    3 2015-02-01 EUR  2 -2 
    3 2015-03-01 EUR  6 4 

Вот код для генерации тестовых данных:

dd <- data.table(ID = c(1,1,1,1,2,2,3,3,3), 
        ValueDate = c("2015-01-01", "2015-02-01", "2015-01-01","2015-02-01", "2015-01-01","2015-02-01","2015-01-01","2015-02-01","2015-03-01"), 
        Act = c("EUR","EUR","MAD","MAD","EUR","EUR","EUR","EUR","EUR"), 
        Volume=c(21,22,12,11,5,7,4,2,6)) 

набор ключ для таблицы:

setkey(dd, ID, Act) 

для просмотра данных:

> dd 
     ID ValueDate Act Volume 
    1 1 2015-01-01 EUR  21 
    2 1 2015-02-01 EUR  22 
    3 1 2015-01-01 MAD  12 
    4 1 2015-02-01 MAD  11 
    5 2 2015-01-01 EUR  5 
    6 2 2015-02-01 EUR  7 
    7 3 2015-01-01 EUR  4 
    8 3 2015-02-01 EUR  2 
    9 3 2015-03-01 EUR  6 

так, мы можем использовать функцию агрегата для вычисления разницы? или метод .SD для «подмножества данных», но я не знаю, как сделать вычисление разницы между двумя строками по группе, обратите внимание, что для некоторых групп число строк может быть другим, но у меня есть попробовал до использования для (i в 0: x), чтобы пересчитать разницу, но я не думаю, что это может быть хороший метод :(

+0

Всегда ли будет ровно две записи? Что вы хотите, если их нет? – Elin

+0

на самом деле не всегда будут две записи, это просто простой случай, некоторые из групп имеют больше записей – ZAWD

ответ

4

Если вы хотите явно использовать свой ключ, вы можете пройти key вызов к by аргумента

dd[, Difference := c(0L, diff(Volume)), by = key(dd)] 
dd 
# ID ValueDate Act Volume Difference 
# 1: 1 2015-01-01 EUR  21   0 
# 2: 1 2015-02-01 EUR  22   1 
# 3: 1 2015-01-01 MAD  12   0 
# 4: 1 2015-02-01 MAD  11   -1 
# 5: 2 2015-01-01 EUR  5   0 
# 6: 2 2015-02-01 EUR  7   2 
# 7: 3 2015-01-01 EUR  4   0 
# 8: 3 2015-02-01 EUR  2   -2 
# 9: 3 2015-03-01 EUR  6   4 

Или с помощью data.table v 1.9.6+ вы можете также использовать функцию shift

dd[, Difference := Volume - shift(Volume, fill = Volume[1L]), by = key(dd)] 
+0

Привет, @David Arenburg, спасибо за ваш ответ, я пробовал это раньше, но была ошибка, сказал Ошибка в ' [.данные.frame (dd,, ': =' (Разница, c (0L, diff (Volume))), by = key (dd)): неиспользуемый аргумент (by = key (dd)) – ZAWD

+0

Вы сказали, что 'dd' is таблица данных уже. Разве вы не запускали 'setkey (setDT (dd), ID, Act)' до этого? –

+1

ой! я нашел свою ошибку, вы правы, я просто сгенерировал данные с неправильным форматом, и теперь он отлично работает! Большое спасибо ! – ZAWD

2

Мы можем использовать dplyr. После группировки по 'ID', 'Act', мы создаем столбец «Difference» как разницу «Volume» и lag этой колонки.

library(dplyr) 
dd %>% 
    group_by(ID, Act) %>% 
    mutate(Difference = Volume-lag(Volume)) 

EDIT: Как упомянуто @DavidArenburg, заменив lag(Volume) на lag(Volume, default = Volume[1L]) даст 0 вместо NA для первого элемента в каждой группе.


Или с ave из base R, мы можем сделать diff и сцепить с 0 так, что длины одинаковы. diff возвращает вектор с длиной, меньшей длины исходного вектора.

with(dd, ave(Volume, ID, Act, FUN= function(x) c(0, diff(x))) 
+1

Возможно, вы можете использовать 'lag (Volume, default = Volume [1L])' для соответствия вывода OP. –

+1

@akrun, спасибо за ваш обмен! Я попробовал метод, который вы сказали, он отлично работает! – ZAWD

+0

@DavidArenburg У меня есть трудное время, чтобы эта штука была правильной в окнах 7. Это была первая попытка. 'Ошибка: ожидая единственное значение ' – akrun