寻找帮助来编写棘手的R代码。
我有一个以下结构的数据框:
#make fake data
category<-c("a", "a", "a", "a", "a", "b", "b", "b", "b", "b")
cat.id<-rep(1:5, 2)
time <- seq.POSIXt(as.POSIXct("10/24/16 21:05", format="%m/%d/%y %H:%M", tz="America/Chicago"), by="5 min", length.out=10)
x<-c(0.2, 3, 4, 0.5, 1.4, 3, 1.9, 2.2, 4, 1.2)
data<-data.frame(category, cat.id, time, x)
>data
category cat.id time x
1 a 1 2016-10-24 21:05:00 0.2
2 a 2 2016-10-24 21:10:00 3.0
3 a 3 2016-10-24 21:15:00 4.0
4 a 4 2016-10-24 21:20:00 0.5
5 a 5 2016-10-24 21:25:00 1.4
6 b 1 2016-10-24 21:30:00 3.0
7 b 2 2016-10-24 21:35:00 1.9
8 b 3 2016-10-24 21:40:00 2.2
9 b 4 2016-10-24 21:45:00 4.0
10 b 5 2016-10-24 21:50:00 1.2
对于“类别”的每个子集(例如,“a”或“b”),我需要移动“cat.id”,以便: -if“x”是&lt;在图2中,然后将“cat.id”匹配(或移位)到最接近的先前值“cat.id”,其中x是> = 2。 - 移位的“cat.id”值存储在“cat.idshifted”列中 - 对于“cat.id”== 1的值,没有移位,因为“category”的子集没有先前的值
这会生成如下数据框:
data$cat.idshifted<-c(1, 2, 3, 3, 3, 1, 1, 3, 4, 4)
>data
category cat.id time x cat.idshifted
1 a 1 2016-10-24 21:05:00 0.2 1
2 a 2 2016-10-24 21:10:00 3.0 2
3 a 3 2016-10-24 21:15:00 4.0 3
4 a 4 2016-10-24 21:20:00 0.5 3
5 a 5 2016-10-24 21:25:00 1.4 3
6 b 1 2016-10-24 21:30:00 3.0 1
7 b 2 2016-10-24 21:35:00 1.9 1
8 b 3 2016-10-24 21:40:00 2.2 3
9 b 4 2016-10-24 21:45:00 4.0 4
10 b 5 2016-10-24 21:50:00 1.2 4
基本思想是“cat.id”表示“类别”收集的数据文件的数量。有时,由于硬件问题,实际属于单个事件的数据文件会被拆分为多个文件。因此,实际上可以在3个文件中收集1个数据事件。您可以通过查看“x”找出哪些文件在一起。如果x <2的值,则文件一起出现。并且由于1个文件可以分成许多,因此x&lt; 2表示属于一起的多个文件。
所以我想做的是每次x&lt; 2,并将“cat.id”或文件ID调整为正确的值,这恰好是收集了与x&gt; = 2的前一个文件中最接近的时间。
我在想一个索引最接近(及时)&gt; = 2的“x”值的函数可能是合适的。然后索引值将“cat.id”值返回“cat.idshifted”。
我熟悉which.max等索引值,但是我不知道如何通过说“给我最接近的值的东西”来索引值。
为简单起见,我没有在这里包含,但x实际上是每个文件集合之间的时间量。例如,它是一个difftime对象。也许一段时间循环可以工作?哪里: - 有x&lt; 2个值 -Shift cat.id值返回1(例如,cat.id-1) - 重新计算difftime - 检查是否仍然存在x <2的值,重复,直到不为真。
对这个棘手的代码有何看法?
答案 0 :(得分:1)
试试这个:
# Create 'temp' column to indicate whether record belongs to previous file (0) or not (cat.id)
data$temp = ifelse(data$x < 2, 0, data$cat.id)
data$temp[data$cat.id==1] = 1
# Take the cumulative max of 'temp' by category.
data$cat.idshifted = unlist(by(data, data$category, function(da) cummax(da$temp)))
> data
# category cat.id time x temp cat.idshifted
# 1 a 1 2016-10-24 21:05:00 0.2 1 1
# 2 a 2 2016-10-24 21:10:00 3.0 2 2
# 3 a 3 2016-10-24 21:15:00 4.0 3 3
# 4 a 4 2016-10-24 21:20:00 0.5 0 3
# 5 a 5 2016-10-24 21:25:00 1.4 0 3
# 6 b 1 2016-10-24 21:30:00 3.0 1 1
# 7 b 2 2016-10-24 21:35:00 1.9 0 1
# 8 b 3 2016-10-24 21:40:00 2.2 3 3
# 9 b 4 2016-10-24 21:45:00 4.0 4 4
# 10 b 5 2016-10-24 21:50:00 1.2 0 4
答案 1 :(得分:0)
data$cat.idshifted <- NA
for(c in data$category){
for(i in which(data$category==c)){
if(data$cat.id[i]==1){
data$cat.idshifted[i] <- data$cat.id[i]
} else if(data$x[i]<=2){
data$cat.idshifted[i] <- max( data$cat.id[data$x > 2 & data$category==c & data$cat.id < data$cat.id[i]])
} else if(data$x[i]>2){
data$cat.idshifted[i] <- data$cat.id[i]
}
}
}
data
category cat.id time x cat.idshifted 1 a 1 2016-10-24 21:05:00 0.2 1 2 a 2 2016-10-24 21:10:00 3.0 2 3 a 3 2016-10-24 21:15:00 4.0 3 4 a 4 2016-10-24 21:20:00 0.5 3 5 a 5 2016-10-24 21:25:00 1.4 3 6 b 1 2016-10-24 21:30:00 3.0 1 7 b 2 2016-10-24 21:35:00 1.9 1 8 b 3 2016-10-24 21:40:00 2.2 3 9 b 4 2016-10-24 21:45:00 4.0 4 10 b 5 2016-10-24 21:50:00 1.2 4
如果您希望缩短时间,可以先将if
和我的第二个else if
合并为一个if
语句与|
运算符,但这样可行原样。
声明的方式:
max( data$cat.id[data$x > 2 & data$category==c & data$cat.id < data$cat.id[i]])
作品就是如下:
cat.id
对应x
的值为&gt; 2,因此data$x > 2
部分data$category==c
)data$cat.id < data$cat.id[i]
)max()
)