【问题标题】:R: Fast Subsetting Large Data Table Conditioned on Key Words in One of the ColumnsR:以其中一列中的关键字为条件的快速子集大数据表
【发布时间】:2015-12-21 15:58:20
【问题描述】:

我正在使用的数据表是这样的

require(data.table)
set.seed(2)
dt <- data.table(user=c(rep('a', 3), rep('b', 2), rep('c', 4)),
                 type=c(sample(LETTERS[1:4], 3), 
                        sample(LETTERS[1:4], 2),
                        sample(LETTERS[1:4], 4))
                 )

这是

   user type
1:    a    A
2:    a    C
3:    a    B
4:    b    A
5:    b    C
6:    c    D
7:    c    A
8:    c    B
9:    c    C     

我只想在ABC 中查找特定类型的用户。在上面的示例中,用户c 不合格,因为他的一个类型记录中有D。所以期望的输出应该是

   user type
1:    a    A
2:    a    C
3:    a    B
4:    b    A
5:    b    C

我想到的第一种方法显然效率低下,将dtsplit(dt, dt$user) 分开,并检查greplnrow 是否相同,然后是索引和rbindlist。由于我实际使用的数据表有 10989251 行,因此需要一种有效的方法来进行子集化。

【问题讨论】:

    标签: r data.table subset


    【解决方案1】:

    按'user'分组,ifall'type'中的元素只有前三个LETTERS,我们得到Data.table的子集(.SD)。这里我使用%chin% 进行向量比较,因为它是%in% 的更快版本,针对character 向量进行了优化。

    dt[, if(all(type %chin% LETTERS[1:3])) .SD, by = user]
    #    user type
    #1:    a    A
    #2:    a    C
    #3:    a    B
    #4:    b    A
    #5:    b    C
    

    【讨论】:

    • 酷,谢谢。顺便问一下,chinin 有什么不同?
    • @Francis 根据?"%chin%"中的描述,是字符向量的更快匹配,已经优化。
    【解决方案2】:

    使用经典过滤器选择:

    dt[unlist(by(type, user, function(x) !!cumprod(x %in% LETTERS[1:3]))),]
    #   user type
    #1:    a    A
    #2:    a    C
    #3:    a    B
    #4:    b    A
    #5:    b    C
    

    【讨论】:

      【解决方案3】:

      有些人可能会觉得这种方式不太优雅,但它可能会更快:找到具有 D 类型的用户,然后排除他们。如果没有重复的用户类型对或重复的用户类型对很少,则可以跳过唯一的。

      badusers = dt[type=='D',unique(user)];
      dt.ABCs = dt[!user %in% badusers,];
      

      【讨论】:

        猜你喜欢
        • 2015-11-08
        • 2020-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-03
        • 2020-09-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多