2017-08-14 52 views
1

我包含三個變量,其中包含三個唯一ID,每個都有多個記錄。見下面排除R中特定行下面的所有記錄

ID <- c(rep(1,7), rep(2,6), rep(3,5), rep(4,6)) 
t <- c(seq(1,7), seq(1,6), seq(1,5), rep(2,6)) 
y <- c(rep(6,7), rep(1,6), rep(6,5), rep(0.2,6)) 
z <- c(5,0,0,0,1,0,0,0,0,-1,0,0,0,4,2,NaN,0,1,0,0,1,Inf,Inf, Inf) 
dat1 <- data.frame(ID, t, y, z) 

對於每個ID,如果Z值小於0(負),NaN的,天道酬勤,或-Inf,我需要排除的記錄和它下面的所有記錄。

對於這個數據,新處理的數據是這樣的:

ID <- c(rep(1,7), rep(2,2), rep(3,2), rep(4,3)) 
t <- c(seq(1,7), seq(1,2), seq(1,2), rep(2,3)) 
y <- c(rep(6,7), rep(1,2), rep(6,2), rep(0.2,3)) 
z <- c(5,0,0,0,1,0,0,0,0,4,2,0,0,1) 
dat2 <- data.frame(ID, t, y, z) 

回答

6

ave做到這一點,作爲一個羣體,被替代。使用cumsum計數器然後確定要刪除的任何後續行:

dat1[with(dat1, ave(z < 0 | (!is.finite(z)), ID, FUN=cumsum) == 0),] 

快速檢查,看它們是否匹配,與rownames除外不排隊:

all.equal(
    dat2, 
    dat1[with(dat1, ave(z < 0 | (!is.finite(z)), ID, FUN=cumsum) == 0),], 
    check.attributes=FALSE 
) 
#[1] TRUE 
+0

與'cummin'基本相同的是'dat1 [as.logical(ave(dat1 $ z,dat1 $ ID,FUN = function(x)cummin(is.finite(x)&x> = 0))),] '。可以通過更接近地匹配你的論點來清理一下。 – lmo

0

這個工作對你的樣本數據。可能不是最快的解決方案。

mutate(dat1, rownumber = 1:nrow(dat1)) -> dat1 

for(i in unique(dat1$ID)) { 
    firstMiss = min(filter(dat1, ID==i & 
          (z %in% c(NaN, Inf, -Inf) | 
           z < 0))$rownumber, 
        max(filter(dat1, ID==i)$rownumber)+1, 
        na.rm=TRUE) 
    dat1 <- filter(dat1, !(ID==i & rownumber >= firstMiss)) 
} 
dat2 <- select(dat1, -rownumber) 
2

如果您ID列按升序排序,你可以用

dat2 <- dat1[unlist(tapply(dat1$z, dat1$ID, function(x) 
      cumsum(x<0 | x %in% c(NaN, -Inf, Inf))==0)),] 

dat2 
    ID t y z 
1 1 1 6.0 5 
2 1 2 6.0 0 
3 1 3 6.0 0 
4 1 4 6.0 0 
5 1 5 6.0 1 
6 1 6 6.0 0 
7 1 7 6.0 0 
8 2 1 1.0 0 
9 2 2 1.0 0 
14 3 1 6.0 4 
15 3 2 6.0 2 
19 4 2 0.2 0 
20 4 2 0.2 0 
21 4 2 0.2 1 
+1

雖然這依賴於按順序排序的ID。試着用'dat1 < - rbind(dat1 [dat1 $ id == 2,],dat1 [dat1 $ ID!= 2,])',你會看到它給出了一些意想不到的結果。 – thelatemail

+0

是的 - 'tapply'將它們視爲因素並對它們進行分類。我在上面加了一個警告。謝謝。使用'ave'解決方案更好。 –

0

只是爲了laffs:

library(dplyr) 
dat1 %>% group_by(ID) %>% 
     mutate(non_positive = min(which(lead(z,1) < 0 | 
           !is.finite(lead(z,1)) | row_number() == n()))) %>% 
     filter(row_number() <= non_positive) %>% 
     select(-non_positive) 

# # A tibble: 14 x 4 
# # Groups: ID [4] 
#  ID  t  y  z 
# <dbl> <dbl> <dbl> <dbl> 
# 1  1  1 6.0  5 
# 2  1  2 6.0  0 
# 3  1  3 6.0  0 
# 4  1  4 6.0  0 
# 5  1  5 6.0  1 
# 6  1  6 6.0  0 
# 7  1  7 6.0  0 
# 8  2  1 1.0  0 
# 9  2  2 1.0  0 
# 10  3  1 6.0  4 
# 11  3  2 6.0  2 
# 12  4  2 0.2  0 
# 13  4  2 0.2  0 
# 14  4  2 0.2  1