gather() 有两个键列

gather() with two key columns

我有一个包含两行数据的数据集,我想使用类似 gather() 的方法来整理它们,但不知道如何将它们标记为关键列。

数据看起来像:

Country  US   Canada  US 
org_id   332  778     920
02-15-20 25   35      54
03-15-20 30   10      60

我希望它看起来像

country  org_id  date      purchase_price 
US       332      02-15-20 25
Canada   778      02-15-20 35
US       920      02-15-20 54
US       332      03-15-20 30
Canada   778      03-15-20 10
US       920      03-15-20 60

例如,我知道 gather() 可以将国家/地区行移动到列,但是有没有办法将国家/地区和 org_id 行都移动到列?

数据中有重复的列名不是一个好主意,所以我将重命名其中一个。

names(df)[4] <- 'US_1'
  • gather 已停用并替换为 pivot_longer

  • 这不是传统的重塑,因为第一行中的数据需要与其余行区别对待,因此我们可以单独执行重塑并将结果组合起来得到一个最终数据帧。

library(dplyr)
library(tidyr)

df1 <- df %>% slice(-1L) %>% pivot_longer(cols = -Country)

df %>% 
  slice(1L) %>%
  pivot_longer(-Country, values_to = 'org_id') %>%
  select(-Country) %>%
  inner_join(df1, by = 'name') %>%
  rename(Country = name, date = Country) -> result

result

#  Country org_id date     value
#  <chr>    <int> <chr>    <int>
#1 US         332 02-15-20    25
#2 US         332 03-15-20    30
#3 Canada     778 02-15-20    35
#4 Canada     778 03-15-20    10
#5 US_1       920 02-15-20    54
#6 US_1       920 03-15-20    60

数据

df <- structure(list(Country = c("org_id", "02-15-20", "03-15-20"), 
    US = c(332L, 25L, 30L), Canada = c(778L, 35L, 10L), US = c(920L, 
    54L, 60L)), class = "data.frame", row.names = c(NA, -3L))

首先,我们将Countryorg_id

粘贴在一起
library(tidyverse)

data <- set_names(data, paste(names(data), data[1,], sep = "-")) 
data
  Country-org_id US-332 Canada-778 US-920
1         org_id    332        778    920
2       02-15-20     25         35     54
3       03-15-20     30         10     60

然后,我们删除第一行,旋转 table 并分隔列名。

df <-  data %>% 
    slice(2:n()) %>% 
    rename(date = `Country-org_id`) %>% 
    pivot_longer(cols = -date, values_to = "price") %>% 
    separate(col = name, into = c("country", "org_id"), sep = "-")

df

# A tibble: 6 x 4
  date     country org_id price
  <chr>    <chr>   <chr>  <int>
1 02-15-20 US      332       25
2 02-15-20 Canada  778       35
3 02-15-20 US      920       54
4 03-15-20 US      332       30
5 03-15-20 Canada  778       10
6 03-15-20 US      920       60