2017-02-07 31 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

相关问题