簡體   English   中英

如何用 tidyr 替換數組的 reshape2::melt?

[英]How to replace reshape2::melt for an array with tidyr?

我想將矩陣/數組(帶有dimnames)轉換為數據框。 這可以很容易用做reshape2::melt但似乎更難tidyr ,而事實上不是真的有可能在陣的情況。 我錯過了什么嗎? (特別是因為reshape2將自己描述為已退休;請參閱https://github.com/hadley/reshape )。

例如,給定以下矩陣

MyScores <- matrix(runif(2*3), nrow = 2, ncol = 3, 
                   dimnames = list(Month = month.name[1:2], Class = LETTERS[1:3]))

我們可以把它變成一個數據框,如下所示

reshape2::melt(MyScores, value.name = 'Score') # perfect

或者,使用tidyr如下:

as_tibble(MyScores, rownames = 'Month') %>% 
  gather(Class, Score, -Month)

在這種情況下, reshape2tidyr看起來很相似(盡管如果您正在尋找長格式的數據框, reshape2會更短)。

但是對於數組,似乎更難。 給定的

EverybodyScores <- array(runif(2*3*5), dim = c(2,3,5), 
                         dimnames = list(Month = month.name[1:2], Class = LETTERS[1:3], StudentID = 1:5))

我們可以將其轉換為數據框,如下所示:

reshape2::melt(EverybodyScores, value.name = 'Score') # perfect

但使用tidyr不清楚如何做到這一點:

as_tibble(EverybodyScores, rownames = 'Month') # looses month information and need to distange Class and StudentID

在這種情況下,正確的解決方案是堅持使用reshape2嗎?

我剛剛通過玩耍發現的一種方法是通過tbl_cube進行強制。 我從來沒有真正使用過這個類,但在這種情況下它似乎可以解決問題。

EverybodyScores <- array(
  runif(2 * 3 * 5),
  dim = c(2, 3, 5),
  dimnames = list(Month = month.name[1:2], Class = LETTERS[1:3], StudentID = 1:5)
)
library(tidyverse)
library(cubelyr)
EverybodyScores %>%
  as.tbl_cube(met_name = "Score") %>%
  as_tibble
#> # A tibble: 30 x 4
#>    Month    Class StudentID Score
#>    <chr>    <chr>     <int> <dbl>
#>  1 January  A             1 0.366
#>  2 February A             1 0.254
#>  3 January  B             1 0.441
#>  4 February B             1 0.562
#>  5 January  C             1 0.313
#>  6 February C             1 0.192
#>  7 January  A             2 0.799
#>  8 February A             2 0.277
#>  9 January  B             2 0.631
#> 10 February B             2 0.101
#> # ... with 20 more rows

reprex 包(v0.2.0) 於 2018 年 8 月 15 日創建。

制作 tibble 會刪除行名稱,但不是直接進入 tibble,您可以將數組制作為基本 R data.frame ,然后使用tidyr::rownames_to_column制作一列數月。 請注意,轉換為數據框會創建名稱類似於A.1列,將類和 ID 粘在一起; 您可以使用tidyr::separate再次將它們tidyr::separate 調用as_tibble是可選的,只是因為您是否關心它最終是一個tibble ,並且一旦您從行名稱中創建了一個列,也可以在工作流程中的任何點調用。

library(tidyverse)

EverybodyScores <- array(runif(2*3*5), dim = c(2,3,5), 
                         dimnames = list(Month = month.name[1:2], Class = LETTERS[1:3], StudentID = 1:5))

EverybodyScores %>%
  as.data.frame() %>%
  rownames_to_column("Month") %>%
  gather(key = class_id, value = value, -Month) %>%
  separate(class_id, into = c("Class", "StudentID"), sep = "\\.") %>%
  as_tibble()
#> # A tibble: 30 x 4
#>    Month    Class StudentID value
#>    <chr>    <chr> <chr>     <dbl>
#>  1 January  A     1         0.576
#>  2 February A     1         0.229
#>  3 January  B     1         0.930
#>  4 February B     1         0.547
#>  5 January  C     1         0.761
#>  6 February C     1         0.468
#>  7 January  A     2         0.631
#>  8 February A     2         0.893
#>  9 January  B     2         0.638
#> 10 February B     2         0.735
#> # ... with 20 more rows

reprex 包(v0.2.0) 於 2018 年 8 月 15 日創建。

這是執行相同操作的新tidyr方法:

library(tidyr)

EverybodyScores <- array(
  runif(2 * 3 * 5),
  dim = c(2, 3, 5),
  dimnames = list(Month = month.name[1:2], Class = LETTERS[1:3], StudentID = 1:5)
)

as_tibble(EverybodyScores, rownames = "Month") %>%
  pivot_longer(
    cols = matches("^A|^B|^C"),
    names_sep = "\\.",
    names_to = c("Class", "StudentID")
  )
#> # A tibble: 30 x 4
#>    Month   Class StudentID  value
#>    <chr>   <chr> <chr>      <dbl>
#>  1 January A     1         0.0325
#>  2 January B     1         0.959 
#>  3 January C     1         0.593 
#>  4 January A     2         0.0702
#>  5 January B     2         0.882 
#>  6 January C     2         0.918 
#>  7 January A     3         0.459 
#>  8 January B     3         0.849 
#>  9 January C     3         0.901 
#> 10 January A     4         0.328 
#> # … with 20 more rows

reprex 包(v1.0.0) 於2021年 2 月 23 日創建

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM