web-dev-qa-db-ja.com

データフレームをピボット/ピボット解除(キャスト/メルト)する方法

テーブルを「アンピボット」するにはどうすればよいですか?これの適切な専門用語は何ですか?

更新:この用語はmeltと呼ばれます

国ごとのデータフレームと毎年のデータがあります

Country     2001    2002    2003
Nigeria     1       2       3
UK          2       NA       1

そして、私は何かをしたいです

Country    Year    Value
Nigeria    2001    1
Nigeria    2002    2
Nigeria    2003    3
UK         2001    2
UK         2002    NA
UK         2003    1
22
pedrosaurio

私はまだ答えでアンドリーを倒したとは信じられない。 :)

> library(reshape)
> my.df <- read.table(text = "Country     2001    2002    2003
   + Nigeria     1       2       3
   + UK          2       NA       1", header = TRUE)
> my.result <- melt(my.df, id = c("Country"))
> my.result[order(my.result$Country),]
     Country variable value
   1 Nigeria    X2001     1
   3 Nigeria    X2002     2
   5 Nigeria    X2003     3
   2      UK    X2001     2
   4      UK    X2002    NA
   6      UK    X2003     1
20
Roman Luštrik

この問題の基本的なR reshapeアプローチは、特に名前がreshapeが好きな形式ではないため、かなり醜いです。最初のsetNames行が列名をreshapeが利用できるものに変更する次のようなものになります。

reshape(
  setNames(mydf, c("Country", paste0("val.", c(2001, 2002, 2003)))), 
  direction = "long", idvar = "Country", varying = 2:ncol(mydf), 
  sep = ".", new.row.names = seq_len(prod(dim(mydf[-1]))))

ベースRのより良い代替案は、次のようにstackを使用することです。

cbind(mydf[1], stack(mydf[-1]))
#   Country values  ind
# 1 Nigeria      1 2001
# 2      UK      2 2001
# 3 Nigeria      2 2002
# 4      UK     NA 2002
# 5 Nigeria      3 2003
# 6      UK      1 2003

gatherを提供する「tidyr」パッケージなど、現在利用可能なデータを再形成するための新しいツールもあります。もちろん、tidyr:::gather_.data.frameメソッドはreshape2::meltを呼び出すだけなので、私の答えのこの部分は、Hadleyverseで遭遇する可能性がある新しい構文を紹介する以外は、必ずしも多くを追加するわけではありません。

library(tidyr)
gather(mydf, year, value, `2001`:`2003`) ## Note the backticks
#   Country year value
# 1 Nigeria 2001     1
# 2      UK 2001     2
# 3 Nigeria 2002     2
# 4      UK 2002    NA
# 5 Nigeria 2003     3
# 6      UK 2003     1

質問で示した行の順序が必要な場合は、ここでの3つのオプションすべてで行を並べ替える必要があります。


4番目のオプションは、「splitstackshape」パッケージのmerged.stackを使用することです。ベースRのreshapeと同様に、列名を「変数」および「時間」インジケーターを含むものに変更する必要があります。

library(splitstackshape)
merged.stack(
  setNames(mydf, c("Country", paste0("V.", 2001:2003))),
  var.stubs = "V", sep = ".")
#    Country .time_1  V
# 1: Nigeria    2001  1
# 2: Nigeria    2002  2
# 3: Nigeria    2003  3
# 4:      UK    2001  2
# 5:      UK    2002 NA
# 6:      UK    2003  1

サンプルデータ

 mydf <- structure(list(Country = c("Nigeria", "UK"), `2001` = 1:2, `2002` = c(2L, 
     NA), `2003` = c(3L, 1L)), .Names = c("Country", "2001", "2002",               
     "2003"), row.names = 1:2, class = "data.frame")   

meltパッケージのreshapeコマンドを使用できます。ここを参照してください: http://www.statmethods.net/management/reshape.html

おそらくmelt(myframe, id=c('Country'))のようなもの

1
nicolaskruchten