使用开始和结束时间从单独的数据帧中提取值

时间:2016-03-28 20:38:51

标签: r loops posixct

我已经解决了R中的统计数据和数据库问题中的很多问题并且是新用户,但我还没有想出循环和编程。我坚持这个,只是想不出来。我有一个数据框,其中包含开始日期和结束日期以及值TP(总磷)。

begin = c("2015/11/16 17:45",   "2015/11/17 17:45", "2015/11/18 17:45", "2015/11/19 17:45", "2015/11/20 17:45", "2015/11/21 17:45")
end = c("2015/11/17 17:45", "2015/11/18 17:45", "2015/11/19 17:45", "2015/11/20 17:45", "2015/11/21 17:45", "2015/11/22 17:45")
bottle =    c(1,    2,  3,  4,  5,  6)
tp =    c(10,   200,    100,    73, 38, 50)
data=data.frame(begin, end, bottle, tp)

我需要根据每个行的开始和结束日期将TP乘以另一个数据帧的值之和。另一个数据框在下面的缩短版本中....

set.seed(1)
time = seq.POSIXt(from=as.POSIXct('2015-11-15',tz=''),
              to=as.POSIXct('2016-11-25',tz=''),
              by = as.difftime(0.25,units="hours"))
level_m= runif(n = length(time), min = .01, max = .06)
time <- as.data.frame(time)
level_m <- as.data.frame(level_m)
# as dataframe
water_level <- cbind(time, level_m)

我想让它为第一个称为数据的数据帧的每一行做这件事。我所尝试的是使用数据库方法,其中两个数据帧被合并和聚合,但它并不真正令人满意,因为最后一个值将总结太多数据而不仅仅是我需要的范围...而且它做得比我真正需要的还多

rng <- cut(water_levle$time, 
       breaks=c(data$begin, max(data$end)),
                include.lowest=T)
test <- aggregate(cbind(count=1, sum=water_level$level_m)~rng, FUN=sum)

我希望我做得对,因为这是我在这里提出的第一个问题。谢谢,比尔

2 个答案:

答案 0 :(得分:1)

良好的第一篇文章,您可以轻松地重现您的数据。

我认为您正在寻找以下内容。它将指定日期范围内的m_level相加,并将t乘以tp。 level.sum是中间人,为了清楚起见,我将其留在数据框中。

for( n in 1:nrow(data)){
#Defined here for clarify in the subset
  begin_d <- as.Date(data[n,'begin'])
  end_d <- as.Date(data[n,'end'])
  time_d <- as.Date(water_level$time)

  data[n,'level.sum'] <- sum(water_level[time_d>=begin_d & time_d<=end_d, "level_m"])
  data[n,'tp.mult.sum']<- (data[n,"tp"]*data[n,"level.sum"])
}

我编辑它不使用subset(),因为它仅供交互使用。

一般说明:使用dataframe['selection criteria','column name']之类的代码选择数据框的元素是一个有用的工具。

我运行它而不是你拥有的最终代码块,它似乎运行正常。

答案 1 :(得分:0)

不是在water_level$time中找到data$begin,而是在water_level$time中提供每个data$begin(和data$end)出现的位置:< / p>

#convert to date-time
data$begin = as.POSIXct(data$begin)
data$end = as.POSIXct(data$end)

from = findInterval(data$begin, water_level$time)
to = findInterval(data$end, water_level$time)
from
#[1] 168 264 360 456 552 648
to
#[1] 264 360 456 552 648 744
#e.g. `water_level$time[168:264]` is ` >= data$begin[1]` and ` <= data$end[1]` etc

并且 - 假设nrow(data)和/或to - from不是很大 - 我们可以简单地遍历每个from:to以找到water_level$level的相应总和:

mapply(function(begin, end, level) sum(level[begin:end]), 
       from,
       to, 
       MoreArgs = list(level = water_level$level))
#[1] 3.495112 3.182623 3.419295 3.466763 3.504436 3.450281

#and multiply
#... * data$tp