我的问题涉及使用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))
我的问题是(正如我上面所说)我想要一个数据集,其中包含0个没有任何相关操作的id x日期对。例如,如果在2007-10-10没有观察到John12的操作,我希望输出为id
x date
对返回一行,计数为0.
我考虑过创建上面的框架,然后使用空框架进行合并,但我确信必须有一个更简单的解决方案。任何建议非常感谢!
答案 0 :(得分:6)
这是一个简单的选项,改为使用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]
我们的想法是创建所有可能的id
和date
对(这是CJ
部分所做的),然后将其合并,计算出现次数。
答案 1 :(得分:3)
这就是你可以做到的方式,虽然我只使用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