R 使用data.table筛选、聚合并再次筛选

R 使用data.table筛选、聚合并再次筛选,r,data.table,dplyr,R,Data.table,Dplyr,我正在处理一个大表,需要经常使用聚合。我使用dplyr处理大部分数据,因为语法对我来说更有意义。我认为哈德利在dplyr语法的可读性方面有一个非常正确的观点。但是,脚本的某些部分需要更高的效率,我正在尝试在这个过程中学习data.table 给出下面的代码,它给出了表格的一部分,根据ratio和expression列(前2个过滤器)的值排除行,然后给出了至少有2个副本的观察值的行,这些行按四倍进行聚合,从而得到维度101K x 13 mult.obs <- tidy.dt %>%

我正在处理一个大表,需要经常使用聚合。我使用
dplyr
处理大部分数据,因为语法对我来说更有意义。我认为哈德利在
dplyr
语法的可读性方面有一个非常正确的观点。但是,脚本的某些部分需要更高的效率,我正在尝试在这个过程中学习
data.table

给出下面的代码,它给出了表格的一部分,根据
ratio
expression
列(前2个过滤器)的值排除行,然后给出了至少有2个
副本的观察值的行,这些行按四倍进行聚合,从而得到维度101K x 13

mult.obs <- tidy.dt %>% 
  filter(ratio != "H.L") %>%
  filter(!is.na(expression)) %>%
  group_by(Seq, Gene.names, condition, ratio) %>%
  filter(n_distinct(replicate) > 1)
mult.obs%
过滤器(比率!=“H.L”)%>%
过滤器(!is.na(表达式))%>%
分组依据(顺序、基因名称、条件、比率)%>%
过滤器(n_独立(复制)>1)
我在将语句转换为data.table语法时遇到困难,我的第一次尝试是:

> dt <- tidy.dt[ratio != "H.L" & !is.na(expression), 
+         by = .(Seq, Gene.names, condition, ratio)][
+         uniqueN(replicate > 1)
+         ]

Error in `[.data.table`(tidy.dt, ratio != "H.L" & !is.na(expression),  : 
  'by' or 'keyby' is supplied but not j
>dt 1)
+         ]
“[.data.table”中的错误(tidy.dt,ratio!=“H.L”&!is.na(表达式),:
提供“by”或“keyby”,但不提供j
正如您所看到的,这会导致错误

我尝试了以下方法,但结果是得到了一个更长更窄的表(141K x 5)。除了得到更多的行(?!)之外,我还没有得到我想要得到的所有列

> dt <- tidy.dt[ratio != "H.L" & !is.na(expression), 
+               uniqueN(replicate > 1), 
+               by = .(Seq, Gene.names, condition, ratio)]
>dt1),
+by=(Seq,Gene.names,条件,比率)]
在第n次查看data.table文档之后,我知道
[I,j,by]
语法大致对应于SQL术语
,其中,选择| update,groupby
,我理解这里给出的示例,但一旦您冒险到新的领域,获得
I,j,by
的权利就会变得相当复杂


我这里没有得到什么?

您需要使用data.table中的
.SD
习惯用法。当使用
by
时,这在
j
参数中使用(也可以在不使用
by
的情况下使用,但我发现它在使用
by
时非常有用)。“SD”是指“数据子集”(或类似的东西)。与
by
组合使用时,它包含每组的data.table

例如,使用iris数据集:

as.data.table(iris)[, .SD[length(unique(Sepal.Length)) == 21], by = Species]
在这里,我们按物种分组,然后找到正好有21个萼片长度唯一值的组

因此,对于您的问题,您可以:

tidy.dt[ratio != "H.L" & !is.na(expression),
  .SD[uniqueN(replicate) > 1],
  by = .(Seq, Gene.names, condition, ratio)]

使用“expression”这样的列名有时会有问题。这是一个重要的R函数名。至少这种做法很容易导致误导性的错误信息。你的两个DT电话都没有分配任务。赋值函数为“:=”。多步骤流程可能需要链接'[.data.table'@42-这是因为我不想更改表
tidy.dt
,而是想有一个经过筛选的副本。我不需要新的列,只需要根据聚合条件进行筛选。您可能知道这一点,但由于缺少一个。您的代码非常接近,只需使用
if(uniqueN(replicate)>1L).SD
j
参数中。希望最终会有更自然的语法。@Frank是的,我意识到人们之所以投反对票是因为缺乏示例,但我发现这是幼稚的,而且说实话过于热情。我在这里问的问题与实际的表无关,而是语法。我相信我成功了od努力解释我想要达到的目标。如果有人认为问题不清楚或太简单或其他什么,他们不必回答。但是热情的向下/近距离投票阻止任何有用的答案出现,这会适得其反,相当令人沮丧。@顺便说一句,谢谢你的回答。我不完全确定是什么.SD符号是选择所有行所必需的,但它是有效的。如果您愿意提交您的建议作为答案,我愿意投票并接受该答案。谢谢!两个快速问题:1.是否需要在某个地方定义
SD
?2.是否
.SD[uniqueN(replicate)>1]
评估为
j=If(uniqueN)(replicate)>1L).SD
内部或@posdef x[cond],其中cond为TRUE或FALSE与if(cond)x相同。但是,如果cond是一个缺少的值,“if”版本将出错,如果其长度大于1,它将发出警告。我认为这些是调试的理想结果,因此我总是采用“if”方式。