我想创建一个新的计算列(另一列文本的摘要)。为了让您重现,我创建了一个 df 作为可重现的示例:
df <- data.frame(name = replicate(1000, paste(sample(LETTERS, 20, replace=TRUE), collapse="")),stringsAsFactors=FALSE)
> head(df,3)
name
1 ZKBOZVFKNJBRSDWTUEYR
2 RQPHUECABPQZLKZPTFLG
3 FTBVBEQTRLLUGUVHDKAY
现在我想要第二列,其中包含每行的“名称”列的摘要
这工作得很好,但是很慢(每个 md5 都不同,它是 name 列的相应摘要):
> df$md5 <- sapply(df$name, digest)
> head(df, 3)
name md5
1 ZKBOZVFKNJBRSDWTUEYR b8d93a9fe6cefb7a856e79f54bac01f2
2 RQPHUECABPQZLKZPTFLG 52f6acbd939df27e92232904ce094053
3 FTBVBEQTRLLUGUVHDKAY a401a8bc18f0cb367435b77afd353078
但这(使用 dplyr)不起作用,我不明白为什么:每行的 md5 都是相同的!事实上,它是完整 df$name 的摘要,包括所有行。请问有人可以向我解释一下吗?
> df <- mutate(df, md5=digest(name))
> head(df, 3)
name md5
1 ZKBOZVFKNJBRSDWTUEYR 10aa31791d0b9288e819763d9a41efd8
2 RQPHUECABPQZLKZPTFLG 10aa31791d0b9288e819763d9a41efd8
3 FTBVBEQTRLLUGUVHDKAY 10aa31791d0b9288e819763d9a41efd8
再次,如果我采用数据表方式,似乎使用新变量的标准方式不起作用:
> dt <- data.table(df)
> dt[, md5:=digest(name)]
> head(dt,3)
name md5
1: ZKBOZVFKNJBRSDWTUEYR 10aa31791d0b9288e819763d9a41efd8
2: RQPHUECABPQZLKZPTFLG 10aa31791d0b9288e819763d9a41efd8
3: FTBVBEQTRLLUGUVHDKAY 10aa31791d0b9288e819763d9a41efd8
如果我强制分组,那么它会再次起作用(但速度很慢):
> dt[,md5:=digest(name), by=name]
> head(dt, 3)
name md5
1: ZKBOZVFKNJBRSDWTUEYR b8d93a9fe6cefb7a856e79f54bac01f2
2: RQPHUECABPQZLKZPTFLG 52f6acbd939df27e92232904ce094053
3: FTBVBEQTRLLUGUVHDKAY a401a8bc18f0cb367435b77afd353078
我还测试了 Tapply 和工作(创建一个因素,但我的真实数据有数百万行,而且速度非常慢)。
然后,首先,有人可以向我解释为什么 dplyr mutate 不采用每行的值来计算摘要,以及为什么数据表符号会发生相同的想法(除非我分组)?
其次,是否有一种更快的方法来计算所有行的摘要?