R - 链接 data.table 操作的最佳实践

aim*_*r21 4 r data.table

到处搜索,但没有找到任何用于安排 data.table 链式代码的一般准则,这些代码可能跨越多行以提高可读性。

拿f.ex。(仅用于说明目的的玩具示例)

iris.dt[sepal.length > 5 & sepal.width > 3 & petal.length > 2 & petal.width > 2 & species == "virginica"] 
Run Code Online (Sandbox Code Playgroud)

由于这一切都对应于相同的参数 (dt[i]),因此将其拆分为多行很容易,我只会这样做:

iris.dt[sepal.length > 5 & 
        sepal.width  > 3 & 
        petal.length > 2 & 
        petal.width  > 2 & 
        species == "virginica"] 
Run Code Online (Sandbox Code Playgroud)

或者

iris.dt[sepal.length > 5 & 
          sepal.width  > 3 & 
          petal.length > 2 & 
          petal.width  > 2 & 
          species == "virginica"] 
Run Code Online (Sandbox Code Playgroud)

但是拿f.ex。像这样。您将如何清理此代码片段以及在哪里缩进/换行?注意:这只是一个关于长 data.table 链式代码块在实践中的样子的玩具示例。

    iris.dt[, id := 1:.N, by = species][, comb_area_sepal := (sepal.length * sepal.width), 
by = species][, comb_area_petal := (petal.length * petal.width), by = species][
species == "virginica" & comb_area_petal > 12.5, .(petal.width, petal.length, comb_area_petal]
Run Code Online (Sandbox Code Playgroud)

我将如何处理这样的代码?如何最好地打破界限并安排争论和括号?我应该优先考虑什么来提高可读性

有时,尤其是在处理大型数据集和变量名(列名)很长以进行某种描述时,争论(主要是 j)将跨越几行。如果它们跨越多行 (dt[i, j, by]),我是否应该缩进相同的参数。那么从第二行开始缩进 j 吗?

我的直觉会像这样打破上面的玩具示例:

    iris.dt[, id := 1:.N, by = species][,
            comb_area_sepal := (sepal.length * sepal.width), 
            by = species][, 
            comb_area_petal := (petal.length * petal.width), 
            by = species][
            species == "virginica" & comb_area_petal > 12.5,
            .(petal.width, petal.length, comb_area_petal]
Run Code Online (Sandbox Code Playgroud)

你怎么认为?我意识到这也可能因各种不同的编码风格而异,但我非常感兴趣的是您在实践中应用了哪些概念来保持此类代码易于阅读。

akr*_*run 5

创建序列的第一个操作可以用 简化rowid,然后通过乘法创建两列的第二个和第三个操作实际上并不需要 group by 因为这些是元素操作并且可以组合在一起。最后一个是子集(行),选择列

iris.dt[, id := rowid(species)][,
    c('comb_area_sepal', 'comb_area_petal') := 
     .((sepal.length * sepal.width), (petal.length * petal.width))
      ][species == "virginica" & comb_area_petal > 12.5,
        .(petal.width, petal.length, comb_area_petal)]
Run Code Online (Sandbox Code Playgroud)

此外,这可以与 %>%

library(magrittr)
iris.dt[, id := rowid(species)] %>%
    .[,c('comb_area_sepal', 'comb_area_petal') := 
     .((sepal.length * sepal.width), (petal.length * petal.width))
      ] %>%
    .[species == "virginica" & comb_area_petal > 12.5,
        .(petal.width, petal.length, comb_area_petal)]
Run Code Online (Sandbox Code Playgroud)

-输出

#     petal.width petal.length comb_area_petal
# 1:         2.5          6.0           15.00
# 2:         2.2          5.8           12.76
# 3:         2.1          6.6           13.86
# 4:         2.5          6.1           15.25
# 5:         2.2          6.7           14.74
# 6:         2.3          6.9           15.87
# 7:         2.3          5.7           13.11
# 8:         2.0          6.7           13.40
# 9:         2.0          6.4           12.80
#10:         2.3          6.1           14.03
#11:         2.4          5.6           13.44
#12:         2.4          5.6           13.44
#13:         2.3          5.9           13.57
#14:         2.5          5.7           14.25
Run Code Online (Sandbox Code Playgroud)

对于第一种情况,它也可以简化

iris.dt[iris.dt[, Reduce(`&`, Map(`>`,.SD, .(5, 3, 2, 2))) & 
     species == 'virginica', .SDcols = sepal.length:petal.width]]
Run Code Online (Sandbox Code Playgroud)