以下是我的数据框架的样子:
set.seed(1)
df <- data.frame(Period = seq(1:13)
, Units = c(1,2,rep(1, 3), rep(2, 4), rep(3, 4))
, Temperature = rnorm(13, 25, 5)
)
我想测量单位值变化前后的平均温度。最重要的是,我想仅在单位的价值在变化前后至少4个时期内保持稳定时才测量平均值。
所以,我认为这个过程可以分解为几个部分:
对于第一步,我创建一个包含单位变化位置的变量:
for (i in 1:length(which(diff(df$Units) != 0))){
assign(paste("change_", i, sep=""), which(diff(df$Units) != 0)[i])
}
第二步,我使用IF-ELSE检查,然后将三分之一嵌套在其中:
if (change_1>=4
&&(df$Units[change_1] == df$Units[change_1-1])
&& (df$Units[change_1] == df$Units[change_1-2])
&& (df$Units[change_1] == df$Units[change_1-3])
&& (df$Units[change_1] == df$Units[change_1-4])){
old_mean <- mean(c(df$Temperature[change_1]
, df$Temperature[change_1-1]
, df$Temperature[change_1-2]
, df$Temperature[change_1-3]))
new_mean <- mean(c(df$Temperature[change_1+1]
, df$Temperature[change_1+2]
, df$Temperature[change_1+3]
, df$Temperature[change_1+4]))
}
当然,如果第一次发生变化,IF条件为FALSE,那么在 else if 我将检查 change_2 之前和之后是否有4个稳定单位。所以最后,使用上面的例子,对于old_mean,我希望代码输出mean的结果(df $ Temperature [6:9])或26.22633。
这不是最佳选择,因为我想在几个数据框架中运行它,其中更改的数量会有所不同。 因此,我需要以某种方式根据有多少change_n变量来管理else语句的数量。
任何人都可以建议如何自动告诉R应该有多少Else-Ifs? 如果你能提出更实际的工作方式,还有其他要点。
答案 0 :(得分:2)
每次发生更改时生成一个新变量并不是完成您想要做的事情的理想方式。一般情况下(即,不仅仅是在R编程时),如果您正在考虑动态生成一堆变量,那么通过创建数组或向量来提供更好的服务。
在这种情况下,创建一个向量,该向量将索引作为一组连续相同单元类型的一部分的每个单元。然后,使用此新向量和by()
函数,您可以获得平均值。一些代码是:
rep.threshold <- 4 #variable that will let you change how many repetitions before it "counts"
units.grp <- rep(0,length(df$Units)) #vector of indices for units
grp.id <- 1 #variable to store current index
repeats <- 1 #variable that tracks how many time unit has repeated
for(i in 2:length(df$Units)){
#if current unit equal to last unit, increment number of repeats counted so far
if(df$Units[i]==df$Units[i-1]) repeats <- repeats+1
#otherwise, reset repetition count and increment group if at the end of a running group
else{
if(repeats>=rep.threshold) grp.id <- grp.id+1
repeats<-1
}
#if there have been enough repeats, write group index into vectorfor all matches
if(repeats>=rep.threshold) units.grp[(i-rep.threshold+1):i]<-rep(grp.id,rep.threshold)
}
对于您的示例数据框,上面的代码将生成[0 0 0 0 0 1 1 1 1 2 2 2 2]
现在,您可以使用by(df$Temperature, units.grp, mean)
来获取每个索引组的平均值(因为所有温度不足以重复的平均值,将显示为组0)。