2015-09-15 54 views
2

我被困在一個可能很簡單的問題 - 如何總結連續的重複行並刪除除第一行以外的所有行。而且,如果在兩個副本(例如2,na,2)之間存在NA,也可以將它們相加併除去第一個條目。 到目前爲止好,這裏是我的樣本數據R總結連續的重複行並刪除除第一行以外的所有行

ia<-c(1,1,2,NA,2,1,1,1,1,2,1,2) 
time<-c(4.5,2.4,3.6,1.5,1.2,4.9,6.4,4.4, 4.7, 7.3,2.3, 4.3) 
a<-as.data.frame(cbind(ia, time)) 

樣本輸出

 a 
    ia time 
1 1 4.5 
2 1 2.4 
3 2 3.6 
4 NA 1.5 
5 2 1.2 
6 1 4.9 
7 1 6.4 
8 1 4.4 
9 1 4.7 
10 2 7.3 
11 1 2.3 
12 2 4.3 

現在我想 1)概括連續IA的的「時間」列 - 即,和時間如果數字1出現兩次或更多次,則在本例中,第一行和第二列的時間總和爲4.5+2.4

2.)如果在兩個數字(ia列)之間有一個NA,它們是相同的(i.e., ia = 2, NA, 2),那麼也將所有這些時間相加。

3.)只保留ia的第一次出現,然後刪除其餘部分。

最後,我想有這樣的事情:

a 
     ia time 
    1 1 6.9 
    3 2 6.3 
    6 1 20.4 
    10 2 7.3 
    11 1 2.3 
    12 2 4.3 

我發現這對於總結,但它並沒有考慮到連續的因素

aggregate(time~ia,data=a,FUN=sum) 

,我發現這用於刪除

a[cumsum(rle(as.numeric(a[,1]))$lengths),] 

儘管rle方法保持最後一項,我會w螞蟻保持第一。我也不知道如何處理NAs

如果我有一個1-NA-2的模式,那麼NA不應該與他們中的任何一個進行計數,在這種情況下,應該刪除NA行。

+1

如果你有'1-NA-2'的模式怎麼辦? NA應該計爲1,2還是兩者都不?另外,連續有多少個NA? –

+0

如果我有1-NA-2的模式,那麼NA不應該與他們中的任何一個計數,在這種情況下NA應該被移除。是的,連續可能會有一個以上的NA。 – LaNeu

+0

澄清:當我說連續超過一個NA時,我的意思是連續超過一個NA。例如,是否有可能按順序存在「1 NA NA 1」?在那種情況下,新生兒是否應計爲1? –

回答

3

您首先需要用它們周圍的值替換NAs序列(如果它們相同)。 This answer顯示了動物園的na.locf功能,其用最後的觀察來填充NA。通過測試它是否是相同的,當你攜帶值向後或向前,就可以過濾掉你不想在NAS,然後執行弘揚:

library(dplyr) 
library(zoo) 

a %>% 
    filter(na.locf(ia) == na.locf(ia, fromLast = TRUE)) %>% 
    mutate(ia = na.locf(ia)) 
#> ia time 
#> 1 1 4.5 
#> 2 1 2.4 
#> 3 2 3.6 
#> 4 2 1.5 
#> 5 2 1.2 
#> 6 1 4.9 
#> 7 1 6.4 
#> 8 1 4.4 
#> 9 2 7.3 
#> 10 1 2.3 
#> 11 2 4.3 

現在你已經固定的那些來港定居,就可以使用cumsum組連續組值。完整的解決方案是:

result <- a %>% 
    filter(na.locf(ia) == na.locf(ia, fromLast = TRUE)) %>% 
    mutate(ia = na.locf(ia)) %>% 
    mutate(change = ia != lag(ia, default = FALSE)) %>% 
    group_by(group = cumsum(change), ia) %>% 
    summarise(time = sum(time)) 
result 
#> Source: local data frame [6 x 3] 
#> Groups: group [?] 
#> 
#> group ia time 
#> (int) (dbl) (dbl) 
#> 1  1  1 6.9 
#> 2  2  2 6.3 
#> 3  3  1 15.7 
#> 4  4  2 7.3 
#> 5  5  1 2.3 
#> 6  6  2 4.3 

如果你想擺脫group柱,使用附加線:

result %>% 
    ungroup() %>% 
    select(-group) 
+0

嗨,再次感謝您的幫助。我想知道如何處理額外的列 - 比如我在數據框z <-c(1,1,1,1,1,1,1,1,1,1,1,1)中也有列z,它應該不要總結或任何事情,只有行應刪除如上(即連同ia的連續)..你知道如何處理這個? – LaNeu

+0

@LaNeu你可以添加'z = z [1]'作爲參數來總結 –

+0

,這聽起來很簡單,而且效果很好 - 謝謝! – LaNeu

2
nas <- which(is.na(df$ia)) 
add.index <- sapply(nas, function(x) {logi <- which(as.logical(df$ia)) 
    aft <- logi[logi > x][1] 
    fore <- tail(logi[logi< x], 1) 
    if(df$ia[aft] == df$ia[fore]) aft else NA}) 
df$ia[nas] <- df$ia[add.index] 
df <- df[complete.cases(df),] 

首先,我們確定該列的NA值由相同的值所包圍。如果是,則周圍值取代NA。如果數據具有連續的NA值,則沒有問題。

接下來我們通過小組操作做一個標準總和。 cumsum允許我們根據數字的變化創建一個獨特的組。

df$grps <- cumsum(c(F, !df$ia[-length(df$ia)] == df$ia[-1]))+1 
aggregate(time ~ grps, df, sum) 
# grps time 
# 1 1 6.9 
# 2 2 6.3 
# 3 3 20.4 
# 4 4 7.3 
# 5 5 2.3 
# 6 6 4.3 

這是一個base R的方法。使用像dplyrzoodata.table這樣的軟件包,可以使用不同的選項,因爲它們具有專門的功能,可以完成我們在此處執行的操作。

+0

如果連續有多個NA,則此解決方案不起作用。 –

+0

@DavidRobinson我在第4行用兩個NA值測試了你的函數。對於值'2',返回NA。根據OP的預期產出,這不會發生。用我的解決方案'4.8'返回。 –

+0

我對「行」這個詞的誤解。在一個數據框的一行中,我不是指兩個以上的新來港定居人士;我的意思是在'ia'列中有兩個以上連續的NA,例如,如果'aia [4]'和'aia [5]'都是NA。 (也就是說,[連續成語]](http://idioms.thefreedictionary.com/in+a+row)) –

5

隨着data.table(如RHertel建議na.locf):

library(data.table) 
library(zoo) 

setDT(a)[na.locf(ia, fromLast=T)==na.locf(ia), sum(time), cumsum(c(T,!!diff(na.locf(ia))))] 
# id V1 
#1: 1 6.9 
#2: 2 6.3 
#3: 3 20.4 
#4: 4 7.3 
#5: 5 2.3 
#6: 6 4.3 
+1

即使它們後面跟着不同的值,這也會帶有值前進的值,這違反了此處描述的行爲[http://stackoverflow.com/questions/32588433/R-和連續重複的,行和移除,所有的,但是一/ 32588960#comment53030951_32588433)。例如,試着用'a < - data.frame(ia = c(1,NA,2),time = 1)' –

+0

我加了一個掩碼來處理這個,但是這增加了兩倍的行數.. –

+0

'by ='in'data.table'接受表達式。 – Arun