2016-07-28 98 views
0

我試圖提取1950年至2015年期間幾個儀表站的年平均降雨量。降雨數據集由每日測量值組成。有條件地去除R中的分組數據的行

在計算每個單獨站點的年平均值之前,我需要過濾數據,以便每個月必須有> 15天的數據值。

這怎麼可能在R?

讓這成爲一個工作示例:

id<-rep(c("Station_1","Station_2","Station_3"),length(1),each=1080) 
year<-rep(c(1950:1952),length(1:3),each=360) 
month <- rep(c(1:12),length(1:9),each=30) 
day <- rep(c(1:30),length(1:108)) 
value<-runif(3240, min=0, max=10) 

df<-data.frame(cbind(id,year,month,day,value)) 

我想是這樣的:

result<-df %>% 
    group_by(id,year,month) %>% 
    summarise(No._of_days=n(),mean_month=mean(value)) 
result<-result[!(result$No._of_days<15),] 
result<-result %>% 
    group_by(id,year) %>% 
    summarise(No._of_months=n(),mean_year=mean(mean_month)) 

然而,這導致了錯誤的解決辦法,因爲我的「從平均平均」服用。

感謝您的任何建議。

+0

請停止使用'data.frame(cbind(...))'。 'data.frame()'就足夠了。看看'?data.frame'。 – Arun

+0

謝謝Sathish,aichao,sebolus和NJBurgo的快速和正確答覆 - 非常感謝您的幫助!所有的解決方案都可以工作,但我會堅持使用aichao,就像我最適合使用dplyr一樣。 抱歉,關於錯誤地表述數據框 - 現在我會離開「原樣」,因爲這裏的每個人都已經就如何正確構建它添加了良好的評論。 –

回答

1

原始數據:刪除創建數據框時的默認因式分解變量。

df<-data.frame(id = id,year = year, month = month, day = day, value = value, stringsAsFactors = FALSE) 

組數據由id, year, month,並得到天的使用.N內部變量子集的數量。接下來,鏈接結果(類似於dplyr中的%>%)。現在分組id, year,然後是條件N > 15,最後計算該子集的mean降雨量並存儲在avg_rainfall中。

setDT參照

library("data.table") 
setDT(df)[, .(value, .N), by = .(id, year, month)][N > 15, .(avg_rainfall = mean(value)), by = .(id, year)] 

#   id year avg_rainfall 
# 1: Station_1 1950  4.852840 
# 2: Station_1 1951  5.138069 
# 3: Station_1 1952  4.934006 
# 4: Station_2 1950  4.870335 
# 5: Station_2 1951  5.179425 
# 6: Station_2 1952  5.055026 
# 7: Station_3 1950  4.959524 
# 8: Station_3 1951  5.049996 
# 9: Station_3 1952  4.927548 
+0

非常感謝你的快速和清晰的解決方案 - 我真的很感激!關於錯誤地制定數據框的道歉 - 下次將不再考慮。 –

+0

還有一個問題,而不是過濾超過15天的行,如果連續15個單元是NAs,我可以過濾嗎?例如... df [,!apply(is.na(df),2,function(x) {v < - cumsum(x); any(diff(v,2)== 2)})]。 ....如果需要,我會更新我的問題。改編自這篇文章:http://stackoverflow.com/questions/15186697/conditional-row-removal-based-on-number-of-nas-within-the-row –

+0

如果你的意圖是在計算平均值之前刪除NA ,你可以在平均函數內傳遞'na.rm = TRUE'。例如:'avg_rainfall = mean(value,na.rm = TRUE)' – Sathish

1

有幾件事情,例子data.frame轉換數據幀到數據表,因爲你如何創建它,一切的代碼作爲一個因素。用這個代替:

df<-data.frame(id = id, 
       year = year, 
       month = month, 
       day = day, 
       value = value) 

然後(我很抱歉,我不是一個magrittr風扇)下面的工作:

# Filter into a new data.frame 
df2 <- semi_join(df, 
      filter(summarise(group_by(df, year, month), N = n()), N > 15), 
      by = c(year = "year", 
       month = "month")) 

# Summarise 
summarise(group_by(df2, id), 
      value = mean(value, na.rm = TRUE)) 
+0

感謝@NJBurgo,對於這個問題的出色解決方案和快速響應!乾杯,C –

0

只注重代碼,它爲我工作,一些修改。例如。你寫了你想要> 15天的數據,但選擇> 14,也確保值是數字,而不是你的DF的因素。

`df<-data.frame(cbind(id,year,month,day,value)) 
df$value<- as.numeric(as.character(df$value)) 
    result<-df %>% 
    group_by(id,year,month) %>% 
    summarise(No._of_days=n(),mean_month=mean(value)) 
result<-result[!(result$No._of_days<=15),] 
result<-result %>% 
    group_by(id,year) %>% 
    summarise(No._of_months=n(),mean_year=mean(mean_month))` 

代碼:從數學的角度來看,這種方法對我來說並不清楚。爲什麼要排除每年總計少於16次測量的所有內容?如果您的測量結果是真實存在的,請考慮使用您在任何月份的值,並將數據集中所有缺失的天數計算在內(例如,對每個測站使用迴歸,年份(連續),日曆周,前後降雨天)。

使用 dplyrmagrittr
+0

感謝@ sebolus爲您的解決方案 - 我真的很感激快速週轉。回覆。數學,我的子集方法是完成的,因爲如果在制定年平均數時有幾個月沒有得到充分的體現,那麼一年中的降雨季節差異可能會丟失。雖然你的推理方法是可行的,但現有文獻中有關降雨/風/溫度數據等的常用方法是簡單地排除這些月份(如果有必要的話,還有幾年)以避免這個問題。目前,我會堅持使用子集方法。謝謝,蔡 –

0

稍微不同的方法:

library(dplyr) 
set.seed(42) # this is only so we get consistent results to compare 

# then generate id, year month, day, and value using your code 
# but use what @NJBurgo used to generate df 

df<-data.frame(id = id, 
     year = year, 
     month = month, 
     day = day, 
     value = value) 

result <- df %>% 
    group_by(id,year,month) %>% 
    mutate(No._of_days=n()) %>% 
    filter(No._of_days > 15) %>% ## keep only rows with number of days greater than 15 
    ungroup() %>% 
    group_by(id,year) %>% 
    summarize(mean_year=mean(value)) 

# using set.seed(42), you should get 
print(result) 
##   id year mean_year 
##  <fctr> <int>  <dbl> 
##1 Station_1 1950 4.954538 
##2 Station_1 1951 4.878709 
##3 Station_1 1952 4.737996 
##4 Station_2 1950 4.942614 
##5 Station_2 1951 4.876992 
##6 Station_2 1952 5.193242 
##7 Station_3 1950 5.235278 
##8 Station_3 1951 4.955401 
##9 Station_3 1952 4.905078 

的關鍵是filtergroup_by行(由idyear,並month分組)。我也用mutate代替summarise來創建​​。然後ungroup(),然後重新組合idyear來計算平均值。

順便說一句,你的測試用例不足以測試這個,因爲所有的月份都有30天。

希望這會有所幫助。

+0

謝謝@aichao - 我喜歡這個解決方案,特別是我最舒服的工作與dplyr。 關於數據框的觀點 - 我認爲重要的是要包括一個例子,即使它是一個窮人!我之前並沒有製作過一個虛擬數據集,也不想花費太長時間來研究如何創建真實數據的更真實的複製,因爲知道過濾的概念在任何時候都會保持不變。 非常感謝 –