【问题标题】:how to access rownames in a chained data.table of R如何访问 R 的链式 data.table 中的行名
【发布时间】: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


【解决方案1】:

试试cbind:

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=cbind(lon,lat),p2=cbind(i.lon,i.lat))]
# correct : 100 lines
dt[lon>77 & lat<12.5][,dist:=distGeo(p1=cbind(lon,lat),p2=cbind(i.lon,i.lat))]
# also correct : 16 lines

:= 无需汇总即可处理每一行。
cbind 允许将扩展的 n*2 lat-lon 矩阵提供给函数。

【讨论】:

  • 您的解决方案可能有效,但看起来非常冗长。我一直在寻找更优雅或更简洁的解决方案:类似by=.I(但这不起作用)。但是我想我会按照之前的建议在原始 DT 中创建rown=rownames(),然后使用by=rown 在下游创建。
  • 如果 cbind 有效,则意味着函数 distGeo 确实接受向量。我会尽快尝试并接受答案。
猜你喜欢
  • 1970-01-01
  • 2017-10-24
  • 2020-01-19
  • 2018-10-27
  • 2012-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多