我们的销售数据来自触摸屏自动售货机。当客户将钱存入机器时,它会启动一个会话,使用该机器特有的一系列数字来计算这些会话。大多数情况下,系统启动和停止会话。然而,大约7%的时间,当机器中仍有剩余资金用于支出时,人为地开始新的会话。
所以,
session available.spend actual.spend
1 20 20
2 25 17
3 0 8
4 15 15
5 14 7
6 0 7
7 59 50
8 0 9
9 15 15
10 21 21
其中available.spend
是所有不同列的总和,表示已将金钱或凭证插入到计算机中,actual.spend
是该会话期间所有花费的总和。
所以,大多数时候他们彼此相等。但是,在第2节中,插入了25美元,仅花费了17美元。第3节显示没有可用的资金,但实际花费了8美元,这平衡了第一次会议。
我想让R组合这些会话并创建一个指标列,告诉我新会话是合并会话的结果。
我如何让R看看会话是否平衡,然后,如果没有,请检查下一个会话以查看是否:
然后,如果(且仅当)满足所有三个条件,则组合这两个会话(使用会话编号或新编制的会话编号)和带有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>)
这就是我希望输出的样子:
session available.spend actual.spend newsess
1 20 20 0
2 25 25 1
4 15 15 0
5 14 14 1
7 59 59 1
9 15 15 0
10 21 21 0
和dput()
:
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>)
我一直在尝试在data.table(数据集非常大)和/或ifelse中找到这种方法,但是我无法弄清楚如何检查三个条件并且仅在遇到它时才执行操作这三个,同时还删除旧列并创建虚拟变量列。 呼
还有一个皱纹:这些会话ID可以(虽然很少发生)在一天以上发生。因此,代码必须要么在data.frame中查找下一行,要么如果它查找下一个按顺序进行的会话,则需要确保两个会话上的日期匹配。
感谢您的帮助。
答案 0 :(得分:1)
所以你想要的结果data.frame不完全相同。 我在可用支出和实际支出上使用cumsum(累积和)。然后我检查哪些是匹配的,并且只针对那些匹配我放的&#34; 1&#34;在new.session专栏中。
mydt$spend.sum <-cumsum(mydt$actual.spend) #Cumulative sum of actual
mydt$avail.sum <-cumsum(mydt$available.spend) #Cumulative sum of actual
现在制作一个新专栏并将其全部纳入NA
mydt$new.session <-NA
检查哪些累积总和匹配,并用1&#39>替换NA&#39;
mydt$new.session[with(mydt, which(spend.sum == avail.sum))]<-1
如果您只想在new.session列中使用1&#39s的data.frame
这样做
mydt[complete.cases(my.dt),]
答案 1 :(得分:1)
如果你的available.spend
在这些情况下总是为零,你可以使用它来对行进行分组(我假设你有时连续有多个这样的0,否则你可以简单地采取{ {1}},将它移1并总结回比较):
actual.spend
从这一点开始,您应该拥有继续所需的所有信息。
或许,更一般地说,按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
进行分组会更好。
答案 2 :(得分:0)
这是一种笨重的解决方案,但考虑到狭窄的参数和期望的结果,我无法想到更好的方法来做到这一点,除了一块一块。
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,]