使用 pivot_longer 和 pivot_gather 整理一个虚拟填充的数据框

Using pivot_longer and pivot_gather to tidy a dummy-filled dataframe

朋友们,您好!我有一个数据框,其中包含来自一个行业的大约 200 万名员工以及他们在 2000 年至 2019 年期间合作过的公司。它看起来像这样:

| ID |  FIRM | NAICS | Q1 | Q2 | Q3 | Q4 |
| A  |   001 |   100 |  1 |  1 |  1 |  1 |
| B  |   002 |   200 |  1 |  1 |  0 |  0 |
| B  |   003 |   100 |  0 |  0 |  1 |  1 |

... 其中 NAICS 是某人在给定季度工作的公司的行业代码。例如,A四个季度都在同一个行业; 个人 BQ3行业 200 移动到 行业 100 ] 靠搬家公司。

我希望得到的框架如下所示:

| ID |  Q1 |  Q2 |  Q3 |  Q4 |
| A  | 100 | 100 | 100 | 100 |
| B  | 200 | 200 | 100 | 100 |

... 这样我就可以跟踪人们来自哪些行业,然后构建类似于 this NYT animated sankey diagram 的东西。

你能帮我弄清楚如何从第一个到第二个吗?我的直觉是我需要使用 dplyr::pivot_longer()dplyr::pivot_wider(),我知道它们正在替换 spread()gather()

这里基本上分为三个步骤:

  • 让它变长,每个季度都有自己的行
  • 删除公司在该季度"inactive"所在的行
  • 扩大范围,将 "quarter" 变量扩展到列中
library(dplyr)
library(tidyr)

df %>%
  pivot_longer(
    cols = Q1:Q4,
    names_to = "quarter",
    values_to = "active"
  ) %>%
  filter(active == 1) %>%
  select(- FIRM, - active) %>%
  pivot_wider(
    names_from = quarter,
    values_from = NAICS
  )

输出:

# A tibble: 2 x 5
  ID       Q1    Q2    Q3    Q4
  <fct> <int> <int> <int> <int>
1 A       100   100   100   100
2 B       200   200   100   100

由于您的数据框包含 200 万员工的 ID,也许使用 data.table 包中的 meltdcast 函数的解决方案对您来说会更快:

library(data.table)
setDT(dt)
Col <- paste("Q",1:4,sep = "")
dt.m <- melt(dt, measure = list(Col), variable.name = "quarter", value.name = "value")
dt.m <- dt.m[value == 1]
dt.m[,value:= NULL]
dt.m <- dcast(dt.m, ID~quarter, value.var = "NAICS")

   ID  Q1  Q2  Q3  Q4
1:  A 100 100 100 100
2:  B 200 200 100 100

可重现数据

dt <- data.frame(ID = c("A","B","B"),
                 NAICS = c(100,200,100),
                 Q1 = c(1,1,0),
                 Q2 = c(1,1,0),
                 Q3 = c(1,0,1),
                 Q4 = c(1,0,1))