总计一年内的公司数量

时间:2017-11-13 04:08:36

标签: r dplyr data.table tidyr

假设我有一个如下数据框:

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家公司退出。谢谢!

4 个答案:

答案 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按照提供的顺序排序。如果没有,就必须先按年份排序。

以下是评论中来自thelatemail的建议方式,结果如下:

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;年份。包括它们是可能的,但还有很多额外的步骤。使用两个库dplyrtidyr,我们可以完成整个过程。

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会计算每组一次的值,我们得到enteredexited,我们会生成一个计数变量count
  • 现在我们按enteredexited分组(顺序很重要),因此我们会在两年的交叉上进行分组
  • 我们现在用几年的组合来计算我们的计数变量。 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的预期结果包括年份20012003的列,尽管它们只包含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()中给出的年份范围来控制。例如,可以通过

删除2003至2005年的空白年份
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