2016-08-17 104 views
1

第一觀察我有這樣的示例:更換0時的水平因子R

data <- structure(list(mmsi = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L, 2L), .Label = c("a", "b"), class = "factor"), 
    tr = c(1, 1, 1, 0, 2, 2, 0, 4, 4, 0, 5, 5)), .Names = c("mmsi", 
"tr"), row.names = c(NA, -12L), class = "data.frame") 

我想在列trtr先前值替換每個0,對於每個mmsi

此功能以及對樣本:

for (i in levels(data$mmsi)) { 
data$test <- na.locf(with(data, { is.na(tr) <- tr == 0; tr }), fromLast = FALSE)} 

但是,當我與一個更大的樣本玩,有一個問題apears:如果第一個值是0的話,我有一個錯誤(因爲它無法找到以前的值...)。

例如,如果我與

data <- structure(list(mmsi = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L, 2L), .Label = c("a", "b"), class = "factor"), 
    tr = c(0, 1, 1, 0, 2, 2, 0, 4, 4, 0, 5, 5)), .Names = c("mmsi", 
"tr"), row.names = c(NA, -12L), class = "data.frame") 

編輯小樣本列tr從這裏開始與0而不是1以前的樣本。如果我申請相同的功能for (i in levels(data$mmsi)) { data$test <- na.locf(with(data, { is.na(tr) <- tr == 0; tr }), fromLast = FALSE)}話,我當然有錯誤

Error in `$<-.data.frame`(`*tmp*`, "test", value = c(1, 1, 1, 2, 2, 2, : 
    replacement has 11 rows, data has 12 

- >功能無法取代(列tr的第一個值)

我想我需要的價值我的變化在我的函數中,當tr中的第一個級別出現時,首先編輯0行。新行應該用下面的非零值替換0。然後,其餘的功能是好的。

我尋找這個新列的輸出是:

data$test 
[1] 1 1 1 1 2 2 2 4 4 4 5 5 

任何想法如何得到這個?

回答

1

我們可以通過功能組中的一個來做到這一點。將'data.frame'轉換爲'data.table'(setDT(data)),按'mmsi'分組,應用na.locf(從zoo)在將'0'值替換爲'NA'並且使用選項na.rm = FALSE後,第二個na.locffromLast = TRUE將起始0(又名NA)替換爲下一個值。

library(data.table) 
library(zoo) 
setDT(data)[, test := na.locf(na.locf(replace(tr, tr==0, NA), 
        na.rm=FALSE), fromLast=TRUE), by = mmsi] 
data 
# mmsi tr test 
# 1: a 0 1 
# 2: a 1 1 
# 3: a 1 1 
# 4: a 0 1 
# 5: a 2 2 
# 6: a 2 2 
# 7: a 0 2 
# 8: b 4 4 
# 9: b 4 4 
#10: b 0 4 
#11: b 5 5 
#12: b 5 5 

我們也能做到這一點,而無需使用na.locf

setDT(data)[, test := pmax(pmax(tr, shift((NA^!tr) * tr), na.rm = TRUE),1), mmsi] 
+0

偉大的,它似乎運作得非常好(用'tr'是數字;))。我嘗試用'for for(i in levels(data $ mmsi))獲得相同的步驟數據$ test = data $ rl [!! data $ rl] [cumsum(!! data $ rl)+1] data $ test [is.na(data $ test)] < - 0 data $ test < - na.locf(with(data,{is.na(test)< - test == 0; test}),fromLast = TRUE )'但它沒有在你的答案之前得到它。謝謝! – Floni