我将R与data.table包一起使用。我有一个计算计数的循环,但由于它是一个循环,所以速度非常慢。现在我想以某种方式改变它,这样它就不需要几天的时间来计算了。
我有一个数据集,我想计算这个人在数据集中出现的频率。当名字、姓氏和出生日期(生日、出生月份和生日)相同时,它是相同的“人”。然而,我的问题是,日期也很重要。因此,如果我正在查看的这个人出现在数据集中,我必须检查“同一个人”的日期是否在我正在查看的人的日期之前。因此,同一个人必须在我看到的人之前知道。
然后我还想计算这些条目之间的平均时间。以下是我目前的解决方案(工作有效,但速度非常慢):
library(data.table)
data <- data[order(-persondatetime)]
vec_countperson <- numeric(nrow(data))
vec_time <- numeric(nrow(data))
for (i in 1:nrow(data)){
vec_countperson[i] <- data[firstname == data[i, firstname] &
surname == data[i, surname] &
birthdate == data[i, birthdate] &
persondatetime < data[i, persondatetime], .N]
vec_time[i] <- data[firstname == data[i, firstname] &
surname == data[i, surname] &
birthdate == data[i, birthdate] &
persondatetime < data[i, persondatetime],
mean(abs(diff(c(persondatetime, data[i, persondatetime]))))]
}
data[, countperson := vec_countperson]
data[, timebetweenentries := vec_time]示例data.table将如下所示:
data <- data.table(
firstname = c("Paul", "Jens", "Jens", "Jens","Paul", "Dieter"),
surname = c("Mueller", "Mustermann", "Mustermann", "Mustermann", "Mueller", "Brian"),
birthdate = as.Date(c("1960-05-08", "1960-05-08", "1960-05-08",
"1960-05-08", "1960-05-08", "1960-05-08")),
persondatetime = as.POSIXct(c("2018-05-01 23:18:38 CET", "2018-03-01 23:18:38 CET",
"2018-06-01 23:18:38 CET", "2018-04-01 23:18:38 CET",
"2018-04-06 23:18:38 CET", "2018-04-08 23:18:38 CET")))预期输出为:
firstname surname birthdate persondatetime countperson timebetweenentries
1: Jens Mustermann 1960-05-08 2018-03-01 23:18:38 0 NaN
2: Jens Mustermann 1960-05-08 2018-04-01 23:18:38 1 30.95833
3: Paul Mueller 1960-05-08 2018-04-06 23:18:38 0 NaN
4: Dieter Brian 1960-05-08 2018-04-08 23:18:38 0 NaN
5: Paul Mueller 1960-05-08 2018-05-01 23:18:38 1 25.00000
6: Jens Mustermann 1960-05-08 2018-06-01 23:18:38 2 45.97917你知道我怎么才能避免这个循环吗?我想过其他的想法,但我的问题总是与日期有关!
发布于 2019-07-09 12:43:18
您可以使用类似于@chinsoon12在他的评论中发布的代码来重新创建countperson列。
data[data,
on=.(firstname, surname, birthdate=birthdate, persondatetime > persondatetime),
countperson:=.N,
by=.EACHI]
data[, countperson := coalesce(countperson, 0L)]此更新联接的data.table语法为X[I, on=.(conditions), var:=.N, by=.EACHI]。对于data.table I中的每一行,都会找到X匹配conditions中的行。使用by=.EACHI参数按I中的行对此连接的结果进行分组。在data.table中,.N符号表示每个组的行数。在本例中,对于I中的每一行,.N是X中基于conditions匹配的行数。如果I中的某一行在X中没有匹配的行,则.N为NA,我们在下一行中使用coalesce将其设置为0。
重新创建timebetweenentries变量的一种方法是按指示行属于同一个person的列进行分组,计算每个组的persondatetime的平均差异,并将其分配给data.table中的一列。如果您想要连续条目之间的时间,那么您应该在获得差异之前对persondatetime进行排序。
下面的代码使用data.table的setkey函数一次完成所有排序。这应该会加快分组速度,并避免为每个组调用sort(persondatetime)。
setkey(data, firstname, surname, birthdate, persondatetime)
data[, timebetweenentries := mean(abs(diff(persondatetime)), na.rm=T)https://stackoverflow.com/questions/56930207
复制相似问题