2017-02-07 35 views
0

我有興趣從數據幀中提取信息,其中數據幀中給定條目的值與以前不同。下面是一個例子幀:在前一行中具有不同值的快速拉數據幀行

df <- data.frame(name = rep("a",5), val1 = c(1,1,2,2,2), val2 = c(10,11,12,13,14)) 

> df 
    name val1 val2 
1 a 1 10 
2 a 1 11 
3 a 2 12 
4 a 2 13 
5 a 2 14 

我對提取行2和3,其中從1 val1變化爲2我可以通過在數據幀中的每個條目遍歷做到這一點的信息,跟蹤以前的val1這樣,當它改變時,我可以拉兩個相關的行,但我想知道是否有一個更快或更有效的方式來做到這一點,當數據幀非常大。 R通常比迭代有更快的提取信息的方式,但我不確定在這裏使用什麼。

回答

2

的一種方法是使用diff和邏輯子集:

keepers <- diff(df$val1) 
df[as.logical(c(0, keepers) + c(keepers, 0)),] 
    name val1 val2 
2 a 1 11 
3 a 2 12 

diff捕獲值的變化。 0被前置並追加以捕獲變化後的第一行和變化前的最後一行,並將這些向量相加在一起,產生1和0的向量。 as.logical將此變成一個邏輯向量,用於子行的子集。

1

這與選擇組的第一行和最後一行基本相同。從那裏你可以刪除第一行和最後一行。一個簡單的數據表的解決辦法是:

library(data.table) 
zz=data.table(df) 
yy=zz[, .SD[c(1,.N)], by=val1] 
yy[2:(nrow(yy)-1)] 
0

我們可以使用lagdplyr得到它並不像前一個類似的,然後也通過從指數中減去1選擇一個行之上的行的索引。

library(dplyr) 
i1 <- which(df$val1 != lag(df$val1)) 
df[sort(c(i1, i1-1)),] 

#name val1 val2 
#2 a 1 11 
#3 a 2 12 

又如,

df <- data.frame(name=rep("a", 7),val1=c(1,1,2,2,2,3, 3), val2=c(10,11,12,13,14, 15, 16)) 
df 
df 
# name val1 val2 
#1 a 1 10 
#2 a 1 11 
#3 a 2 12 
#4 a 2 13 
#5 a 2 14 
#6 a 3 15 
#7 a 3 16 

i1 <- which(df$val1 != lag(df$val1)) 
df[sort(c(i1, i1-1)),] 

# name val1 val2 
#2 a 1 11 
#3 a 2 12 
#5 a 2 14 
#6 a 3 15 
2

隨着diff你可以採取的事實,diff給您少於行數一個價值優勢。附:

which(diff(df$val1)==1) + 0:1 
# instead of '==1' you can also use '>0' or '!=0': which(diff(df$val1)!=0) + 0:1 

你得到的變更後的行的前一個索引和行:

> which(diff(df$val1)==1) + 0:1 
[1] 2 3 

因此:

df[which(diff(df$val1)==1) + 0:1, ] 

導致期望的結果:

name val1 val2 
2 a 1 11 
3 a 2 12 

另一個不錯R-TRIC被比較的headtail結果:(!關閉過程)

which(head(df$val1,-1) != tail(df$val1,-1)) + 0:1 

這導致在相同的索引。

+0

'diff'會更快,因爲它是一個單一的操作? – oregano

+0

@oregano不知道,你必須測試 – h3rm4n

相關問題