r-如何检查矢量是否为后进先出法/先进先出法递减



假设我有一个data.table,其中每行由两个向量组成:

  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"列的行,作为非prm列的LIFO减法。例如

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       

编辑:

后进先出法(后进先出)和先进先出法是区分某些元素优先级的减法方法。

考虑一个数字向量,(a,b,c)。将"c"视为最近的,将"a"视为最不最近的。

这个向量中的单位总数是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,1)

以下是一种可能的方法,可以在筛选具有lifo向量的行之前先计算lifo向量:

#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]
]

输出:

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

数据:

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"
))

在评论中重申@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

最新更新