【问题标题】:Using dplyr for frequency counts of interactions, must include zero counts使用 dplyr 进行交互频率计数,必须包括零计数
【发布时间】:2014-07-09 19:13:22
【问题描述】:

我的问题涉及使用 R

中的 dplyr 包编写代码

我有一个相对较大的数据框(大约 500 万行),包含 2 列:第一列带有单独的标识符 (id),第二列带有日期 (date)。目前,每一行表示在日期列中的日期发生的动作(id 列中的个人所采取的)。大约有 300,000 个独特的个体,以及大约 2600 个独特的日期。例如,数据的开头是这样的:

    id         date
    John12     2006-08-03
    Tom2993    2008-10-11
    Lisa825    2009-07-03
    Tom2993    2008-06-12
    Andrew13   2007-09-11

我想重新调整数据,以便为每个可能的id x date 对设置一行,另外一列计算发生的事件总数(可能取值 0)在给定日期列出的个人。

我使用 dplyr 包取得了一些成功,我用它来将数据中观察到的 id x 日期计数制成表格。

到目前为止,这是我用来统计 id x date 计数的代码:(我的数据框称为 df

reduced = df %.% 
  group_by(id, date) %.%
  summarize(length(date))

我的问题是(正如我上面所说)我想要一个数据集,其中还包含 id x 日期对的 0,这些日期对没有任何关联的操作。例如,如果在 2007 年 10 月 10 日没有观察到 John12 的操作,我希望输出为该 id x date 对返回一行,计数为 0。

我考虑过创建上面的框架,然后与一个空框架合并,但我相信一定有一个更简单的解决方案。任何建议都非常感谢!

【问题讨论】:

    标签: r dplyr frequency interaction large-data


    【解决方案1】:

    这是一个简单的选项,使用 data.table 代替:

    library(data.table)
    
    dt = as.data.table(your_df)
    
    setkey(dt, id, date)
    
    # in versions 1.9.3+
    dt[CJ(unique(id), unique(date)), .N, by = .EACHI]
    #          id       date N
    # 1: Andrew13 2006-08-03 0
    # 2: Andrew13 2007-09-11 1
    # 3: Andrew13 2008-06-12 0
    # 4: Andrew13 2008-10-11 0
    # 5: Andrew13 2009-07-03 0
    # 6:   John12 2006-08-03 1
    # 7:   John12 2007-09-11 0
    # 8:   John12 2008-06-12 0
    # 9:   John12 2008-10-11 0
    #10:   John12 2009-07-03 0
    #11:  Lisa825 2006-08-03 0
    #12:  Lisa825 2007-09-11 0
    #13:  Lisa825 2008-06-12 0
    #14:  Lisa825 2008-10-11 0
    #15:  Lisa825 2009-07-03 1
    #16:  Tom2993 2006-08-03 0
    #17:  Tom2993 2007-09-11 0
    #18:  Tom2993 2008-06-12 1
    #19:  Tom2993 2008-10-11 1
    #20:  Tom2993 2009-07-03 0
    

    在 1.9.2 或之前的版本中,等效表达式省略了显式 by

    dt[CJ(unique(id), unique(date)), .N]
    

    这个想法是创建所有可能的iddate 对(这是CJ 部分所做的),然后将其合并回来,计算出现次数。

    【讨论】:

    • 另外:dcast.data.table(dt[, bla := "count"], id + date ~ bla, drop=FALSE, fun.agg=length),虽然我更喜欢你的(并且可能会更快,因为这里的每个组都有eval(length(.))
    • 另外值得注意的是 data.table 不接受 "Date" 对象
    • @D8Amonk 这不是真的
    【解决方案2】:

    这就是你可以做到的方式,尽管我使用dplyr 仅部分用于计算原始df 和left_join 中的频率。正如您在问题中已经建议的那样,我创建了一个新的 data.frame 并将其与现有的合并。我想如果你想只在dplyr 中执行它,那将需要你以某种方式在过程中rbind 很多行,我认为这种方式可能比另一种方式更快。

    require(dplyr)
    
    original <- read.table(header=T,text="    id         date
    John12     2006-08-03
    Tom2993    2008-10-11
    Lisa825    2009-07-03
    Tom2993    2008-06-12
    Andrew13   2007-09-11", stringsAsFactors=F)
    
    original$date <- as.Date(original$date) #convert to date
    
    #get the frequency in original data in new column and summarize in a single row per group
    original <- original %>%
      group_by(id, date) %>%
      summarize(count = n())            
    
    #create a sequence of date as you need it
    dates <- seq(as.Date("2006-01-01"), as.Date("2009-12-31"), 1)    
    
    #create a new df with expand.grid to get all combinations of date/id
    newdf <- expand.grid(id = original$id, date = dates)     
    
    #remove dates
    rm(dates)
    
    #join original and newdf to have the frequency counts from original df
    newdf <- left_join(newdf, original, by=c("id","date"))   
    
    #replace all NA with 0 for rows which were not in original df
    newdf$count[is.na(newdf$count)] <- 0          
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-16
      • 1970-01-01
      • 1970-01-01
      • 2012-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多