假设我有一个如下数据框:
dt=structure(list(id = c(1L, 1L, 1L, 1L, 2L, 3L, 3L, 3L, 4L, 4L,
4L, 4L, 5L, 5L, 6L, 6L), year = c(2001L, 2002L, 2003L, 2004L,
2002L, 2002L, 2003L, 2004L, 2002L, 2003L, 2004L, 2005L, 2001L,
2002L, 2001L, 2002L)), .Names = c("firm", "year"), row.names = c(NA,
-16L), class = "data.frame")
dt
firm year
1 1 2001
2 1 2002
3 1 2003
4 1 2004
5 2 2002
6 3 2002
7 3 2003
8 3 2004
9 4 2002
10 4 2003
11 4 2004
12 4 2005
13 5 2001
14 5 2002
15 6 2001
16 6 2002
现在,我希望总结一年内退出市场的公司数量。例如,我想要一个这样的表:
resulttable
All 2001 2002 2003 2004 2005
2001 3 0 2 0 1 0
2002 3 0 1 0 1 1
结果表的第一行意味着2001年有3家公司进入市场,2003年有2家公司退出,2004年有1家公司退出。谢谢!
答案 0 :(得分:4)
您可以制表"输入"年和"退出"年table
:
res <- table(
dt$year[!duplicated(dt$firm)],
factor(dt$year[!duplicated(dt$firm, fromLast = TRUE)], levels = unique(dt$year))
)
res <- as.data.frame.matrix(res)
res$All <- rowSums(res)
# > res
# 2001 2002 2003 2004 2005 All
# 2001 0 2 0 1 0 3
# 2002 0 1 0 1 1 3
我假设dt
按照提供的顺序排序。如果没有,就必须先按年份排序。
addmargins(table(
dt$year[!duplicated(dt$firm)],
factor(dt$year[!duplicated(dt$firm, fromLast = TRUE)], levels = unique(dt$year))
), 2)
# 2001 2002 2003 2004 2005 Sum
# 2001 0 2 0 1 0 3
# 2002 0 1 0 1 1 3
答案 1 :(得分:4)
Here is an option using dcast
from data.table
. Convert the 'data.frame' to 'data.table' (setDT(dt)
), grouped by 'firm' get the range
of 'year' into two columns, dcast
into 'wide' with drop = FALSE
to avoid removing the unused levels and then sum the values in the row with Reduce
library(data.table)
dcast(setDT(dt)[, as.list(range(year)), firm], V1 ~ factor(V2, levels = unique(dt$year)),
drop =FALSE)[, All := Reduce(`+` , .SD), .SDcols = -1][]
# V1 2001 2002 2003 2004 2005 All
#1: 2001 0 2 0 1 0 3
#2: 2002 0 1 0 1 1 3
答案 2 :(得分:3)
这不是一个完整的解决方案,因为结果不包括遗漏的&#39;退出&#39;年份。包括它们是可能的,但还有很多额外的步骤。使用两个库dplyr
和tidyr
,我们可以完成整个过程。
library(dplyr)
library(tidyr)
dt %>%
group_by(firm) %>%
summarise(entered=min(year),exited=max(year),count=1) %>%
group_by(entered,exited) %>%
summarise(count=sum(count)) %>%
mutate(All = sum(count)) %>%
ungroup() %>%
spread(exited,count,fill=0)
> # A tibble: 2 x 5
> entered All `2002` `2004` `2005`
> * <dbl> <dbl> <dbl> <dbl> <dbl>
> 1 2001 3 2 1 0
> 2 2002 3 1 1 1
group_by
表示我们希望在firm
summarise
会计算每组一次的值,我们得到entered
,exited
,我们会生成一个计数变量count
entered
和exited
分组(顺序很重要),因此我们会在两年的交叉上进行分组summarise
这里放弃了最正确的分组级别mutate
在这种情况下创建一个新变量All
,它看起来就像summarise
但不是折叠行,而是在我们的组中计算它,复制重复的行。< / LI>
ungroup
删除了残留分组spread
为我们的密钥中的每个值创建一个列,用指定的值列填充它,用0填充缺失值答案 3 :(得分:1)
使用data.table
的方法稍有不同,在从长格式转换为宽格式之前创建总计:
library(data.table)
setDT(dt)[, .(entry = min(year), exit = max(year)), by = firm][, All := .N, by = entry][
, dcast(.SD, entry + All ~ exit, length, value.var = "firm")]
entry All 2002 2004 2005 1: 2001 3 2 1 0 2: 2002 3 1 1 1
这已经传达了OP在问题中口头描述的所有重要结果。
但是,OP的预期结果包括年份2001
和2003
的列,尽管它们只包含0.如果需要显示没有条目或退出的年份,则可以完成此操作通过在计算总计All
之前完成缺失的年份并重新整形:
setDT(dt)[, .(entry = min(year), exit = max(year)), by = firm][
CJ(entry = dt$year, exit = dt$year, unique = TRUE), on = .(entry, exit)][
, All := sum(!is.na(firm)), by = entry][][
, dcast(.SD, entry + All ~ exit, function(x) (sum(!is.na(x))), value.var = "firm")]
entry All 2001 2002 2003 2004 2005 1: 2001 3 0 2 0 1 0 2: 2002 3 0 1 0 1 1 3: 2003 0 0 0 0 0 0 4: 2004 0 0 0 0 0 0 5: 2005 0 0 0 0 0 0
通过加入由{em>交叉加入 year
创建的CJ()
的所有可用组合的表格,可以完成缺失的年份。完成在NA
中引入了大量firm
值,因此length(firm)
必须由sum(!is.na(firm))
替换为聚合函数。
生成的宽格式的扩展可以通过CJ()
中给出的年份范围来控制。例如,可以通过
setDT(dt)[, .(entry = min(year), exit = max(year)), by = firm][
CJ(entry = min(entry):max(entry), exit = dt$year, unique = TRUE), on = .(entry, exit)][
, All := sum(!is.na(firm)), by = entry][][
, dcast(.SD, entry + All ~ exit, function(x) (sum(!is.na(x))), value.var = "firm")]
entry All 2001 2002 2003 2004 2005 1: 2001 3 0 2 0 1 0 2: 2002 3 0 1 0 1 1
完全复制OP预期的resulttable
。
或者,也可以通过
删除2001年和2005年的空出口年份setDT(dt)[, .(entry = min(year), exit = max(year)), by = firm][
CJ(entry = min(entry):max(entry), exit = min(exit):max(exit)), on = .(entry, exit)][
, All := sum(!is.na(firm)), by = entry][][
, dcast(.SD, entry + All ~ exit, function(x) (sum(!is.na(x))), value.var = "firm")]
entry All 2002 2003 2004 2005 1: 2001 3 2 0 1 0 2: 2002 3 1 0 1 1