R中的复杂算法与使用先前行值的data.tables

时间:2013-12-18 10:47:14

标签: r data.table

我的数据形式为data.table,如下所示

structure(list(atp = c(1, 0, 1, 0, 0, 1), len = c(2, NA, 3, NA, 
NA, 1), inv = c(593, 823, 668, 640, 593, 745), GU = c(36, 94, 
57, 105, 48, 67), RUTL = c(100, NA, 173, NA, NA, 7)), .Names = c("atp", 
"len", "inv", "GU", "RUTL"), row.names = c(NA, -6L), class = c("data.table", 
"data.frame"), .internal.selfref = <pointer: 0x0000000000320788>)

我需要形成4个新列csi_begin,csi_end,IRQ和csi_order。当atp = 1时,csi_begin和csi_end的值直接取决于inv和gu值。

但是当atp不等于1 csi_begin且csi_end依赖于inv和gu值以及前一行的IRQ值 如果atp == 1,则IRQ的值取决于该行的csi_order,否则其0和csi_order值取决于先前csi_begin值的两行。

我在for循环的帮助下编写了这个条件。 以下是给出的代码

lostsales<-function(transit)
{

if (transit$atp==1)
{
  transit$csi_begin[i]<-(transit$inv)[i]
  transit$csi_end[i]<-transit$csi_begin[i]-transit$GU[i]
}
else
{
  transit$csi_begin[i]<-(transit$inv)[i]+transit$IRQ[i-1]
  transit$csi_end[i]<-transit$csi_begin[i]-transit$GU[i]
}
if (transit$csi_begin[i-2]!= NA)
{
  transit$csi_order[i]<-transit$csi_begin[i-2]
}
else
  { transit$csi_order[i]<-0}
if (transit$atp==1)
{
  transit$IRQ[i]<-transit$csi_order[i]-transit$RUTL[i] 
}

else
{
  transit$IRQ[i]<-0
}
}

任何人都可以帮助我如何使用setkeys有效地使用data.tables进行循环?由于我的数据集非常大而且我不能用于循环,否则时间会非常高。

1 个答案:

答案 0 :(得分:1)

在您的示例中添加所需的结果将非常有用,因为我无法遵循if / then逻辑。但无论如何我还是捅了一下:

library(data.table)

# Example data:
dt <- structure(list(atp = c(1, 0, 1, 0, 0, 1), len = c(2, NA, 3, NA, NA, 1), inv = c(593, 823, 668, 640, 593, 745), GU = c(36, 94, 57, 105, 48, 67), RUTL = c(100, NA, 173, NA, NA, 7)), .Names = c("atp", "len", "inv", "GU", "RUTL"), row.names = c(NA, -6L), class = c("data.table", "data.frame"), .internal.selfref = "<pointer: 0x0000000000320788>")

# Add a row number:
dt[,rn:=.I]

# Use this function to get the value from a previous (shiftLen is negative) or future (shiftLen is positive) row:
rowShift <- function(x, shiftLen = 1L) {
  r <- (1L + shiftLen):(length(x) + shiftLen)
  r[r<1] <- NA
  return(x[r])
}

# My attempt to follow the seemingly circular if/then rules:
lostsales2 <- function(transit) {
  # If atp==1, set csi_begin to inv and csi_end to csi_begin - GU:
  transit[atp==1, `:=`(csi_begin=inv, csi_end=inv-GU)]

  # Set csi_order to the value of csi_begin from two rows prior:
  transit[, csi_order:=rowShift(csi_begin,-2)]

  # Set csi_order to 0 if csi_begin from two rows prior was NA
  transit[is.na(csi_order), csi_order:=0]

  # Initialize IRQ to 0
  transit[, IRQ:=0]

  # If ATP==1, set IRQ to csi_order - RUTL
  transit[atp==1, IRQ:=csi_order-RUTL]

  # If ATP!=1, set csi_begin to inv + IRQ value from previous row, and csi_end to csi_begin - GU
  transit[atp!=1, `:=`(csi_begin=inv+rowShift(IRQ,-1), csi_end=inv+rowShift(IRQ,-1)-GU)]
  return(transit)
}

lostsales2(dt)
##    atp len inv  GU RUTL rn csi_begin csi_end csi_order  IRQ
## 1:   1   2 593  36  100  1       593     557         0 -100
## 2:   0  NA 823  94   NA  2        NA      NA         0    0
## 3:   1   3 668  57  173  3       668     611       593  420
## 4:   0  NA 640 105   NA  4       640     535         0    0
## 5:   0  NA 593  48   NA  5       593     545       668    0
## 6:   1   1 745  67    7  6       745     678       640  633

此输出是否接近您的预期?