使用data.table同时进行顺序,行过滤和列选择

时间:2015-06-02 20:54:34

标签: r data.table

我正在尝试在R中的一行中执行多个步骤,以从具有多个条件的data.table(dt)中选择一个值。

例如:

set.seed(123)
dt <- data.table(id = rep(letters[1:2],2),
             time = rnorm(4),
             value = rnorm(4)*100)

#    id        time      value
# 1:  a -0.56047565   12.92877
# 2:  b -0.23017749  171.50650
# 3:  a  1.55870831   46.09162
# 4:  b  0.07050839 -126.50612

# Now I want to select the last (maximum time) value from id == "a"
# My pseudo data.table code looks like this

dt[order(time) & id == "a" & .N, value]
# [1] 12.92877 46.09162  

而不是获取这两个值,我只想获得最后一个值(具有更高的时间值)。

如果我一步一步地做到这一点:

dt <- dt[order(time) & id == "a"]
dt[.N, value]
# [1] 46.09162

加成:

如何在不复制data.table的情况下订购data.table:ie

dt <- dt[order(time)]

没有<-。类似于:= - 运算符,例如在dt[, new_val := value*2]中创建新变量而不复制整个data.table。

谢谢,非常感谢任何想法!

2 个答案:

答案 0 :(得分:7)

首先问题,请尝试

dt[id == "a", value[which.max(time)]]
## [1] 46.09162

对于红利问题,请尝试setorder function,它会对您的数据进行排序(您也可以通过在-前面添加time按降序排序)

setorder(dt, time)
dt
#    id        time      value
# 1:  a -0.56047565   12.92877
# 2:  b -0.23017749  171.50650
# 3:  b  0.07050839 -126.50612
# 4:  a  1.55870831   46.09162

此外,如果您已经按时间排序数据,则可以同时执行这两项操作 - 按引用顺序排列并按条件选择value - 单行

setorder(dt, time)[id == "a", value[.N]]

答案 1 :(得分:2)

我知道这是一个较老的问题,但我想补充一些东西。有一个类似的问题我偶然发现了这个问题,尽管David Arenburg的回答确实为这个确切的问题提供了解决方案,但在尝试替换/覆盖过滤和排序的data.table中的值时我遇到了麻烦,所以这里是一种替代方法,它还允许您将<-调用直接应用于已过滤和排序的data.tabe。

关键是data.table允许您将多个[]相互连接。

示例:

dt[id=="a", ][order(time), ][length(value), "value"] <- 0

这也适用于多个条目,只需提供合适的向量作为替换值。

但请注意,作为列表对象的.N需要替换为例如i。列的长度,因为data.table需要j中此位置的整数,并且您要在""中选择的列需要由var isMobileSorted = false; $(window).resize(function() { if ($(window).width() < 768) { if(!isMobileSorted) { // sort mobile $("#widget").insertAfter($("#pictures")); $("#video").insertAfter($("#widget")); $("#reviews").insertAfter($("#contact")); isMobileSorted = true; } } else { if(isMobileSorted) { // resort desktop $("aside").prepend($("#widget")) $("#video").insertAfter($("#widget")); $("#reviews").insertAfter($("#video")); isMobileSorted = false; } } }).resize(); 包裹。

我发现这是更直观的方式,它不仅可以过滤数据表,还可以操纵其值,而无需担心临时表。