【发布时间】:2020-08-10 19:10:55
【问题描述】:
有时我们需要行名来创建一个新列,该列是先前列的函数,但仅针对一行(每一行)进行聚合。换句话说,该函数正在跨行运行。
考虑一下:
library(data.table)
library(geosphere)
dt <- data.table(lon=77+rnorm(100),lat=13 + rnorm(100),i.lon=77+rnorm(100),i.lat=13 + rnorm(100))
dt[,dist:=distGeo(p1=c(lon,lat),p2=c(i.lon,i.lat)),by=rownames(dt)] # correct
第二行代码运行良好,因为 data.table 名称 dt 在方括号内可用(它本身对我来说看起来不太优雅),但并非总是如此。
如果有一个 data.tables 链怎么办?考虑前面示例的扩展:
dt[lon>77 & lat<12.5][,dist:=distGeo(p1=c(lon,lat),p2=c(i.lon,i.lat)),by=rownames(dt)] # incorrect
显然这是不正确的用法,因为 rownames(dt) 的长度与传递给链中下一个的子集 data.table 的长度不同。
我想我更大的问题是:rownames() 是实现每一行汇总的唯一方法吗?如果不是,那么具体问题仍然存在:如果 by= 构造中的 data.table 是链式 data.table,我们如何访问它?
【问题讨论】:
-
Data.table 不使用行名。将其存储为列(称为 row.names)并在链中使用它会更有效。
-
data.table 中的操作不是已经按行进行了吗?如果我使用 sum 函数,我将得到每一行的总和。我不明白为什么在这种情况下需要逐行分组...也许强制 distGeo 的输入不是向量...
-
@daniellga:不完全是,像
paste(..collapse=)或不起眼的sum这样的函数是矢量化的,所有行都会被同时考虑。 -
@LazarusThurston 我的意思是,虽然它是矢量化的,但操作的完成就像它是行的。我认为你在这个问题上的唯一解决方案就是要走的路。与其在 data.table 操作中按行分组,不如修复您正在应用以接受以矢量化方式工作的函数可能更快、更易读。
-
或者甚至是for循环,这样做没有问题。
标签: r data.table