我不太清楚.SDby的用法.

例如,下面的代码片段是否意味着:"将DT中的所有列更改为除AB之外的系数?"在data.table手册中还说:".SD是指每个组的data.table的子集(不包括分组列)"——所以AB列不包括在内?

DT = DT[ ,lapply(.SD, as.factor), by=.(A,B)]

然而,我也读到,当你进行聚合时,by的意思类似于SQL中的"groupby".例如,如果我想对除AB之外的所有列求和(比如SQL中的colsum),我还会使用类似的方法吗?或者,在这种情况下,下面的代码是否意味着取第A列和第B列中的总和和分组值?(按照SQL中的A,B进行求和和和分组)

DT[,lapply(.SD,sum),by=.(A,B)]

那么,除了AB之外,我如何在所有的列上做一个简单的colsum

推荐答案

为了用一个例子来说明上面的 comments ,让我们举一个例子

set.seed(10238)
# A and B are the "id" variables within which the
#   "data" variables C and D vary meaningfully
DT = data.table(
  A = rep(1:3, each = 5L), 
  B = rep(1:5, 3L),
  C = sample(15L),
  D = sample(15L)
)
DT
#     A B  C  D
#  1: 1 1 14 11
#  2: 1 2  3  8
#  3: 1 3 15  1
#  4: 1 4  1 14
#  5: 1 5  5  9
#  6: 2 1  7 13
#  7: 2 2  2 12
#  8: 2 3  8  6
#  9: 2 4  9 15
# 10: 2 5  4  3
# 11: 3 1  6  5
# 12: 3 2 12 10
# 13: 3 3 10  4
# 14: 3 4 13  7
# 15: 3 5 11  2

比较以下各项:

#Sum all columns
DT[ , lapply(.SD, sum)]
#     A  B   C   D
# 1: 30 45 120 120

#Sum all columns EXCEPT A, grouping BY A
DT[ , lapply(.SD, sum), by = A]
#    A  B  C  D
# 1: 1 15 38 43
# 2: 2 15 30 49
# 3: 3 15 52 28

#Sum all columns EXCEPT A
DT[ , lapply(.SD, sum), .SDcols = !"A"]
#     B   C   D
# 1: 45 120 120

#Sum all columns EXCEPT A, grouping BY B
DT[ , lapply(.SD, sum), by = B, .SDcols = !"A"]
#    B  C  D
# 1: 1 27 29
# 2: 2 17 30
# 3: 3 33 11
# 4: 4 23 36
# 5: 5 20 14

几点注意事项

  • 你说"下面的片段…是否更改了DT中的所有列…"

答案是no,这对data.table人来说非常重要.返回的对象是new data.tableDT中的所有列与运行代码之前完全相同.

  • 您提到想要更改列类型

再次提到上面这一点,请注意,您的代码(DT[ , lapply(.SD, as.factor)])返回一个new data.table,并且根本不会更改DT.一种(incorrect)方法是用base中的data.frames来完成,即用返回的新data.table覆盖旧data.table,即DT = DT[ , lapply(.SD, as.factor)].

这是浪费,因为它涉及到创建DT的副本,而当DT很大时,这可能是效率杀手.解决此问题的正确方法是使用`:=`(例如DT[ , names(DT) := lapply(.SD, as.factor)])通过引用更新列,这不会创建数据的副本.更多信息请参见data.table's reference semantics vignette.

  • 你提到比较lapply(.SD, sum)colSums的效率.sumdata.table中进行了内部优化(您可以从[]中添加verbose = TRUE参数的输出中注意到这一点);为了看到这一点的实际效果,让我们加强一下你的DT,并运行一个基准测试:

结果:

library(data.table)
set.seed(12039)
nn = 1e7; kk = seq(100L)
DT = setDT(replicate(26L, sample(kk, nn, TRUE), simplify=FALSE))
DT[ , LETTERS[1:2] := .(sample(100L, nn, TRUE), sample(100L, nn, TRUE))]

library(microbenchmark)
microbenchmark(
  times = 100L,
  colsums = colSums(DT[ , !c("A", "B")]),
  lapplys = DT[ , lapply(.SD, sum), .SDcols = !c("A", "B")]
)
# Unit: milliseconds
#     expr       min        lq      mean    median        uq       max neval
#  colsums 1624.2622 2020.9064 2028.9546 2034.3191 2049.9902 2140.8962   100
#  lapplys  246.5824  250.3753  252.9603  252.1586  254.8297  266.1771   100

R相关问答推荐

确定邻国

仅在ggplot的每个方面绘制最丰富的物种

R图中的字体大小和字体样式(带有R底图)

如何使用行政边界形状文件中的人口普查数据调整格栅数据集中的人口数据

从API中抓取R数据SON

单击 map 后,将坐标复制到剪贴板

判断字符串中数字的连续性

获取一个数据库框架的摘要,该数据库框架将包含一列数据库框架,

过滤器数据.基于两列的帧行和R中的外部向量

计算时间段的ECDF(R)

当我添加美学时,geom_point未对齐

在列表中排列R数据框中的列顺序

R如何将列名转换为更好的年和月格式

在R中,如何将误差条放置在堆叠的每个条上?

在点图上绘制置信度或预测区间ggplot2

解析嵌套程度极高的地理数据

变长向量的矢量化和

按两个因素将观测值分组后计算单独的百分比

如何在内联代码中添加额外的空格(R Markdown)

如何使用grepl()在数据帧列表中 Select 特定字符串?