2013-10-05 143 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