Кумулятивная сумма объекта Matrix / xts на двух столбцах в R

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

Я хотел бы вычислить совокупную сумму инвентаризации конкретных идентификаторов (ID 100 в приведенном ниже примере) на основе информации в двух столбцах объекта matrix / xts. Для простоты использования я добавил пример кода ниже:

a <- c(20,50,30,50,10, 40)
b <- c("100", "200", "300", "100", "100", "100")
c <- c("200", "100", "100", "200", "200", "100")
matrix1 <- cbind(a,b,c)
dim(matrix1) <- c(6,3)
colnames(matrix1) <- c("inventory", "buyer", "seller")

Когда вы помещаете этот код в R, должна появиться матрица, заданная в следующем формате:

inventory | buyer   | seller
20        |  100    | 200
50        |  200    | 100
30        |  300    | 100
50        |  100    | 200
10        |  100    | 200
40        |  100    | 100

РЕДАКТИРОВАТЬ: я изменил буквы в столбцах "Покупатель" и "Продавец" на числа, чтобы теперь он работал с матрицами правильно, извините! (Обратите внимание, что, поскольку это объект xts, слева от столбца inventory должна быть отметка времени, но я оставил ее, поскольку она не имеет значения).

Теперь есть три идентификатора: 100, 200 и 300, и каждый из них покупает и продает друг у друга, при этом происходит то, что buyer получает инвентарь в каждой строке, а seller теряет инвентарь. Кроме того, если в столбцах buyer и seller указан один и тот же идентификатор, то инвентарь останется неизменным. Для моей конкретной проблемы меня интересует только совокупная инвентаризация ID 100, и меня не волнует совокупная инвентаризация 200 и 300.

В приведенном выше примере это означает, что в первой строке 100 совокупный запас равен 20, а во второй строке 100 теперь суммарный запас равен -30. Аналогично, для третьей строки 100 имеет совокупный запас -60, в четвертой строке он имеет совокупный запас -10, а в пятой строке 100 имеет совокупный запас 0. Для шестой строки, поскольку 100 равно В обоих столбцах buyer и seller инвентарь такой же, как и в пятом столбце, так что он снова равен 0.

Поэтому я хотел бы получить вектор кумулятивного инвентаря, заданный как c(20, -30, -60, -10, 0, 0)

Кроме того, поскольку это объект xts, я не уверен, что это меняет что-нибудь (хотя я очень сомневаюсь, что это что-то меняет, единственное, что я пропустил, это тот факт, что на самом деле должен быть столбец с отметкой времени слева от матрицы. , но я исключил его, так как это не имеет отношения к вопросу).

Есть ли хороший способ вычисления совокупной суммы на основе двух столбцов и индивидуальных идентификаторов?


person ThePlowKing    schedule 10.07.2017    source источник
comment
Отвечать на вопросы о 'xts' -объектах, не видя вывода dput (xts_obj), очень сложно. Утверждать, что индекс объекта xts не имеет значения, просто неправдоподобно. Прочтите минимальный воспроизводимый пример   -  person IRTFM    schedule 11.07.2017
comment
Вы также должны сказать, какой правильный ответ. Из описания проблемы я предполагаю, что «инвентарь - это счетчик, и для результата должно быть c(20, -30, -60, -10, 0).   -  person IRTFM    schedule 11.07.2017
comment
@ 42- А, ладно, в таком случае я сейчас буду рассматривать его как матрицу и после этого конвертирую в объект xts. И да, я хотел бы иметь вектор c(20, -30, -60, -10,0) :) Я отредактирую свой код, чтобы включить его   -  person ThePlowKing    schedule 11.07.2017
comment
Матрица может быть не лучшим объектом для хранения столбцов с разными типами данных   -  person HubertL    schedule 11.07.2017
comment
@HubertL в моем коде буквы на самом деле являются числами, но я изменил их на буквы в этом примере, чтобы попытаться сделать вещи немного яснее / проще для понимания. Но в таком случае я верну его к цифрам, тогда, если будет лучше   -  person ThePlowKing    schedule 11.07.2017
comment
Это матрица символов.   -  person IRTFM    schedule 11.07.2017


Ответы (1)


Я отредактировал его для работы либо с data.frame, либо с матрицей. Сообщите мне, работает ли это для вас.

cum.inv <- function(ID, data){
  stopifnot(colnames(data) %in% c("inventory", "buyer", "seller"))
  cumsum(ifelse(data[,"buyer"] == data[,"seller"], 0, 
                ifelse(data[,"buyer"] == ID, as.numeric(matrix1[,"inventory"]), 
                       ifelse(data[,"seller"] == ID, -as.numeric(matrix1[,"inventory"]), 0))))
}
cum.inv(100, matrix1)
#[1]  20 -30 -60 -10   0   0

cum.inv(200, matrix1)
#[1] -20  30  30 -20 -30 -30

cum.inv(300, matrix1)
#[1]  0  0 30 30 30 30
person Evan Friedland    schedule 10.07.2017
comment
Выглядит неплохо :) В идеале я бы хотел сохранить его в матричной форме, хотя, если возможно (поскольку преобразование занимает довольно много времени!). Что касается кода фрейма данных, который вы опубликовали, если я возьму новую информацию, которую я добавил в свое исходное сообщение, изменится ли код на это? cum.inv <- function(ID) { cumsum(ifelse(df$buyer==ID & df$seller==ID, 0 ,ifelse(df$buyer == ID, df$inventory, ifelse(df$seller == ID, -df$inventory, 0)))) }? - person ThePlowKing; 11.07.2017
comment
Да, вы добавляете ifelse для обработки, если покупатель и продавец совпадают. Вместо df$buyer==ID & df$seller==ID я использовал df$buyer==df$seller. И преобразование не должно занимать много времени! as.data.frame() обычно происходит довольно быстро. - person Evan Friedland; 11.07.2017
comment
Извините за поздний ответ, раньше я был немного занят. Но теперь ваш отредактированный код идеален, спасибо за это! - person ThePlowKing; 11.07.2017
comment
На самом деле, если это не слишком большая проблема, у меня есть последний вопрос: есть ли способ добавить этот вектор обратно в исходную матрицу без необходимости использовать такие вещи, как cbind()? Поскольку матрица у меня довольно большая, я бы хотел, чтобы функция «заполняла» четвертый столбец матрицы, если это возможно. Я пытаюсь немного изменить ваш код, но мне не очень везет :( - person ThePlowKing; 11.07.2017
comment
Четвертый столбец чего? Результатом этой функции является вектор, длина которого равна размеру строк. matrix1[,"NewColumnName"] <- cum.inv(300, matrix1)? - person Evan Friedland; 11.07.2017
comment
Ах, это прекрасно, да, это именно то, что я искал :) Не могу поверить, что забыл что-то такое простое, ха-ха. Большое спасибо за помощь! - person ThePlowKing; 11.07.2017