2016-08-17 95 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