2013-10-05 98 views
1

我有一个3列,订单,放电,日期(数值)的大型数据集。有20年,每个订单每天排放价值观,它可以超越100替代循环和索引?

> head(dat) 
     Order Discharge date 
     1 0.04712 6574 
     2 0.05108 6574 
     3 0.00000 6574 
     4 0.00000 6574 
     5 3.54100 6574 
     6 3.61500 6574 

延长对于给定的顺序X,我愿与平均更换放电值在该日期的x + 1和x-1的放电量。我一直以粗略的方式进行for循环和索引,但处理需要一个多小时。我知道必须有更好的方法。

x <- 4 
    for(i in min(dat[,3]):max(dat[,3])) 
    dat[,2][dat[,3] == i & dat[,1] == x ] <- 
    mean(c(dat[,2][dat[,3] == i & dat[,1] == x + 1], 
    dat[,2][dat[,3] == i & dat[,1] == x - 1])) 

给人

> head(dat) 
    Order Discharge date 
     1 0.04712 6574 
     2 0.05108 6574 
     3 0.00000 6574 
     4 1.77050 6574 
     5 3.54100 6574 
     6 3.61500 6574 

如果放于订单4,日期6574已替换为1.77050。它有效,但速度很慢。

我应该指定我不需要在每个订单上进行此计算,但只有少数几个(总共117个中只有8个)。基于这个答案,我有以下几点。

dat$NewDischarge <- by(dat$Discharge,dat$date,function(x) 
    colMeans(cbind(c(x[-1],NA), x, 
    c(NA, x[-length(x)])), na.rm=T)) 

我想还是想出一个办法只有选择订单的值进行计算和我停留在一个for循环和索引的日期和订单的车辙。

+0

你有什么选择'x'的标准?是否有一个外部循环来确定你没有向我们展示'x'?这可能是相关的。 – Peyton

+0

顺序代表测量河流流量的河流站点。 X-1和X + 1基本上是上游和下游的台站。我希望从上游和下游站的某一天的平均排放量中适用当天的中间站。我已经单独确定了这些x(有8个),但是我可以将它们放入一个向量中并将其包含在函数中。 – user2850039

回答

0

我会用它去如下:

  1. 确保Order是一个因素。
  2. 对于每个订购,你现在有一个子问题:
    1. 排序date子数据帧。
    2. 每个Discharge -mean可以被“vectorally”制备: colMeans(cbind(c(Discharge[-1], NA), Discharge, c(NA, Discharge[-length(Discharge)])))
  3. 子问题可以处理一个简单的for循环或功能by。我宁愿by
  4. 您的数据已重新排列,但您可以轻松对其重新排序。

对于第2.2点,用一个简单的矢量想象它(或尝试它)并查看cbind操作的效果。这也迫使你考虑极限情况;第一个和最后一个排放值是如何计算的(无前置或前置日期)。

+0

这是一个很好的开始。我应该指出,我不需要在每个订单上进行这种计算,但只需要少数几个(总共117个中只有8个)。根据你的回答,我有以下几点。 'dat $ NewDischarge < - by(dat $ Discharge,dat $ date,function(x)colMeans(cbind(c(x [-1],NA),x,c(NA,x [-length(x)]) ),na.rm = T)) '。我试图找出一种方法,仍然只有选择订单的值才能计算出来,并且卡在for循环和日期和订单的索引中。 – user2850039

+0

这可能不起作用。 'by'很少返回要插入到data.frame中的矢量。你的第二个参数'by'按日期分割数据 - 在这种情况下,你正在采取几个Orders的意思。 既然你只有8个订单,你可以这样做: dat <-dat [order(dat $ date),] dat $ MeanDischarge < - NA for(o in c(1,3,4,5)) { rows = dat $ Order == 0 x = dat $ Discharge [rows] dat $ MeanDischarge [rows] = colMeans(...) } – MrGumble

0

有几种方法可以解决您的特定困境,但在遇到缓慢的for循环时要问的基本问题是“如何使用矢量化来替换此循环?” (好吧,也许你应该首先问一下“我应该......”)在你的情况中,你在循环日期,但是没有必要明确地做到这一点,因为只需抓住所有的行,其中dat$Order==x将隐式地抓住所有的日期。

您发布仅有一个日期,但我可以生成一些假的数据来说明该数据集:

generate.data <- function(n.order, n.date){ 
    dat <- expand.grid(Order=seq_len(n.order), date=seq_len(n.date)) 
    dat$Discharge <- rlnorm(n.order * n.date) 
    dat[, c("Order", "Discharge", "date")] 
} 

dat <- generate.data(10, 5) 

head(dat) 
# Order Discharge date 
# 1  1 2.1925563 1 
# 2  2 0.4093022 1 
# 3  3 2.5525497 1 
# 4  4 1.9274013 1 
# 5  5 1.1941986 1 
# 6  6 1.2407451 1 
tail(dat) 
# Order Discharge date 
# 45  5 1.4344575 5 
# 46  6 0.5757580 5 
# 47  7 0.4986190 5 
# 48  8 1.2076292 5 
# 49  9 0.3724899 5 
# 50 10 0.8288401 5 

这里的所有行,其中dat$Order==4,在所有日期:

dat[dat$Order==4, ] 
# Order Discharge date 
# 4  4 1.9274013 1 
# 14  4 3.5319072 2 
# 24  4 0.2374532 3 
# 34  4 0.4549798 4 
# 44  4 0.7654059 5 

你可以只需拿Discharge一栏,你就会得到你作业的左手边:

dat[dat$Order==4, ]$Discharge 
# [1] 1.9274013 3.5319072 0.2374532 0.4549798 0.7654059 

现在您只需要右侧,它有两个组成部分:排放口x-1和排放口x+1。你可以抓住这些你抢到x放电以同样的方式:

dat[dat$Order==4-1, ]$Discharge 
# [1] 2.5525497 1.9143963 0.2800546 8.3627810 7.8577635 
dat[dat$Order==4+1, ]$Discharge 
# [1] 1.1941986 4.6076114 0.3963693 0.4190957 1.4344575 

要获得新的价值,你需要的平行平均。 R没有一个pmean功能,但你可以cbind这些并采取rowMeans

rowMeans(cbind(dat[dat$Order==4-1, ]$Discharge, dat[dat$Order==4+1, ]$Discharge)) 
# [1] 1.8733741 3.2610039 0.3382119 4.3909383 4.6461105 

那么,你到底有:

dat[dat$Order==4, ]$Discharge <- rowMeans(cbind(dat[dat$Order==4-1, ]$Discharge, 
               dat[dat$Order==4+1, ]$Discharge)) 

你甚至可以使用%in%,使这项工作跨越你所有的x值。

请注意,这假设您的数据是有序的。

+0

这是完美的。 – user2850039