[英]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)
在這種情況下, reshape2
和tidyr
看起來很相似(盡管如果您正在尋找長格式的數據框, 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.