我是R中的循环新手,并且有一个相对简单的数据集来处理。我的示例数据集包含时间戳 - SELECT * FROM sales INNER JOIN partner on user_id = idpartner WHERE DATE((end_date) + 5) >= DATE(NOW()) ORDER BY end_date ASC LIMIT 0,50000
,手机ID:time
和手机电池电量:id
我的目标是产生一个输出,该输出随着时间的推移考虑电池的下降速率,考虑到充电周期。可以识别循环的开始,其中下面的记录级别大于前一级别。换句话说,虽然level
< = level
,但周期应该继续,但只要lag(level)
> level
,循环应该重启
lag(level)
在上面的示例数据集中,预期输出将如下所示,其中> test
time id level
1: 2017-12-25 14:10:03 1 81
2: 2017-12-25 14:20:03 1 81
3: 2017-12-25 14:30:04 1 81
4: 2017-12-25 14:40:04 1 73
5: 2017-12-25 14:50:04 1 70
6: 2017-12-25 15:00:03 1 70
7: 2017-12-25 15:10:04 1 65
8: 2017-12-25 15:20:04 1 62
9: 2017-12-25 15:30:04 1 61
10: 2017-12-25 15:40:04 1 60
11: 2017-12-25 15:50:03 1 60
12: 2017-12-25 16:00:04 1 60
13: 2017-12-25 16:10:04 1 95
14: 2017-12-25 16:20:03 1 95
15: 2017-12-25 16:30:04 1 95
16: 2017-12-25 16:40:04 1 94
17: 2017-12-25 16:50:04 1 92
18: 2017-12-25 17:00:03 1 90
19: 2017-12-25 17:10:04 1 81
20: 2017-12-25 17:20:03 1 79
21: 2017-12-25 17:30:03 2 100
22: 2017-12-25 17:40:03 2 100
23: 2017-12-25 17:50:03 2 100
24: 2017-12-25 18:00:03 2 90
25: 2017-12-25 18:10:03 2 85
26: 2017-12-25 18:20:03 2 75
27: 2017-12-25 18:30:04 2 65
28: 2017-12-25 18:40:03 2 54
29: 2017-12-25 18:50:03 2 32
30: 2017-12-25 19:00:03 2 11
31: 2017-12-25 19:10:04 2 92
32: 2017-12-25 19:20:04 2 92
33: 2017-12-25 19:30:03 2 91
34: 2017-12-25 19:40:04 2 90
35: 2017-12-25 19:50:04 2 90
36: 2017-12-25 20:00:03 2 81
37: 2017-12-25 20:10:03 2 79
38: 2017-12-25 20:20:04 2 99
39: 2017-12-25 20:30:04 2 96
40: 2017-12-25 20:40:03 2 96
=周期开始和停止之间的时间差,difftime
=电池电平之间的差异周期开始和停止,diffcharge
= rate
diffcharge/difftime
到目前为止,我已经尝试过简单地创建一个while循环来连接每个循环的级别,之后我可以使用以下代码获取min,max等,但这不会产生预期的输出。
> outcome
id start recharge difftime diffcharge rate
1 1 2017-12-25 14:10:03 2017-12-25 16:00:04 110.0167 21 0.1908801
2 1 2017-12-25 16:10:04 2017-12-25 17:20:03 69.98333 16 0.2286259
3 2 2017-12-25 17:30:03 2017-12-25 19:00:03 90 89 0.9888889
4 2 2017-12-25 19:10:04 2017-12-25 20:10:03 59.98333 13 0.2167269
5 2 2017-12-25 20:20:04 2017-12-25 20:40:03 19.98333 3 0.1501251
有关如何使用raw_data <- test
unique_id = unique(test$id)
for (id in unique_id)
{
onePhone <- raw_data[ which(raw_data$id == id), ]
onePhone <- onePhone[order(onePhone$time, decreasing = FALSE),]
cycle <- NULL
if(nrow(onePhone) >=2 ){
for(i in 2:nrow(onePhone)) {
while(onePhone[i-1,"level"] >= onePhone[i,"level"])
{
i = i+1
cycle <- c(z, onePhone[i,"level"])
}
print(cycle)
}
}
}
,data.table
或简单的while循环的任何建议,我们将不胜感激。以下是示例数据:
dplyr
答案 0 :(得分:2)
在第一步中使用@Hugh方法然后获得最终结果:
update_attributes
答案 1 :(得分:1)
如果test
是data.table
,您可以将cumsum
与shift
一起使用。 (shift
是来自data.table
的函数;它与lag
相同。)
test[, cycle := cumsum(level > shift(level, fill = first(level))), by = "id"]
答案 2 :(得分:1)
假设您从csv文件中读取测试:
test<-read.csv("test.csv",stringsAsFactors = F)
test$DateTime<-paste(test$Date,test$time,by=" ")
test$Charge<-FALSE
test$Charge[1:((nrow(test)-1))]<-diff(test$level)>0
start=test[which(test$Charge)+1,]$DateTime
start<-c(test$DateTime[1],start)
start<-dmy_hms(start)
recharge<-filter(test,Charge)$DateTime
recharge<-c(recharge,tail(test$DateTime,1))
recharge<-dmy_hms(recharge)
difftime=recharge-start
startLevel=test[which(test$Charge)+1,]$level
startLevel=c(test$level[1],startLevel)
endLevel=filter(test,Charge)$level
endLevel=c(endLevel,tail(test$level,1))
diffcharge=startLevel-endLevel
rate=diffcharge/as.numeric(difftime)
id=filter(test,Charge)$id
id=c(id,tail(test$id,1))
outcome=data.frame(id=id,start=start,recharge=recharge,difftime=difftime,diffcharge=diffcharge,rate=rate)