【问题标题】:R: Use gather and spread to transpose a time series dataset from wide to longR:使用gather和spread将时间序列数据集从宽转长
【发布时间】:2020-02-18 00:12:06
【问题描述】:

所以我有一个时间序列数据集,它的形状很宽,不适合分析。我打算做的是使用收集和传播以我想要的方式将数据转换为长。

样本数据:

df <- data.frame(
  id = 1:3,
  "X1" = c(100,90,80),
  "X2" = c(100,90,80),
  "X3" = c(100,90,80),
  "X4" = c(100,90,80),
  "X5" = c(100,90,80)
)

> print(df)
  id  X1  X2  X3  X4  X5
1  1 100 100 100 100 100
2  2  90  90  90  90  90
3  3  80  80  80  80  80

期望的输出:

df2 <- data.frame(
  id = c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3),
  "month" = c(1,2,3,4,5,1,2,3,4,5,1,2,3,4,5),
  "balance" = c(100,100,100,100,100,90,90,90,90,90,80,80,80,80,80)
)
print(df2)
> print(df2)
   id month balance
1   1     1     100
2   1     2     100
3   1     3     100
4   1     4     100
5   1     5     100
6   2     1      90
7   2     2      90
8   2     3      90
9   2     4      90
10  2     5      90
11  3     1      80
12  3     2      80
13  3     3      80
14  3     4      80
15  3     5      80

我尝试了什么,我得到了什么:

test_gather <-gather(df, "month", "value", X1:X5,na.rm = FALSE )
> print(test_gather)
   id month value
1   1    X1   100
2   2    X1    90
3   3    X1    80
4   1    X2   100
5   2    X2    90
6   3    X2    80
7   1    X3   100
8   2    X3    90
9   3    X3    80
10  1    X4   100
11  2    X4    90
12  3    X4    80
13  1    X5   100
14  2    X5    90
15  3    X5    80

如上所示,我得到的结果根本没有正确排序。如果可能的话,我希望能够直接通过收集/传播而不在 dplyr 中进行安排来获得所需的输出。

【问题讨论】:

    标签: r


    【解决方案1】:

    这需要在gather 之后的“id”列上添加arrange 并删除前缀(如有必要)

    library(stringr)
    library(dplyr)
    library(tidyr)
    df %>%
       gather(month, balance, -id) %>%
       arrange(id) %>%
       mutate(month = str_remove(month, "^X"))
    #   id month balance
    #1   1     1     100
    #2   1     2     100
    #3   1     3     100
    #4   1     4     100
    #5   1     5     100
    #6   2     1      90
    #7   2     2      90
    #8   2     3      90
    #9   2     4      90
    #10  2     5      90
    #11  3     1      80
    #12  3     2      80
    #13  3     3      80
    #14  3     4      80
    #15  3     5      80
    

    使用来自tidyr_1.0.0pivot_longer,它不会改变顺序

    df %>%
       pivot_longer(cols = -id, names_to = "month", values_to = "balance") %>%
       mutate(month = readr::parse_number(month))
    # A tibble: 15 x 3
    #      id month balance
    #   <int> <dbl>   <dbl>
    # 1     1     1     100
    # 2     1     2     100
    # 3     1     3     100
    # 4     1     4     100
    # 5     1     5     100
    # 6     2     1      90
    # 7     2     2      90
    # 8     2     3      90
    # 9     2     4      90
    #10     2     5      90
    #11     3     1      80
    #12     3     2      80
    #13     3     3      80
    #14     3     4      80
    #15     3     5      80
    

    【讨论】:

      【解决方案2】:

      基础解决方案:

      # Reshape from wide to long: 
      
      df2 <- 
      
        data.frame(
      
          reshape(
      
            df,
      
            direction = "long",
      
            varying = names(df)[names(df) != "id"],
      
            v.names = "value",
      
            idvar = "id",
      
            timevar = "month",
      
            times = names(df)[names(df) != "id"]
      
          ),
      
        row.names = NULL
      
      )
      
      # Order by id:
      
      df2 <- df2[order(df2$id),]
      
      # Keep only month numbers and coerce vector to numeric: 
      
      df2$month <- as.numeric(gsub("^\\D+", "", df2$month))
      

      数据

      df <- data.frame(
      
        id = 1:3,
      
        "X1" = c(100,90,80),
      
        "X2" = c(100,90,80),
      
        "X3" = c(100,90,80),
      
        "X4" = c(100,90,80),
      
        "X5" = c(100,90,80)
      )
      

      【讨论】:

        猜你喜欢
        • 2016-07-29
        • 1970-01-01
        • 1970-01-01
        • 2020-08-11
        • 1970-01-01
        • 2021-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多