Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 基于多个条件在销售数据中重新组合人工拆分的会话_R_Data.table - Fatal编程技术网

R 基于多个条件在销售数据中重新组合人工拆分的会话

R 基于多个条件在销售数据中重新组合人工拆分的会话,r,data.table,R,Data.table,我们有来自触摸屏自动售货机的销售数据。当客户将钱放入机器时,它会启动一个会话,使用该机器特有的数字序列对会话进行计数。大多数情况下,系统会在应该的时候启动和停止会话。然而,在大约7%的情况下,当机器中还有钱要花时,它会人工启动一个新会话 所以 其中,可用。支出是所有不同列的总和,表示已将钱或凭证插入机器,实际支出是该会话期间花费的所有钱的总和 所以,大多数情况下,他们是平等的。然而,在第2次会议中,插入了25美元,只花了17美元。第三节课显示没有可用的钱可以花,但实际花了8美元,这就平衡了第一节

我们有来自触摸屏自动售货机的销售数据。当客户将钱放入机器时,它会启动一个会话,使用该机器特有的数字序列对会话进行计数。大多数情况下,系统会在应该的时候启动和停止会话。然而,在大约7%的情况下,当机器中还有钱要花时,它会人工启动一个新会话

所以

其中,
可用。支出
是所有不同列的总和,表示已将钱或凭证插入机器,
实际支出
是该会话期间花费的所有钱的总和

所以,大多数情况下,他们是平等的。然而,在第2次会议中,插入了25美元,只花了17美元。第三节课显示没有可用的钱可以花,但实际花了8美元,这就平衡了第一节课

我想让R合并这些会话,并创建一个指示符列,告诉我新会话是合并会话的结果

我将如何查看会话是否平衡,如果不平衡,请检查下一个会话是否:

  • 没有可用的
  • 有实际支出;以及
  • 两个会话的实际.spend==第一个会话的可用.spend
  • 然后,如果(且仅当)所有三个条件都满足,则将合并这两个会话(使用会话号或新的、由一个会话组成的会话),并创建一个带有1的新列,显示新会话是合并其他会话的结果

    以下是我制作的样品的
    dput()

    mydt<-    structure(list(session = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), available.spend = c(20, 
          25, 0, 15, 14, 0, 59, 0, 15, 21), actual.spend = c(20, 17, 8, 
          15, 7, 7, 50, 9, 15, 21)), .Names = c("session", "available.spend", 
          "actual.spend"), row.names = c(NA, -10L), class = c("data.table", 
          "data.frame"), .internal.selfref = <pointer: 0x0000000000300788>)
    
    以及
    dput()


    mynew.dt所以结果与您想要的data.frame不太一样。
    我在可用支出和实际支出上使用累积金额。然后我检查哪些匹配,只有那些匹配的我在new.session列中放“1”

    mydt$spend.sum <-cumsum(mydt$actual.spend) #Cumulative sum of actual 
    mydt$avail.sum <-cumsum(mydt$available.spend) #Cumulative sum of actual 
    

    如果您的
    可用.expense在这些情况下始终为零,您可以使用该值对行进行分组(我假设您有时在一行中有多个0,否则您可以简单地将
    实际.expense
    ,将其移位1,然后求和以进行比较):

    从这一点上,你应该有所有的信息,你需要继续


    也许,更一般地说,最好按
    cumsum(available.spend>=actual.spend)
    进行分组这是一种笨重的解决方案,但是考虑到狭窄的参数和期望的结果,我想不出更好的方法来实现这一点,除非一件一件地完成

    mismatches <- mydt[available.spend != actual.spend, which=TRUE]
    zeros <- mydt[available.spend == 0, which=TRUE]
    x <- setdiff(mismatches, zeros)
    followcheck <- mydt[x+1, session == mydt[zeros, session] & actual.spend > 0]
    following.zeros <- zeros[followcheck]
    sumthing <- mydt[x, available.spend==actual.spend + mydt[following.zeros, actual.spend]]
    x <- x[sumthing]
    y <- x + 1
    mydt[x, actual.spend:=actual.spend + mydt[y, actual.spend]]
    # Caution here, data.table gave a warning about needing to copy the table in memory to do this next line.
    mydt[, newsess:=0]
    mydt[x, newsess:=1]
    mydt <- mydt[-y,]
    

    不匹配这实际上会变得更加复杂,因为有时候,会话可能不会在下一个会话中保持平衡,而是在接下来的两个(或三个)会话中保持平衡。然而,这是非常罕见的,我希望我可以忽略这些~然而,人工创建的会话中有7%太多了,不容忽视。这当然是一个可行的解决方法。我担心的是,由于7%的会议被取消,结果会出现偏差。data.table大约有2400万行,因此7%的客户被从分析中删除。如果我不能想出上述解决方案,这将是我所能希望的最好的。谢谢你花时间来解决这个问题。再看一眼,cumsum不是好办法。只要完成最后三行代码,我就可以在可用和实际会面的地方获得会话。Cumsum使它看起来好像在数百万次中只发生了几次(前四次)。@infominer仅供参考,为了显示
    数据.frame
    数据.table
    的可读性之间的差异,这是
    数据.table
    方式:
    mydt[,new.session:=Cumsum(available.spend)==Cumsum(actual.spend)]
    ;或者,为了避免溢出:
    mydt[,new.session:=cumsum(available.spend-actual.spend)==0]
    @datahappy我不明白为什么你认为
    cumsum
    做不到你想做的事-你可能想举个例子说明它在哪里fails@eddi因为cumsum就是这样做的-提供了一个总的累积和。一旦有一个可用的和实际的不相等的实例,那么在那之后的每个实例中,它们都是不相等的。(发生在第四次观察时)。因此,当创建一个只包含完整案例的data.table时,它只包含前四个观察值,而不是它应该包含的2100万个观察值。好吧,这就像一种魅力。它正确地组合了会话,修复了所有人为分割的会话。不幸的是,它创建的data.table只包含变量session、available.spend和actual.spend(加上一个cumsum列)。如何让它保留并合并data.table中的所有其他(22)列?看起来我需要单独将所有变量添加到列表中?同样,我假设(例如totsales=sum(totsales)等)有更简单的方法来实现这一点吗?@datahappy使用
    .SD[1]
    ,而不是
    session=session[1]
    ,如果速度太慢,请参阅;或者我误解了,您想使用
    lappy(.SD,sum)
    而不是单独的求和;你挑吧:)
    mynew.dt<- structure(list(session = c(1, 2, 4, 5, 7, 9, 10), available.spend = c(20, 
                25, 15, 14, 59, 15, 21), actual.spend = c(20, 25, 15, 14, 59, 
                15, 21), newsess = c(0, 1, 0, 1, 1, 0, 0)), .Names = c("session", 
                "available.spend", "actual.spend", "newsess"), row.names = c(NA, 
                -7L), class = c("data.table", "data.frame"), .internal.selfref = <pointer:                     0x0000000000300788>)
    
    mydt$spend.sum <-cumsum(mydt$actual.spend) #Cumulative sum of actual 
    mydt$avail.sum <-cumsum(mydt$available.spend) #Cumulative sum of actual 
    
    mydt$new.session <-NA
    
    mydt$new.session[with(mydt, which(spend.sum == avail.sum))]<-1
    
    mydt[complete.cases(my.dt),]
    
    dt[, list(session = session[1],
              available.spend = sum(available.spend),
              actual.spend = sum(actual.spend)),
         by = cumsum(available.spend != 0)]
    #   cumsum session available.spend actual.spend
    #1:      1       1              20           20
    #2:      2       2              25           25
    #3:      3       4              15           15
    #4:      4       5              14           14
    #5:      5       7              59           59
    #6:      6       9              15           15
    #7:      7      10              21           21
    
    mismatches <- mydt[available.spend != actual.spend, which=TRUE]
    zeros <- mydt[available.spend == 0, which=TRUE]
    x <- setdiff(mismatches, zeros)
    followcheck <- mydt[x+1, session == mydt[zeros, session] & actual.spend > 0]
    following.zeros <- zeros[followcheck]
    sumthing <- mydt[x, available.spend==actual.spend + mydt[following.zeros, actual.spend]]
    x <- x[sumthing]
    y <- x + 1
    mydt[x, actual.spend:=actual.spend + mydt[y, actual.spend]]
    # Caution here, data.table gave a warning about needing to copy the table in memory to do this next line.
    mydt[, newsess:=0]
    mydt[x, newsess:=1]
    mydt <- mydt[-y,]