R需要基于ID和时间偏移的非唯一第二列分布来比较R中的行
我需要比较第一个值和最后一个值(取差值)。我试着把用户(C/A)列放在后面。把人1想象成C,把人2想象成A 问题是,从C到C到C等有不同的周期,没有上限,所以我需要一些足够灵活的东西。有两个周期,我可以只挂接序列并连接,但这只是一个特例,对我一点帮助都没有。我需要确定的是每个时段从第一个C到最后一个C的时间偏移分布,因此每个ID可能有多个C->C->C->etc偏移,因此我无法通过将ID和序列以及用户连接到组来创建唯一标识符,如果Cs的每个时段都有一个唯一的ID,这将非常好。当C=C时,有一个假人帮助识别。如果我能用虚拟的差值求和,我也能得到我所需要的。例如,第2行和第3行中的17+15=C-C-C期间的时间差,我需要所有事件的时间差 以下是迄今为止的数据示例: 数据:R需要基于ID和时间偏移的非唯一第二列分布来比较R中的行,r,R,我需要比较第一个值和最后一个值(取差值)。我试着把用户(C/A)列放在后面。把人1想象成C,把人2想象成A 问题是,从C到C到C等有不同的周期,没有上限,所以我需要一些足够灵活的东西。有两个周期,我可以只挂接序列并连接,但这只是一个特例,对我一点帮助都没有。我需要确定的是每个时段从第一个C到最后一个C的时间偏移分布,因此每个ID可能有多个C->C->C->etc偏移,因此我无法通过将ID和序列以及用户连接到组来创建唯一标识符,如果Cs的每个时段都有一个唯一的ID,这将非常好。当C=C时,有一个假
ID Sequen_num user time_shift userlag1 time_shift2 difference Dummy(user= C userlag1=C )
1 1 A 1 C 15 14 0
1 2 C 15 C 32 17 1
1 3 C 32 C 47 15 1
1 4 C 47 A 65 18 0
1 5 A 65 C 80 15 0
1 6 C 80 C 110 30 1
1 7 C 110 A 120 10 0
1 8 A 120
如果我有这样的东西,那将非常简单(基本上是一种识别每个ID中每个块的方法):
这将创建一个排序向量,该向量在用户列的连续值运行中具有相同的值。假设此当前未命名的数据帧的名称为“dat”:
ct <- 1; for( i in seq_along(dat$user)[-1] ) { if (dat$user[i] != dat$user[i-1]) {
ct <-c( ct,tail(ct,1)+1)
}else{ct <- c(ct, tail(ct,1))} }
> ct
[1] 1 2 2 2 3 4 4 5 # this is your "user_block"
我想我可能不明白你想要什么<代码>数据。表可能是一个开始
#Make data
dat <- structure(list(ID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Sequen_num = 1:8,
user = c("A", "C", "C", "C", "A", "C", "C", "A"), time_shift = c(1L,
15L, 32L, 47L, 65L, 80L, 110L, 120L)), .Names = c("ID", "Sequen_num",
"user", "time_shift"), class = "data.frame", row.names = c(NA,-8L))
#Calculate running count of A's (or non-C's)
require("data.table")
dat<- data.table(dat)
#Find running cnt of non-C values
dat[,Running.A.Cnt := factor(cumsum(dat$user!="C"))]
#Create a new group variable
dat[user=="C",NewGroup:=.GRP,by=c("user","Running.A.Cnt")]
dat[user!="C",NewGroup:=NA]
#Calculate difference between first and last entry
dat[user=="C",differ:=(time_shift[.N]-time_shift[1]),by=c("NewGroup")]
dat
# ID Sequen_num user time_shift Running.A.Cnt NewGroup differ
# 1: 1 1 A 1 1 NA NA
# 2: 1 2 C 15 1 1 32
# 3: 1 3 C 32 1 1 32
# 4: 1 4 C 47 1 1 32
# 5: 1 5 A 65 2 NA NA
# 6: 1 6 C 80 2 2 30
# 7: 1 7 C 110 2 2 30
# 8: 1 8 A 120 3 NA NA
#生成数据
dat将表格行缩进4行,谢谢。很长一段时间以来,我一直在使用Stackexchange和overflow进行引用,但从未发布过。我已经搜索了一整天,没有找到任何关于这个问题的具体内容。我已经习惯了像“C-C-C”的每个集群都有一个唯一的ID这样的事情,这将使这变得超级简单。这是一个开始,但它不会让我在索引中为每个CCC组获得不同的值,con2非常感谢。伙计,你知道你的本事。到目前为止,这似乎工作得非常好。哇!我真的需要把R作为一个整体来学习。到目前为止,来自SAS的我正在学习分段,所以现在对我来说非常困难。我注意到的唯一一件事是,最后一个用户块的尾部与下一个用户块的头部的值相同,但我要处理的是,我正在使用cbind将Ct连接到dat,这是一种糟糕的形式吗?它似乎有效,但我可能不完全理解所有的注意事项cbind
?应该没问题。我最后用这个来打破它,Id:ct 2东西:这只在6万行上运行非常慢,所以在4千万行上它是不可行的。其次,它随机停止工作,现在我得到错误。嘿Mike BondedDust差不多已经搞定了但当进入下一个ID时,它会将最后一次计数带入新ID的第一个实例,所以非常接近。我还需要再玩一玩。嘿,迈克,谢谢,我下一步要试试。嵌套循环实际上需要很长时间才能运行,我非常确信数据表方法会快得多。非常感谢。对不起,我没说清楚,没问题。让我知道运行需要多长时间(以及数据有多大)!每日文件为400K-500K行。所以每个月和每个季度都会有很大的增长。嘿,迈克,这会立即运行,效果很好。而且速度非常快。非常感谢你。我现在决定花一些时间学习R中的数据表包。非常感谢。唯一的问题是,它遇到了与上一个相同的问题,下一个用户ID的第一个C(客户机)块的时间偏移错误,而嵌套的for循环,它将从上一个客户机块(假设773是时间偏移)获取差异,然后从下一个客户机块获取1,得到一个-722的时间偏移,而不是它应该是什么
dput(dat)
structure(list(ID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Sequen_num = 1:8,
user = c("A", "C", "C", "C", "A", "C", "C", "A"), time_shift = c(1L,
15L, 32L, 47L, 65L, 80L, 110L, 120L)), .Names = c("ID", "Sequen_num",
"user", "time_shift"), class = "data.frame", row.names = c(NA,
-8L))
> dat$differ <- ave(dat$time_shift, factor(ct), FUN=function(x) tail(x,1)-head(x,1) )
> dat
ID Sequen_num user time_shift differ
1 1 1 A 1 0
2 1 2 C 15 32
3 1 3 C 32 32
4 1 4 C 47 32
5 1 5 A 65 0
6 1 6 C 80 30
7 1 7 C 110 30
8 1 8 A 120 0
> dat$cumtime <- ave(dat$time_shift, factor(ct), FUN=cumsum )
> dat
ID Sequen_num user time_shift differ cumtime
1 1 1 A 1 0 1
2 1 2 C 15 32 15
3 1 3 C 32 32 47
4 1 4 C 47 32 94
5 1 5 A 65 0 65
6 1 6 C 80 30 80
7 1 7 C 110 30 190
8 1 8 A 120 0 120
runcatf <- function(x) cumsum(c(TRUE, x[-length(x)] != x[-1]))
dat$runcat <- ave (dat$tuser, dat$ID, FUN=runcatf )
dat.tbl[ , runcat := ave(user) , by=c("ID") ]
#Make data
dat <- structure(list(ID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Sequen_num = 1:8,
user = c("A", "C", "C", "C", "A", "C", "C", "A"), time_shift = c(1L,
15L, 32L, 47L, 65L, 80L, 110L, 120L)), .Names = c("ID", "Sequen_num",
"user", "time_shift"), class = "data.frame", row.names = c(NA,-8L))
#Calculate running count of A's (or non-C's)
require("data.table")
dat<- data.table(dat)
#Find running cnt of non-C values
dat[,Running.A.Cnt := factor(cumsum(dat$user!="C"))]
#Create a new group variable
dat[user=="C",NewGroup:=.GRP,by=c("user","Running.A.Cnt")]
dat[user!="C",NewGroup:=NA]
#Calculate difference between first and last entry
dat[user=="C",differ:=(time_shift[.N]-time_shift[1]),by=c("NewGroup")]
dat
# ID Sequen_num user time_shift Running.A.Cnt NewGroup differ
# 1: 1 1 A 1 1 NA NA
# 2: 1 2 C 15 1 1 32
# 3: 1 3 C 32 1 1 32
# 4: 1 4 C 47 1 1 32
# 5: 1 5 A 65 2 NA NA
# 6: 1 6 C 80 2 2 30
# 7: 1 7 C 110 2 2 30
# 8: 1 8 A 120 3 NA NA