【问题标题】:R Using paste in data.table to subset variable number of columns and calculate rowMeansR在data.table中使用粘贴来子集可变列数并计算rowMeans
【发布时间】:2016-07-20 01:03:35
【问题描述】:

我在过去一周开始使用data.table,但遇到了问题。我已经查看了解决方案 herehere,但我不完全确定它对我的情况有何帮助。

这是我的示例数据。

> dput(dt)
structure(list(link = c(1L, 1L, 1L, 1L, 1L, 1L), id = c(8395, 8738, 9788, 9789, 9908, 9920), person = c(2937837, 3092435, 3511555, 3511555, 3568112, 3575082), seqid = c(11, 14, 9, 1, 7, 10), time = c(NA, NA, 25372, 50700, NA, NA), max = c(14, 31, 9, 7, 8, 11), hr = c(NA, NA, 7, 14, NA, NA), minhr = c(11, 19, 7, 14, 7, 16), maxhr = c(11, 19, 7, 14, 7, 16), TRAVELTIME0.1avg = c(59, 59, 59, 59, 59, 59 ), TRAVELTIME1.2avg = c(59, 59, 59, 59, 59, 59), TRAVELTIME2.3avg = c(59, 59, 59, 59, 59, 59), TRAVELTIME3.4avg = c(59.2079086331819, 59.2079086331819, 59.2079086331819, 59.2079086331819, 59.2079086331819, 59.2079086331819 ), TRAVELTIME4.5avg = c(59.9182362587214, 59.9182362587214, 59.9182362587214, 59.9182362587214, 59.9182362587214, 59.9182362587214), TRAVELTIME5.6avg = c(60.4905040124798, 60.4905040124798, 60.4905040124798, 60.4905040124798, 60.4905040124798, 60.4905040124798), TRAVELTIME6.7avg = c(59.2897529410742, 59.2897529410742, 59.2897529410742, 59.2897529410742, 59.2897529410742, 59.2897529410742 ), TRAVELTIME7.8avg = c(59.2717176535874, 59.2717176535874, 59.2717176535874, 59.2717176535874, 59.2717176535874, 59.2717176535874), TRAVELTIME8.9avg = c(59.2569737174023, 59.2569737174023, 59.2569737174023, 59.2569737174023, 59.2569737174023, 59.2569737174023), TRAVELTIME9.10avg = c(59.2814811928216, 59.2814811928216, 59.2814811928216, 59.2814811928216, 59.2814811928216, 59.2814811928216 ), TRAVELTIME10.11avg = c(59.2084537775537, 59.2084537775537, 59.2084537775537, 59.2084537775537, 59.2084537775537, 59.2084537775537 ), TRAVELTIME11.12avg = c(59.0915653550983, 59.0915653550983, 59.0915653550983, 59.0915653550983, 59.0915653550983, 59.0915653550983 ), TRAVELTIME12.13avg = c(59.6765035434587, 59.6765035434587, 59.6765035434587, 59.6765035434587, 59.6765035434587, 59.6765035434587 ), TRAVELTIME13.14avg = c(59.246760177185, 59.246760177185, 59.246760177185, 59.246760177185, 59.246760177185, 59.246760177185), TRAVELTIME14.15avg = c(59.4095339982924, 59.4095339982924, 59.4095339982924, 59.4095339982924, 59.4095339982924, 59.4095339982924), TRAVELTIME15.16avg = c(59.5347570536373, 59.5347570536373, 59.5347570536373, 59.5347570536373, 59.5347570536373, 59.5347570536373 ), TRAVELTIME16.17avg = c(59.3799872977671, 59.3799872977671, 59.3799872977671, 59.3799872977671, 59.3799872977671, 59.3799872977671 ), TRAVELTIME17.18avg = c(59.1915498629857, 59.1915498629857, 59.1915498629857, 59.1915498629857, 59.1915498629857, 59.1915498629857 ), TRAVELTIME18.19avg = c(59.1663574471712, 59.1663574471712, 59.1663574471712, 59.1663574471712, 59.1663574471712, 59.1663574471712 ), TRAVELTIME19.20avg = c(59.0217772215269, 59.0217772215269, 59.0217772215269, 59.0217772215269, 59.0217772215269, 59.0217772215269 ), TRAVELTIME20.21avg = c(59.0893371757925, 59.0893371757925, 59.0893371757925, 59.0893371757925, 59.0893371757925, 59.0893371757925 ), TRAVELTIME21.22avg = c(59.0272727272727, 59.0272727272727, 59.0272727272727, 59.0272727272727, 59.0272727272727, 59.0272727272727 ), TRAVELTIME22.23avg = c(59, 59, 59, 59, 59, 59), TRAVELTIME23.24avg = c(59, 59, 59, 59, 59, 59), TRAVELTIME24.25avg = c(59, 59, 59, 59, 59, 59), TRAVELTIME25.26avg = c(59, 59, 59, 59, 59, 59), TRAVELTIME26.27avg = c(59, 59, 59, 59, 59, 59)), .Names = c("link", "id", "person", "seqid", "time", "max", "hr", "minhr", "maxhr", "TRAVELTIME0.1avg", "TRAVELTIME1.2avg", "TRAVELTIME2.3avg", "TRAVELTIME3.4avg", "TRAVELTIME4.5avg", "TRAVELTIME5.6avg", "TRAVELTIME6.7avg", "TRAVELTIME7.8avg", "TRAVELTIME8.9avg", "TRAVELTIME9.10avg", "TRAVELTIME10.11avg", "TRAVELTIME11.12avg", "TRAVELTIME12.13avg", "TRAVELTIME13.14avg", "TRAVELTIME14.15avg", "TRAVELTIME15.16avg", "TRAVELTIME16.17avg", "TRAVELTIME17.18avg", "TRAVELTIME18.19avg", "TRAVELTIME19.20avg", "TRAVELTIME20.21avg", "TRAVELTIME21.22avg", "TRAVELTIME22.23avg", "TRAVELTIME23.24avg", "TRAVELTIME24.25avg", "TRAVELTIME25.26avg", "TRAVELTIME26.27avg"), sorted = "link", class = c("data.table", "data.frame"), row.names = c(NA, -6L))

更新1:为避免internal.selfref 的问题,请在使用上述示例创建dt 后执行dt <- data.table(dt)

我想使用 minhrmaxhr 变量对行程时间进行子集化,并为这些子集化的行程时间计算 rowMeans 并将其添加到当前 dt。如果minhr(或maxhr)为11,则对应的行程时间栏为TRAVELTIME11.12avg;如果是19,对应的行程时间栏是TRAVELTIME19.20avg。所以,如果 minhr 是 9 并且 maxhr 是 10 连续,那么我需要得到 TRAVELTIME9.10avg 的平均值TRAVELTIME10.11avg;同样,如果 minhr 是 15 并且 maxhr 是 17 那么我需要得到 TRAVELTIME15.16avg, TRAVELTIME16.17avg 和 TRAVELTIME17.18avg

我尝试逐步解决问题,并将以下代码用于所有行中的统一旅行时间列的简单案例。它工作正常。

> dt[,avg:=rowMeans(.SD[,TRAVELTIME10.11avg:TRAVELTIME12.13avg, with=FALSE]),by=.(id, seqid)]

接下来,我尝试修改上面的代码,引入paste0()动态引用列名。但是,这会导致错误。此外,我尝试使用as.symbol(paste0())noquote(paste0()) 和其他一些取消引用技术,但均未成功。

   > dt[,avg:=rowMeans(.SD[,paste0("TRAVELTIME", minhr, "." , minhr+1, "avg"):paste0("TRAVELTIME", maxhr, "." , maxhr+1, "avg"), with=FALSE]),by=.(id, seqid)]

Error in paste0("TRAVELTIME", minhr, ".", minhr + 1, "avg"):paste0("TRAVELTIME",  : 
  NA/NaN argument
In addition: Warning messages:
1: In eval(expr, envir, enclos) : NAs introduced by coercion
2: In eval(expr, envir, enclos) : NAs introduced by coercion

鉴于此,我有两个问题:

1) 为什么data.table 不能识别列名,如果使用粘贴命令(即使在取消引用粘贴的字符串之后)子集列而不是直接使用列名?是否与每行的列数不相等有关?

2)由于我不成功,您能否建议一种方法来找到每行可变列数的平均值,并将其添加回 dt。如果该建议能带来有效的方法,我将不胜感激,因为我已经尝试过使用更简单的循环方法,而且我的数据大小需要很长时间(整个数据集大约需要 12 到 15 小时)。

【问题讨论】:

    标签: r data.table paste


    【解决方案1】:

    我相信这可以解决您在使用 paste0 时遇到的问题:

    tmp  <- paste0("TRAVELTIME", dt$minhr, "." , dt$minhr+1, "avg")
    tmp1 <- paste0("TRAVELTIME", dt$maxhr, "." , dt$maxhr+1, "avg")
    dt1  <- dt[,avg:=rowMeans(.SD[,get(tmp):get(tmp1), with=FALSE]),by=.(dt$id, dt$seqid)]
    

    有人可能会指出,您并不严格需要最后一行中的 $,但由于您遇到的问题的性质,我认为这对于识别和解决问题很有用。

    【讨论】:

    • 感谢您的回复。我不知道为什么要报告 internal.selfref 指针。我现在把它删了。无论如何,我采用了您建议的解决方案,并且所有行的平均旅行时间似乎都相同。您能否确认您是否使用此解决方案在各行之间获得了不同的旅行时间?
    • @Gandalf 由于internal.selfref 的问题,我无法复制您的数据(如果我把它拿出来,我在进行聚合时会得到一个不同的错误;这很奇怪)。我只知道这解决了paste0 问题。如果聚合逻辑不正确,那么仍然需要修复。我想你可以用一些条件语句来修复它(或者将条件放在if 语句中,或者将两个不同的聚合函数应用于数据的相关子集)。
    • 我认为在您的代码解决internal.selfref 问题之前使用dt &lt;- data.table(dt)。但是,更重要的是,我认为上面的代码不能解决我的问题。逻辑似乎是完整的,但我猜在程序细节中有些东西是错误的,因为当我尝试dt[,get(tmp):get(tmp1), with=FALSE] 时,我得到了一个名为 TRAVELTIME11.12avg 的向量。我的猜测是这个问题是不等列的结果。但是,我不知道如何解决它。
    • 我认为,在上面的代码中,只使用了向量中的第一个元素。这是错误消息。请注意,我必须丢弃 get() 才能生成此错误和警告。 dt[,(tmp):(tmp1), with=FALSE]Error in (tmp):(tmp1) : NA/NaN argumentIn addition: Warning messages: 1: In (tmp):(tmp1) : numerical expression has 6 elements: only the first used 2: In (tmp):(tmp1) : numerical expression has 6 elements: only the first used 3: In eval(expr, envir, enclos) : NAs introduced by coercion 4: In eval(expr, envir, enclos) : NAs introduced by coercion
    • 我想,我根据您的意见找到了解决方案。首先,我需要创建一个名为 rown 的列,指示行号,如dt[,rown:= as.numeric(row.names(dt))]。然后我创建一个函数并调用它,如下所示:func.dt &lt;- function(rown, x, y) { tmp &lt;- paste0("TRAVELTIME", x, "." , x+1, "avg") tmp1 &lt;- paste0("TRAVELTIME", y, "." , y+1, "avg") rowMeans(dt[rown,get(tmp):get(tmp1), with=FALSE]) } dt[, func.dt(rown, minhr, maxhr), by=rown] 这工作得很好。但是,它非常慢。你能建议我有什么方法让它变快吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-21
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    • 2013-08-23
    • 2019-10-09
    相关资源
    最近更新 更多