我有一个表,该表具有> 1800万行(与多个对象相关的多个事件),并且我试图创建一个关于对象是否具有相同系列事件发生的映射列。
示例数据帧(为了提高效率使用data.table):
aa<-data.table(data.frame(id=c(1,1,1,1,4,4,4,5,5,5,5,5),
val=c("a","a","b","a","c","c","c","a","b","c","a","b")))
对象对应于id列,值是与事件关联的事件发生。
所需的结果,其中noswitch
是我的映射列:
id val noswitch
1: 1 a NA
2: 1 a NA
3: 1 b NA
4: 1 a NA
5: 4 c TRUE
6: 4 c TRUE
7: 4 c TRUE
8: 5 a NA
9: 5 b NA
10: 5 c NA
11: 5 a NA
12: 5 b NA
仅对标记对象的所有事件具有相同值的位置感兴趣
使用for循环执行上述操作的代码:
ids<-unique(aa$id)
aa$noswitch<-rep(NA,nrow(aa))
for ( i in 1: length(ids))
{
if ( length(unique(aa[id==ids[i]]$val))==1) aa[id==ids[i]]$noswitch<-1
}
考虑到原始df的行数和超过200万个对象,使用for循环将需要> 5-6天。
是否存在另一种更有效的方法来实现此目标,而又无需拆分数据集并并行运行某些数据集?
答案 0 :(得分:1)
基于data.table
软件包的解决方案。想法是计算每个id
和val
的行数,然后检查该数字是否与每个id
的总行数相同。
library(data.table)
aa[, Count := .N, by = .(id, val)][
, noswitch := Count == .N, by = id][
, Count := NULL][]
# id val noswitch
# 1: 1 a FALSE
# 2: 1 a FALSE
# 3: 1 b FALSE
# 4: 1 a FALSE
# 5: 4 c TRUE
# 6: 4 c TRUE
# 7: 4 c TRUE
# 8: 5 a FALSE
# 9: 5 b FALSE
# 10: 5 c FALSE
# 11: 5 a FALSE
# 12: 5 b FALSE
答案 1 :(得分:0)
您还可以利用data.table::uniqueN
。
library(data.table)
dt[, noswitch := uniqueN(val) == .N, id]
我发现此解决方案更易于阅读,但请注意,它不是第一个解决方案那么快。