7

Rを使用したデータ分析は初めてです。最近、事前にフォーマットされた環境観測モデルデータセットを取得しました。そのサブセットの例を以下に示します。

date                   site      obs    mod      site           obs    mod
2000-09-01 00:00:00    campus    NA     61.63    city centre    66     56.69
2000-09-01 01:00:00    campus    52     62.55    city centre    NA     54.75
2000-09-01 02:00:00    campus    52     63.52    city centre    56     54.65

基本的に、データには、「繰り返し発生する列」のさまざまなサイト、つまりサイト-obs-modでの汚染物質の1時間ごとの観測およびモデル化された濃度の時系列が含まれます(この例では、合計75サイトのうち2つのみを示しました)。この「幅の広い」データセットをデータフレームとして読み込み、次のように「より狭い」形式に再形成したいと思いました。

date                   site           obs    mod
2000-09-01 00:00:00    campus         NA     61.63
2000-09-01 01:00:00    campus         52     62.55
2000-09-01 02:00:00    campus         52     63.52
2000-09-01 00:00:00    city centre    66     56.69
2000-09-01 01:00:00    city centre    NA     54.75
2000-09-01 02:00:00    city centre    56     54.65

これを行うには、パッケージ「reshape2」を使用する必要があると思いました。最初に、データセットを溶かしてからdcastしようとしました。

test.melt <- melt(test.data, id.vars = "date", measure.vars = c("site", "obs", "mod"))

ただし、データの半分しか返されませんでした。つまり、最初のサイト(「キャンパス」)に続くサイト(「市内中心部」)のレコードはすべて切り取られました。

date                   variable    value
2001-01-01 00:00:00    site        campus
2001-01-01 01:00:00    site        campus
2001-01-01 02:00:00    site        campus
2001-01-01 00:00:00    obs         NA
2001-01-01 01:00:00    obs         52
2001-01-01 02:00:00    obs         52
2001-01-01 00:00:00    mod         61.63
2001-01-01 01:00:00    mod         62.55
2001-01-01 02:00:00    mod         63.52

次に、リキャストを試しました。

test.recast <- recast(test.data, date ~ site + obs + mod)

ただし、次のエラーメッセージが返されました。

Error in eval(expr, envir, enclos) : object 'site' not found

以前の質問を検索しようとしましたが、同様のシナリオは見つかりませんでした(間違っている場合は修正してください)。誰かがこれを手伝ってくれませんか?

よろしくお願いします!

4

2 に答える 2

11

変数名のクリーンアップを行った後、ベースRの形状変更を使用した方がよい場合があります。

これがあなたのデータです。

test <- read.table(header = TRUE, stringsAsFactors=FALSE,
text = "date             site  obs    mod    site             obs    mod
'2000-09-01 00:00:00'  campus   NA  61.63    'city centre'    66     56.69
'2000-09-01 01:00:00'  campus   52  62.55    'city centre'    NA     54.75
'2000-09-01 02:00:00'  campus   52  63.52    'city centre'    56     54.65")
test
#                  date   site obs   mod      site.1 obs.1 mod.1
# 1 2000-09-01 00:00:00 campus  NA 61.63 city centre    66 56.69
# 2 2000-09-01 01:00:00 campus  52 62.55 city centre    NA 54.75
# 3 2000-09-01 02:00:00 campus  52 63.52 city centre    56 54.65

これを正しく行うと、私が得たような名前を取得する必要があります。@ chaseが彼の回答で述べているように、「繰り返しの列名は少し奇妙で、通常のRの動作ではありません」-したがって、これを修正する必要があります。

注:これらのオプションは両方とも、先に進んでドロップできる「時間」変数を生成します。ワイドフォーマットに戻したい場合に備えて、そのままにしておくことをお勧めします。

  • オプション1:私が行ったような名前(持っているはずです)を取得した場合、解決策は簡単です。最初のサイトでは、サイト名に「0」を追加し、ベースRの形状変更を使用します。

    names(test)[2:4] <- paste(names(test)[2:4], "0", sep=".")
    test <- reshape(test, direction = "long", 
                    idvar = "date", varying = 2:ncol(test))
    rownames(test) <- NULL # reshape makes UGLY rownames
    test
    #                  date time        site obs   mod
    # 1 2000-09-01 00:00:00    0      campus  NA 61.63
    # 2 2000-09-01 01:00:00    0      campus  52 62.55
    # 3 2000-09-01 02:00:00    0      campus  52 63.52
    # 4 2000-09-01 00:00:00    1 city centre  66 56.69
    # 5 2000-09-01 01:00:00    1 city centre  NA 54.75
    # 6 2000-09-01 02:00:00    1 city centre  56 54.65
    
  • オプション2:実際に列名が重複している場合でも、修正は簡単で、同じロジックに従います。まず、より適切な列名を作成し(を使用して簡単に実行できますrep())、reshape()次に上記のように使用します。

    names(test)[-1] <- paste(names(test)[-1], 
                             rep(1:((ncol(test)-1)/3), each = 3), sep = ".")
    test <- reshape(test, direction = "long", 
                    idvar = "date", varying = 2:ncol(test))
    rownames(test) <- NULL
    
    ### Or, more convenient:
    # names(test) <- make.unique(names(test))
    # names(test)[2:4] <- paste(names(test)[2:4], "0", sep=".")
    # test <- reshape(test, direction = "long", 
    #                 idvar = "date", varying = 2:ncol(test))
    # rownames(test) <- NULL
    
  • オプションの手順:この形式のデータは、まだ完全に「長い」わけではありません。それが必要な場合、必要なのはもう1つのステップです。

    require(reshape2)
    melt(test, id.vars = c("date", "site", "time"))
    #                   date        site time variable value
    # 1  2000-09-01 00:00:00      campus    0      obs    NA
    # 2  2000-09-01 01:00:00      campus    0      obs 52.00
    # 3  2000-09-01 02:00:00      campus    0      obs 52.00
    # 4  2000-09-01 00:00:00 city centre    1      obs 66.00
    # 5  2000-09-01 01:00:00 city centre    1      obs    NA
    # 6  2000-09-01 02:00:00 city centre    1      obs 56.00
    # 7  2000-09-01 00:00:00      campus    0      mod 61.63
    # 8  2000-09-01 01:00:00      campus    0      mod 62.55
    # 9  2000-09-01 02:00:00      campus    0      mod 63.52
    # 10 2000-09-01 00:00:00 city centre    1      mod 56.69
    # 11 2000-09-01 01:00:00 city centre    1      mod 54.75
    # 12 2000-09-01 02:00:00 city centre    1      mod 54.65
    

更新(コメントからいくつかの質問に対処しようとするため)

  1. reshape()ドキュメントは非常に紛らわしいです。それがどのように機能するかを理解するために、いくつかの例を実行するのが最善です。具体的には、「時間」は時間(問題の「日付」)を指す必要はありませんが、たとえば、同じIDの異なる時間にレコードが収集されるパネルデータの場合です。あなたの場合、元のデータの唯一の「id」は「date」列です。他の潜在的な「id」はサイトですが、データの編成方法ではありません。

    データが次のようになっていると想像してみてください。

    test1 <- structure(list(date = structure(1:3, 
        .Label = c("2000-09-01 00:00:00", 
        "2000-09-01 01:00:00", "2000-09-01 02:00:00"), class = "factor"), 
        obs.campus = c(NA, 52L, 52L), mod.campus = c(61.63, 62.55, 
        63.52), obs.cityCentre = c(66L, NA, 56L), mod.cityCentre = c(56.69, 
        54.75, 54.65)), .Names = c("date", "obs.campus", "mod.campus", 
    "obs.cityCentre", "mod.cityCentre"), class = "data.frame", row.names = c(NA, 
    -3L))
    test1
    #                  date obs.campus mod.campus obs.cityCentre mod.cityCentre
    # 1 2000-09-01 00:00:00         NA      61.63             66          56.69
    # 2 2000-09-01 01:00:00         52      62.55             NA          54.75
    # 3 2000-09-01 02:00:00         52      63.52             56          54.65
    

    今試してみてくださいreshape(test1, direction = "long", idvar = "date", varying = 2:ncol(test1))。サイト名が「時間」として表示されることがわかります(コマンドに「 」をreshape()追加することでオーバーライドできます)。timevar = "site"reshape

    の場合direction = "long"、「時間」によって変化する列を指定する必要があります。あなたの場合、それは最初の列を除くすべての列であるため、2:ncol(test)varying」を使用します。

  2. test2?それはどこですか?

  3. @Chaseの回答の下での質問:あなたはどのように機能するのか誤解していると思いますmelt()。基本的に、それはあなたにあなたのデータの「最も細い」形を取得しようとします。dateこの場合、 +siteは一意のID変数を構成するために必要な最小値であるため、最も細い形式は上記の「オプションのステップ」になります。(「time」は安全に落とすことができます。)

    データが「オプションの手順」で説明されている形式になったら(出力は「test.melt」として保存されていると想定します。テーブルをさまざまな方法で簡単に回転させることができます。これが意味することのデモンストレーションとして、以下を試して、それらが何をするかを確認してください。

    dcast(test.melt, date + site ~ variable)
    dcast(test.melt, date ~ variable + site)
    dcast(test.melt, variable + site ~ date)
    dcast(test.melt, variable + date ~ site)
    

    「オプション1」または「オプション2」で停止する場合、その柔軟性を得るのは簡単ではありません。


更新(数年後)

meltfrom "data.table"は、同様の方法で複数の列を「メルト」できるようになりましたreshape。列名が重複しているかどうかに関係なく機能するはずです。

次のことを試すことができます。

measure <- c("site", "obs", "mod")
melt(as.data.table(test), measure.vars = patterns(measure), value.name = measure)
#                   date variable        site obs   mod
# 1: 2000-09-01 00:00:00        1      campus  NA 61.63
# 2: 2000-09-01 01:00:00        1      campus  52 62.55
# 3: 2000-09-01 02:00:00        1      campus  52 63.52
# 4: 2000-09-01 00:00:00        2 city centre  66 56.69
# 5: 2000-09-01 01:00:00        2 city centre  NA 54.75
# 6: 2000-09-01 02:00:00        2 city centre  56 54.65
于 2012-09-27T14:05:08.957 に答える
7

繰り返し列名があるという事実は少し奇妙であり、通常の R の動作ではありません。ほとんどの場合、R は関数を介して有効な名前を持つことを強制しますmake.names()。とにかく、私はあなたの問題を再現することができます。あなたの例は再現できないため、私は自分の例を作成しましたが、ロジックは同じです。

#Do not force unique names
s <- data.frame(id = 1:3, x = runif(3), x = runif(3), check.names = FALSE)
#-----
  id         x         x
1  1 0.6845270 0.5218344
2  2 0.7662200 0.6179444
3  3 0.4110043 0.1104774

#Now try to melt, note that 1/2 of your x-values are missing!
melt(s, id.vars = 1)
#-----
  id variable     value
1  1        x 0.6845270
2  2        x 0.7662200
3  3        x 0.4110043

解決策は、列名を一意にすることです。前に述べたように、R はほとんどの場合、デフォルトでこれを行います。ただし、事後にそれを行うことができますmake.unique()

names(s) <- make.unique(names(s))
#-----
[1] "id"  "x"   "x.1"

x の 2 列目に 1 が追加されていることに注意してください。melt()期待どおりに動作するようになりました:

melt(s, id.vars = 1)
#-----
  id variable     value
1  1        x 0.6845270
2  2        x 0.7662200
3  3        x 0.4110043
4  1      x.1 0.5218344
5  2      x.1 0.6179444
6  3      x.1 0.1104774

xこの時点で、とを同じ変数として扱いたい場合は、問題のある文字を取り除くためにx.1少しまたは他の正規表現関数を使用すると思います。gsub()これは私が頻繁に使用するワークフローです。

于 2012-09-27T13:19:38.047 に答える