2012-11-29 34 views
15

分裂以填補LOCF的NA我已經與該國變量作爲因子和變量的值以下的數據幀(簡化的)已經缺失值:如何通過在數據幀的因素,因國家

country value 
AUT  NA 
AUT  5 
AUT  NA 
AUT  NA 
GER  NA 
GER  NA 
GER  7 
GER  NA 
GER  NA 

的以下生成上述數據幀:

data <- data.frame(country=c("AUT", "AUT", "AUT", "AUT", "GER", "GER", "GER", "GER", "GER"), value=c(NA, 5, NA, NA, NA, NA, 7, NA, NA)) 

現在,我想使用結轉(LOCF)最後觀察的方法,以取代在每個國家子集中的NA值。我知道動物園包中的命令na.locfdata <- na.locf(data)會給我下面的數據幀:

country value 
AUT  NA 
AUT  5 
AUT  5 
AUT  5 
GER  5 
GER  5 
GER  7 
GER  7 
GER  7 

然而,功能只能由國家分裂個別子使用。以下是我需要的輸出:

country value 
AUT  NA 
AUT  5 
AUT  5 
AUT  5 
GER  NA 
GER  NA 
GER  7 
GER  7 
GER  7 

我想不出一種簡單的方法來實現它。在開始for循環之前,我想知道是否有人對如何解決這個問題有任何想法。

非常感謝!

+0

你可能會得到如果您編輯問題以包含合理的測試數據結構,則可以得到更快的響應。 –

+0

你想[動物園:: na.locf()](http://www.inside-r.org/packages/cran/zoo/docs/na.locf)! – smci

回答

10

這裏有一個ddply解決方案。試試這個

library(plyr) 
ddply(DF, .(country), na.locf) 
    country value 
1  AUT <NA> 
2  AUT  5 
3  AUT  5 
4  AUT  5 
5  GER <NA> 
6  GER <NA> 
7  GER  7 
8  GER  7 
9  GER  7 

編輯ddply幫助,您可以找到

.variables: variables to split data frame by, 
as quoted variables, a formula or character vector. 

所以另一個替代方案得到你想要的是什麼:

ddply(DF, "country", na.locf) 
ddply(DF, ~country, na.locf) 

注意.variablesDF$variable更換是不允許的,這就是爲什麼當你這樣做時出現錯誤。

DF是你data.frame

+0

非常感謝!正是我需要的。我之前嘗試過'ddply',使用'ddply(DF,DF $ country,na.locf)',但這不起作用。使用'。()'符號有什麼區別? – rp1

+0

@ rp1看我的編輯。 –

5

拆分的子集data.frameby和使用na.locf

do.call(rbind,by(data,data$country,na.locf)) 

如果你想刪除的行名稱:

do.call(rbind,unname(by(data,data$country,na.locf))) 
+0

'do.call'和'by'一起工作良好。 –

+0

謝謝,這也適用。但是,我將不得不重新將行名稱重命名爲'seq_len(nrow(data))'。所以,我選擇了上面的答案。但是,您的解決方案可能計算速度更快,因爲對於大型數據集,「ddply」似乎很慢。 – rp1

+0

不錯的基礎解決方案:D +1 –

1

如果速度是考慮那麼這unstack/stack溶液爲約4比我的系統上別人快,雖然它確實意味着代碼稍長線6倍:

stack(lapply(unstack(data, value ~ country), na.locf, na.rm = FALSE)) 
3

你只需要按國家分割,然後做一個zoo::na.locf()或na.fill,填充到右邊。 下面是一個明確顯示na的三組件arg語法的示例。填寫:

library(plyr) 
library(zoo) 

data <- data.frame(country=c("AUT", "AUT", "AUT", "AUT", "GER", "GER", "GER", "GER", "GER"), value=c(NA, 5, NA, NA, NA, NA, 7, NA, NA)) 

# The following is equivalent to na.locf 
na.fill.right <- function(...) { na.fill(..., list(left=NA,interior=NA,right="extend")) } 

ddply(data, .(country), na.fill.right) 

    country value 
1  AUT <NA> 
2  AUT  5 
3  AUT  5 
4  AUT  5 
5  GER <NA> 
6  GER <NA> 
7  GER  7 
8  GER  7 
9  GER  7 
+0

@Gregor,所以OP也想按國家分割,我錯過了那個和'na.locf'的提到,他們被埋在了第三段。現在完美運作。通常標題和第一段應該說明問題,我不明白你爲什麼沒有解決這些問題,現在我只是做了。在過去的一年半中,你們任何一個人都可以而且應該糾正這一點。你現在可以刪除你的downvote。 – smci

11

ddply解決方案的現代版是使用包裝dplyr

library(dplyr) 
DF %>% 
    group_by(county) %>% 
    mutate(value = na.locf(value, na.rm = F))  
+1

對於dplyr版本+1。 @Gregor,請注意,您需要將'na.rm = F'添加到'na.locf()'調用中。否則這會引發錯誤。 – Felix

+0

謝謝,費利克斯---編輯in。 – Gregor

+0

是否有辦法一次爲多個列執行此操作? –

2

的tidyverse方式,雖然沒有使用LOCF是:

library(tidyverse) 

data %>% 
    group_by(country) %>% 
    fill(value) 

Source: local data frame [9 x 2] 
Groups: country [2] 

country value 
(fctr) (dbl) 
1  AUT NA 
2  AUT  5 
3  AUT  5 
4  AUT  5 
5  GER NA 
6  GER NA 
7  GER  7 
8  GER  7 
9  GER  7