首页 > 解决方案 > 如何重塑 R 中的数据,将顶部日期行应用为列并按 id 分组

问题描述

嗨,我有这样的数据

date    2020/06/10  2020/06/10  2020/06/10  2020/06/11  2020/06/11  2020/06/11  
id          x           y           z           x           y           z           
10432       0           0           0           0           0           0           
10668       0           0           0           0           0           0           
11088       0           0           0           0           0           0   

我想要这样的输出

id          date    x   y   z
10432   2020/06/10  0   0   0
10432   2020/06/11  0   0   0
10668   2020/06/10  0   0   0
10668   2020/06/11  0   0   0
11088   2020/06/10  0   0   0
11088   2020/06/11  0   0   0

我想在 R 中获得输出

标签: rlapplyreshapereshape2melt

解决方案


这些数据非常混乱,但是通过一些工作,我设法获得了您想要的输出。


read_table2()这是您提供的示例数据在我使用从readr包中导入后的样子:

library(readr) # 1.3.1

df <- read_table2("date    2020/06/10  2020/06/10  2020/06/10  2020/06/11  2020/06/11  2020/06/11  
id          x           y           z           x           y           z           
10432       0           0           0           0           0           0           
10668       0           0           0           0           0           0           
11088       0           0           0           0           0           0 ")

df[, 8] <- NULL
> df
# A tibble: 4 x 7
  date  `2020/06/10` `2020/06/10_1` `2020/06/10_2` `2020/06/11` `2020/06/11_1` `2020/06/11_2`
  <chr> <chr>        <chr>          <chr>          <chr>        <chr>          <chr>         
1 id    x            y              z              x            y              z             
2 10432 0            0              0              0            0              0             
3 10668 0            0              0              0            0              0             
4 11088 0            0              0              0            0              0   

请注意,在 R 中,您不能有重复的列名,因此它会稍微改变它们。我们必须解决这个问题。(您可能不必完全执行这些步骤,如果您不提供数据,我无法准确知道您的列的名称dput()。)

现在我将当前列名与“id”行粘贴在一起,然后整理列名,以便我们以后可以使用它们:

names(df) <- c("id", paste(df[1, -1], names(df)[-1], sep = "_"))

library(stringr) # 1.4.0

names(df)[-1] <- str_remove(names(df)[-1], "_[1-9]$") # this gets rid of
# the "_1" or "_2" R added automatically when I imported the data

我们现在不再需要第一行,因为它的内容在列名中重复了。

df <- df[-1,]
> df
# A tibble: 3 x 7
  id    `x_2020/06/10` `y_2020/06/10` `z_2020/06/10` `x_2020/06/11` `y_2020/06/11` `z_2020/06/11`
  <chr> <chr>          <chr>          <chr>          <chr>          <chr>          <chr>         
1 10432 0              0              0              0              0              0             
2 10668 0              0              0              0              0              0             
3 11088 0              0              0              0              0              0 

现在我们可以实际处理这个df并从宽格式到长格式:

library(tidyr) # 1.1.0

df %>% pivot_longer(-id, names_to = c(".value", "date"),
                      names_pattern = "(.)_(..../../..)")
# A tibble: 6 x 5
  id    date       x     y     z    
  <chr> <chr>      <chr> <chr> <chr>
1 10432 2020/06/10 0     0     0    
2 10432 2020/06/11 0     0     0    
3 10668 2020/06/10 0     0     0    
4 10668 2020/06/11 0     0     0    
5 11088 2020/06/10 0     0     0    
6 11088 2020/06/11 0     0     0  

所以我们有了它 - 一个使用readr,stringrtidyr包的整理数据解决方案tidyverse- 我认为这是一个非常好的例子,tidyverse它是精确开发的!:)


数据

如果您需要它,这里是df我们在实施之前的整理pivot_longer()

structure(list(id = c("10432", "10668", "11088"), `x_2020/06/10` = c("0", 
"0", "0"), `y_2020/06/10` = c("0", "0", "0"), `z_2020/06/10` = c("0", 
"0", "0"), `x_2020/06/11` = c("0", "0", "0"), `y_2020/06/11` = c("0", 
"0", "0"), `z_2020/06/11` = c("0", "0", "0")), row.names = c(NA, 
-3L), class = c("tbl_df", "tbl", "data.frame"))

推荐阅读