【问题标题】:How to divide data programmatically in a data table in R如何以编程方式在R中的数据表中划分数据
【发布时间】:2014-03-15 08:11:00
【问题描述】:

我有一个代码如下:

newdata <- ddply(data, .(SIC,FYEAR), function(x){if(nrow(x)>7) x else NULL});

在此代码中,该函数应用于被SICFYEAR 划分的每个数据片段。如何编写允许在数据表中以编程方式创建片段的通用函数?类似的,

newdata <- ddply(data, .(col1,col2,...,coln), function(x){if(nrow(x)>7) x else NULL});

但是数据表中的等效解决方案,其中 n 和列的名称都以编程方式给出。如果有人可以让我知道基于数据表的解决方案会更有帮助。谢谢。

一个可重现的例子如下:

require(data.table)
data <- data.table(structure(list(SIC = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1), FYEAR = c(1999, 1999, 1999, 1999, 1999, 2000, 2000, 
2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2001, 2001, 2001, 
2001, 2001, 2001, 2001, 2001, 2001, 2001, 2002, 2002, 2002, 2002, 
2002, 2002, 2002, 2002, 2002, 2002, 2003, 2003, 2003, 2003, 2003, 
2003, 2003, 2003, 2003, 2003, 2004, 2004, 2004, 2004, 2004, 2004, 
2004, 2004, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2006, 2006, 
2006, 2006, 2006, 2006, 2006, 2007, 2007, 2007, 2007, 2007, 2008, 
2008, 2008, 2008, 2008, 2009, 2009, 2009, 2009, 2009, 2009, 2010, 
2010, 2010, 2010, 2010, 2010, 2010, 2010, 2011, 2011, 2011, 2011, 
2011, 2011, 2011, 2011, 2012), BIG4 = c(0, 0, 1, 1, 1, 0, 0, 
0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 
1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 
1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 
0, 0, 1, 1, 1, 1, 1, 1, 0)), .Names = c("SIC", "FYEAR", "BIG4"
), row.names = c(31842L, 48128L, 982L, 2173L, 8655L, 31843L, 
55799L, 62384L, 983L, 2174L, 7034L, 8656L, 36790L, 51631L, 69782L, 
31844L, 55800L, 62385L, 984L, 7035L, 8657L, 18874L, 36791L, 51632L, 
69783L, 985L, 7036L, 8658L, 13375L, 18875L, 31845L, 36792L, 51633L, 
62386L, 69784L, 986L, 2177L, 7037L, 8659L, 18876L, 36793L, 51634L, 
55801L, 62387L, 69785L, 36794L, 987L, 2178L, 7038L, 8660L, 18877L, 
51635L, 62388L, 7039L, 36795L, 988L, 2179L, 8661L, 18878L, 62389L, 
19823L, 36796L, 989L, 2180L, 8662L, 18879L, 62390L, 19824L, 36797L, 
2181L, 8663L, 18880L, 19825L, 36798L, 2182L, 8664L, 69790L, 24268L, 
24325L, 36799L, 2183L, 8665L, 31852L, 24269L, 29392L, 36800L, 
2184L, 8666L, 18883L, 31853L, 69792L, 24270L, 36801L, 2185L, 
8667L, 18884L, 26989L, 31854L, 69793L, 30612L), class = "data.frame"))

编辑:

假设我想写一个函数,并传递cols = c("BIG4")cols = c("SIC", "FYEAR")等来定义用于分片数据的列,然后删除那些少于8个数据点的分片,然后合并左边片段,然后返回连接的数据集。

【问题讨论】:

    标签: r data.table plyr


    【解决方案1】:

    这里有两种方法。

    # using .SD
    foo.SD <- function(x, .by,.thresh){
            x[,if(.N>.thresh){.SD},by=.by]
          }
    # using .I (should be slightly faster as .SD is not loaded into memory for
    # each group
    foo.I <- function(x, .by,.thresh){
           x[x[,if(.N>.thresh){.I},by=.by]$V1]
     }
    
    foo.SD(data, c('SIC','FYEAR'), 7)
    foo.I(data, c('SIC','FYEAR'), 7)
    

    【讨论】:

      【解决方案2】:

      您可以将nrow 条件放在[.data.tablej 参数中,诀窍是为未通过所需行数的组返回相同data.table 的空版本,使用@ 987654325@:

      # Discard chunks of a data.table which have less than a specified number of rows
      throwAwaySmall <- function(data, cols, rowSizeThreshold) {
        data[, .SD[.N>rowSizeThreshold], by=cols]
      }
      

      下面的代码现在相当于你的第一段代码:

      throwAwaySmall(data, c("SIC", "FYEAR"), 7) 
      

      【讨论】:

      • 谢谢,但我想要一个类似的数据表解决方案。
      • @Sumit 我现在已将其更改为正确的data.table 解决方案
      • 或者更简洁,data[, .SD[.N&gt;rowSizeThreshold], by=cols]
      • @ScottRitchie 您的代码返回的表只有三列 - SIC、FYEAR 和给定碎片数据中的行数。它完全忽略其他数据列,并且不会在输出表中返回它们。
      • 请注意,这将是低效的,因为它通过分组为每个调用 [.data.table。很多组 = 很多不必要的开销。
      【解决方案3】:

      这个怎么样:

      DT<-data.table(df,key=c("SIC","FYEAR"))
      DT[,list(BIG4,incl=length(BIG4)>7),by=c("SIC","FYEAR")][incl==T]
      

      【讨论】:

      • 我觉得我的问题还不够清楚。我想使用通用代码对数据进行分段,这意味着我可以使用 .(BIG4) 或 .(SIC,BIG4) 或...代替 .(SIC,FYEAR) 或 ...我希望您明白这一点。
      猜你喜欢
      • 2016-01-29
      • 2017-09-26
      • 1970-01-01
      • 1970-01-01
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      • 2014-11-14
      • 1970-01-01
      相关资源
      最近更新 更多