R 而使用data.table循环条件

R 而使用data.table循环条件,r,while-loop,dplyr,data.table,R,While Loop,Dplyr,Data.table,我不熟悉R中的循环,有一个相对简单的数据集要处理。我的示例数据集由时间戳-时间、手机id:id、手机电池电量:电量 我的目标是生成一个输出,该输出考虑了电池随时间的衰减率,并考虑了充电周期。当以下记录的级别大于前一记录的级别时,可以确定周期的开始。换句话说,当水平滞后(水平)时,循环应重新开始 > test time id level 1: 2017-12-25 14:10:03 1 81 2: 2017-12-25 14:20:03 1

我不熟悉R中的循环,有一个相对简单的数据集要处理。我的示例数据集由时间戳-
时间
、手机id:
id
、手机电池电量:
电量
我的目标是生成一个输出,该输出考虑了电池随时间的衰减率,并考虑了充电周期。当以下记录的级别大于前一记录的级别时,可以确定周期的开始。换句话说,当
水平
滞后(水平)
时,循环应重新开始

> 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

> 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
到目前为止,我只是尝试创建一个while循环来连接每个循环的级别,之后我可以使用下面的代码获取min、max等,但这不会产生预期的输出

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

如果
test
是一个
data.table
,则可以将
cumsum
shift
一起使用。(
shift
是来自
data.table
的函数;它与
lag
相同)


如果
test
是一个
data.table
,则可以将
cumsum
shift
一起使用。(
shift
是来自
data.table
的函数;它与
lag
相同)


在第一步中使用@Hugh方法,然后得到最终结果:

test[, cycle := cumsum(level > shift(level, fill = first(level))), by = "id"]
x <- test[, .(start = min(time),
              recharge = max(time),
              diffcharge = max(level) - min(level)),
          by = .(id, cycle)]
x[, difftime := as.numeric(recharge - start)]
x[, rate :=  diffcharge / difftime]
x
#    id cycle               start            recharge diffcharge  difftime      rate
# 1:  1     0 2017-12-25 14:10:03 2017-12-25 16:00:04         21 110.01283 0.1908868
# 2:  1     1 2017-12-25 16:10:04 2017-12-25 17:20:03         16  69.98285 0.2286274
# 3:  2     0 2017-12-25 17:30:03 2017-12-25 19:00:03         89  89.99613 0.9889314
# 4:  2     1 2017-12-25 19:10:04 2017-12-25 20:10:03         13  59.99771 0.2166749
# 5:  2     2 2017-12-25 20:20:04 2017-12-25 20:40:03          3  19.99584 0.1500312
test[,cycle:=cumsum(level>shift(level,fill=first(level)),by=“id”]

x在第一步使用@Hugh方法,然后得到最终结果:

test[, cycle := cumsum(level > shift(level, fill = first(level))), by = "id"]
x <- test[, .(start = min(time),
              recharge = max(time),
              diffcharge = max(level) - min(level)),
          by = .(id, cycle)]
x[, difftime := as.numeric(recharge - start)]
x[, rate :=  diffcharge / difftime]
x
#    id cycle               start            recharge diffcharge  difftime      rate
# 1:  1     0 2017-12-25 14:10:03 2017-12-25 16:00:04         21 110.01283 0.1908868
# 2:  1     1 2017-12-25 16:10:04 2017-12-25 17:20:03         16  69.98285 0.2286274
# 3:  2     0 2017-12-25 17:30:03 2017-12-25 19:00:03         89  89.99613 0.9889314
# 4:  2     1 2017-12-25 19:10:04 2017-12-25 20:10:03         13  59.99771 0.2166749
# 5:  2     2 2017-12-25 20:20:04 2017-12-25 20:40:03          3  19.99584 0.1500312
test[,cycle:=cumsum(level>shift(level,fill=first(level)),by=“id”]

x假设您从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)

test假设您从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)

test谢谢,但这如何考虑手机的
id
?例如,一个
id
可能在80级结束,然后下一个
id
可能从79级开始,但这仍然会被视为同一个循环,即使这是不正确的,这有意义吗?是的。在这种情况下,
fill=first(level)
如何工作?请尝试省略
fill
参数;
cycle
列将是一列
NA
s。因此,您需要为每个组提供一个合理的首值。谢谢,但这如何考虑手机的
id
?例如,一个
id
可能在80级结束,然后下一个
id
可能从79级开始,但这仍然会被视为同一个循环,即使这是不正确的,这有意义吗?是的。在这种情况下,
fill=first(level)
如何工作?请尝试省略
fill
参数;
cycle
列将是一列
NA
s。因此,您需要为每个组提供一个合理的第一个值。