【问题标题】:Reshape data.frame with multiple headers用多个标题重塑 data.frame
【发布时间】:2021-10-02 07:10:46
【问题描述】:

我的 data.frame 如下所示:

name country1 country1 country2 country2 country3
code1 code1 code2 code2 code3
sector1 sector2 sector1 sector2 sector1
country1 ### ### ### ### ###
country2 ### ### ### ### ###
country3 ### ### ### ### ###
country4 ### ### ### ### ###

## 是数字。

我想这样重塑它:

name country code sector number
country1 country2 code 2 sector 1 ###
country1 country2 code 2 sector 2 ###
country1 country3 code 3 sector 1 ###
country1 country3 code 3 sector 2 ###
country2 country2 code 2 sector 2 ###
country3 country1 code 1 sector 1 ###
country4 country3 code 3 sector 1 ###

如何整理我的数据集?我的问题是原始数据带有这种奇怪的格式,其中有多个标题,所以我不能简单地使用pivot_longer

非常感谢

【问题讨论】:

  • 您能否使用dput 以可重现的格式提供您的数据?阅读how to give a reproducible example
  • 您可以从worldmrio.com/unctadgvc下载数据。这是第三个可用的数据集。我用read.delimsep = "/t"打开了.txt文件
  • 我做了最后的尝试来解决你的问题。看看我答案底部的编辑。

标签: r multiple-columns rows reshape


【解决方案1】:

我相信有更好的方法,但你可以使用dplyr

data %>% 
  slice(1:2) %>% 
  mutate(across(starts_with("country"), ~ paste0(.x, collapse = "_")),
         name = "name") %>% 
  slice(1) %>% 
  mutate(across(starts_with("country"), ~ paste0(cur_column(), "_", .x))) %>% 
  {`colnames<-`(data, unlist(.))} %>% 
  slice(3:n()) %>% 
  pivot_longer(starts_with("country"), 
               names_to = c("country", "code", "sector"),
               names_pattern="(country\\d+).+(code\\d+).+(sector\\d+)") %>%
  filter(name != country)

返回

# A tibble: 15 x 5
   name     country  code  sector  value
   <chr>    <chr>    <chr> <chr>   <chr>
 1 country1 country2 code2 sector1 ###  
 2 country1 country2 code2 sector2 ###  
 3 country1 country3 code3 sector1 ###  
 4 country2 country1 code1 sector1 ###  
 5 country2 country1 code1 sector2 ###  
 6 country2 country3 code3 sector1 ###  
 7 country3 country1 code1 sector1 ###  
 8 country3 country1 code1 sector2 ###  
 9 country3 country2 code2 sector1 ###  
10 country3 country2 code2 sector2 ###  
11 country4 country1 code1 sector1 ###  
12 country4 country1 code1 sector2 ###  
13 country4 country2 code2 sector1 ###  
14 country4 country2 code2 sector2 ###  
15 country4 country3 code3 sector1 ###  

注意:我过滤了 name != country,因为在您预期的输出中,那些匹配的行不存在。

编辑

最后一次尝试:

data %>% 
  slice(1:2) %>% 
  rename(name = X) %>% 
  mutate(across(c(-name), ~ paste0(.x, collapse = "_")),
         name = "name") %>% 
  slice(1) %>% 
  mutate(across(c(-name), ~ paste0(cur_column(), "_", .x))) %>% 
  {`colnames<-`(data, unlist(.))} %>% 
  slice(3:n()) %>% 
  pivot_longer(c(-name), 
               names_to = c("country", "code", "sector"),
               names_pattern="(country\\d+).+(code\\d+).+(sector\\d+)") %>%
  filter(name != country)

【讨论】:

  • 谢谢。不幸的是,我发布的数据集只是一个程式化的数据集。原来的标签有实际的国家名称(“阿富汗,阿尔巴尼亚..),所以我不能使用starts_with 对标签进行分组。我在我的问题中发布了 cmets 中原始数据集的链接。
  • starts_with("country") 替换为c(-name)
  • 这种情况下会报错:Can't subset columns that don't exist
  • 你的第一列像你的例子一样被命名为“name”?
  • 它被命名为“X”,我尝试使用c(-data$X)。现在它被命名为“名称”,我尝试使用c(-data$name)。结果相同
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
相关资源
最近更新 更多