2017-08-01 19 views
1

我有一個排序的數字輸入,看起來像這樣:R:合併排序的數字輸入間隔

1 1 10 
1 12 18 
1 16 30 
1 30 40 
2 35 45 

DF = structure(list(V1 = c(1L, 1L, 1L, 1L, 2L), V2 = c(1L, 12L, 16L, 
30L, 35L), V3 = c(10L, 18L, 30L, 40L, 45L)), .Names = c("V1", 
"V2", "V3"), row.names = c(NA, -5L), class = "data.frame") 

它是由第一列排序,然後第二個。現在我試圖在R中設計一個有效的函數(因爲我的輸入是成千上萬行),可以合併重疊的行,例如,第2行和第3行在三個位置(16,17和18)重疊, ,而第3行和第4行在一個位置(30)重疊,而第5行從第2行開始,因此它與其餘部分分開。總而言之,我想:

1 1 10 
1 12 40 
2 35 45 

不過,我與整合,說:「如果兩行是足夠接近對方參數掙扎,例如,在5個單位),然後將它們合併,否則不會在這種情況下,我想:

1 1 40 
2 35 45 

,因爲12-10 = 2 < 5.但是,如果參數設置爲1,則輸出將只是原來的:

1 1 10 
1 12 40 
2 35 45 

回答

2

這是一個wa Y:

library(data.table) 
setDT(DT) 

th = 5 
DT[, g := cumsum(V2 - shift(V3, fill = first(V2)) >= th), by=V1] 
DT[, .(V2 = first(V2), V3 = last(V3)), by=.(V1, g = rleid(V1, g))] 

# V1 g V2 V3 
# 1: 1 1 1 40 
# 2: 2 2 35 45 

# same code with th = 1 

# V1 g V2 V3 
# 1: 1 1 1 10 
# 2: 1 2 12 40 
# 3: 2 3 35 45 
+0

簡單地說,什麼是'setDT(DT)',我得到'錯誤:無法找到符號DT'。你的意思是'setDT(DF)'? – warship

+0

@戰艦哦對。是的,如果你在任何地方使用'DF',我都有'DT',它應該可以工作。或者,您可以編寫'DT = data.table(DF)'並跳過'setDT'步驟(僅將data.frame轉換爲data.table)。 – Frank

+0

只是好奇,'setDT(DF)','DT = data.table(DF)'和'DT = as.data.table(DF)'之間有區別嗎? 'setDT(DF)'似乎是最高效的,因爲它是通過引用來改變輸入的,所以不需要複製,對吧? – warship

0

這工作對你的玩具例如

df <- data.frame(ID=c(1,1,1,1,2), 
      X1=c(1,12,16,30,35), 
      X2=c(10,18,30,40,45)) 

df %>% 
    group_by(ID) %>%         # group wise operation by ID 
    mutate(lg=lag(X2+5,default=head(X2,1))) %>%  # for comparison, offset X2 column by +1 row and add value of 5 
    mutate(lt=lg<=X2) %>%       # check if lg <= X2 
    mutate(group=cumsum(lt != lag(lt,default=head(lt,1)))) %>% # make groups based on logical test in lt 
    group_by(ID,group) %>% 
    summarise(X1=min(X1), X2=max(X2))    # summarise data as min and max of X1 and X2 respectively 

輸出

 ID group X1 X2 
1  1  0  1 40 
2  2  0 35 45 
+0

我想你可以用一個突變序列做一個「mutate」調用。 – Frank

+1

你當然是對的。我列出他們步驟明智,使其更容易理解。這是我注意到的data.table動詞的一個優點...它看起來更簡潔 – CPak