Как проверить, уменьшается ли вектор LIFO / FIFO - PullRequest
0 голосов
/ 02 января 2019

Предположим, у меня есть таблица данных, в которой каждая строка состоит из двух векторов:

  1. Вектор "до вычитания".
  2. Вектор "после вычитания".

Предварительное вычитание - это самый левый столбец, а столбец - самый правый столбец с суффиксом "prm" в конце.

Например:

#Sample Data
set.seed(2)
fill = data.table(n=1:7)
Tp=3

  for(t in 1:Tp){ 
     set(x = fill, j = paste0('v',t), value = sample(0:10,7))
  }

fill[1,paste0('v',3):=0]
fill[5,paste0('v',2):=0]
fill[5,paste0('v',3):=0]

for(t in 1:Tp){ 
  fill[,paste0('v',t,'prm'):=get(paste0('v',t))]
}


fill[1,paste0('v',1,'prm'):=0] 
fill[2,paste0('v',2,'prm'):=1]   
fill[5,paste0('v',3,'prm'):=1]  
fill[7,paste0('v',3,'prm'):=2] 

Данные:

> fill
   n         v1         v2         v3          v1prm         v2prm        v3prm
1: 1          2          9          0             0             9             0
2: 2          7          4          8             7             1             8
3: 3          5         10          9             5            10             9
4: 4          1          8          1             1             8             1
5: 5          6          0          0             6             0             1
6: 6          8          7          0             8             7             0
7: 7          0          0          6             0             0             2

Вектор LIFO должен уменьшаться по элементам вправо, прежде чем воздействовать на более левые элементы.Первый ряд VIOLATES LIFO, потому что

(2, 9, 0) --> (0, 9, 0) должен был вычесть 2 из 9 перед 2 в самом левом блоке.

Я хотел бы включить в поднабор ТОЛЬКО строки, в которых есть столбцы 'prm' в качестве вычитаний LIFO столбцов, не являющихся prm.Например,

   n         v1         v2          v3          v1prm         v2prm        v3prm
1: 3          5         10          9             5            10             9
2: 4          1          8          1             1             8             1
3: 6          8          7          0             8             7             0
4: 7          0          0          6             0             0             2       

РЕДАКТИРОВАТЬ:

LIFO (последний пришел первым) и FIFO (первый пришел первым) являются способами вычитания, которыерасставьте приоритеты для определенных элементов.

Рассмотрим вектор чисел (a, b, c).Считайте «с» самым последним, а «а» - наименее недавним.

Общее количество единиц в этом векторе a + b + c.

Если мы вычтем из него d единиц, при вычитании LIFO или FIFO, мы не вычтем d из каждого элемента, скорее, мы вычтем его поэлементно из самого последнего (LIFO) или наименее недавнего (FIFO) доон исчерпан (с минимумом 0).

, например,

LIFO: (3,2,1) - 5 = (3,2,1 - 5) -> (3,2 -4, 0) -> (3 -2, 0,0) -> (1,0,0)

FIFO: (3,2,1) - 5 = (3-5,2,1) -> (0,2 -2, 1) -> (0, 0,1)

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Вот возможный подход для вычисления вектора жизни сначала перед фильтром для тех строк с векторами жизни:

#convert into long format from MichaelChirico and svenkatesh
tbl <- melt(fill, meas=patterns("^v[1-9]$", "prm$"), 
    value.name=c("bef","aft"))
setorder(tbl, n, -variable)

     #filter for those lifo vector
fill[n %in% 
        tbl[, {
                #calculate stock taken out
                dif <- sum(bef) - sum(aft)

                #calculate lifo vector
                lifo <- pmin(pmax(cumsum(bef) - dif, 0L), bef)

                #check if after is this lifo vector
                identical(lifo, aft)

            }, by=.(n)][(V1), n]
    ]

output:

   n v1 v2 v3 v1prm v2prm v3prm
1: 3  5 10  9     5    10     9
2: 4  1  8  1     1     8     1
3: 6  8  7  0     8     7     0
4: 7  0  0  6     0     0     2

data:

library(data.table)
fill <- structure(list(n = 1:7, v1 = c(2L, 7L, 5L, 1L, 6L, 8L, 0L), v2 = c(9L, 
    4L, 10L, 8L, 0L, 7L, 0L), v3 = c(0L, 8L, 9L, 1L, 0L, 0L, 6L), 
    v1prm = c(0L, 7L, 5L, 1L, 6L, 8L, 0L), v2prm = c(9L, 1L, 
        10L, 8L, 0L, 7L, 0L), v3prm = c(0L, 8L, 9L, 1L, 1L, 0L, 2L
        )), row.names = c(NA, -7L), class = c("data.table", "data.frame"
        ))
0 голосов
/ 02 января 2019

Чтобы повторить подход @ chinsoon12 и @MichaelChirico в комментариях:

Вот fill:

   n prod1vint1 prod1vint2 prod1vint3 prod1vint1prm prod1vint2prm prod1vint3prm
1: 1          2          9          0             0             9             0
2: 2          7          4          8             7             1             8
3: 3          5         10          9             5            10             9
4: 4          1          8          1             1             8             1
5: 5          6          0          0             6             0             1
6: 6          8          7          0             8             7             0
7: 7          0          0          6             0             0             2

# Melt so that the data from the "prm" columns are different from the "prod" columns 
d = melt(fill, measure.vars = patterns("int[1-9]$", "prm$"))

# Subtract the vectors and check whether the difference is increasing (LIFO condition)
s = d[, !is.unsorted(value1 - value2), by=.(n)]

# Select the rows that satisfy the LIFO condition 
output = fill[n %in% d[, s[(V1), n]], ]

Вот вывод:

   n prod1vint1 prod1vint2 prod1vint3 prod1vint1prm prod1vint2prm prod1vint3prm
1: 3          5         10          9             5            10             9
2: 4          1          8          1             1             8             1
3: 6          8          7          0             8             7             0
4: 7          0          0          6             0             0             2
...