2013-07-25 5 views
5

Unten ist ein Ausschnitt aus der Ausgabe einer Beispielsitzung. Darin erstelle ich eine Matrix mit der matrix() Funktion und wandle sie einfach in einen Datenrahmen mit der as.data.frame() Funktion um. Im zweiten Abschnitt erstelle ich auch eine Matrix, aber durch einen anderen Prozess (den ich machen möchte), aber obwohl str() mir analoge Ausgabe gibt, erhalte ich einen Fehler bei der Konvertierung in einen Datenrahmen. Irgendwelche Ideen?Umwandeln von Matrix in Datenrahmen: Funktioniert in einem Fall, nicht in einem anderen

EDIT: Am Ende habe ich eine Zeile hinzugefügt, wo ich (re) die Matrix zu einer Matrix umwandeln und dann diese in einen Datenrahmen konvertieren. Es funktioniert, aber ich sollte nicht nach dem, was ich sehe in der str() Ausgabe der test_mx, die nicht als ein Datenrahmen umgewandelt werden kann. Ich weiß, wie ich das beheben kann, aber ich verstehe nicht, warum ich diesen zusätzlichen Schritt tun muss.

R version 2.15.2 (2012-10-26) -- "Trick or Treat" 

> library(reshape) 
> ## This works 
> ## ========== 
> tmx = matrix(1:12*0.1, ncol=4) 
> rownames(tmx) = c("A", "B", "C") 
> colnames(tmx) = 0:3 
> tmx 
    0 1 2 3 
A 0.1 0.4 0.7 1.0 
B 0.2 0.5 0.8 1.1 
C 0.3 0.6 0.9 1.2 
> 
> str(tmx) 
num [1:3, 1:4] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 ... 
- attr(*, "dimnames")=List of 2 
    ..$ : chr [1:3] "A" "B" "C" 
    ..$ : chr [1:4] "0" "1" "2" "3" 
> as.data.frame(tmx) 
    0 1 2 3 
A 0.1 0.4 0.7 1.0 
B 0.2 0.5 0.8 1.1 
C 0.3 0.6 0.9 1.2 
> 
> 
> 
> ## This does not 
> ## ============= 
> t = 0:3 
> thesd = 0.1 
> dat = data.frame(
+  a1 = sin(2*pi*t/length(t)) + rnorm(t, sd=thesd), 
+  b1 = sin(2*pi*t/length(t) - pi) + rnorm(t, sd=thesd), 
+  c1 = sin(2*pi*t/length(t) - pi/2) + rnorm(t, sd=thesd), 
+  t = t 
+) 
> 
> test_mx = cast(melt(dat, id.vars="t"), variable ~ t) 
> tmp_rownames = as.character(test_mx[,1]) 
> test_mx = test_mx[,-1] 
> tmp_colnames = colnames(test_mx) 
> test_mx = as.matrix(test_mx) 
> rownames(test_mx) = tmp_rownames 
> colnames(test_mx) = tmp_colnames 
> 
> str(test_mx) 
num [1:3, 1:4] 0.06211 -0.00596 -1.09718 1.1555 -0.96443 ... 
- attr(*, "dimnames")=List of 2 
    ..$ : chr [1:3] "a1" "b1" "c1" 
    ..$ : chr [1:4] "0" "1" "2" "3" 
> as.data.frame(test_mx) 
Error in data.frame(rrownames(x), unx, check.names = FALSE) : 
    arguments imply differing number of rows: 0, 3 
> 
> ## But this does work 
> as.data.frame(as.matrix(test_mx)) 
      0   1   2   3 
a1 -0.16166693 0.97479282 0.01471777 -1.01517539 
b1 -0.01012797 -0.97745698 -0.12667287 0.96542412 
c1 -1.07217297 0.06783235 1.12068282 -0.02012263 

> ## why? 
+0

Zur Anmerkung des Redakteurs: Ich habe 'test_mx = cast (schmelze (dat, id.vars =" t "), Variable ~ t)', die, wo ich lief, die Umform benötigt 'Paket. Ohne es, bekomme ich 'Fehler: konnte die Funktion" cast "' nicht finden. – mpettis

+0

Schauen Sie sich die 'class'es und verwandte' Methoden' an, wie ich [in dieser Antwort] (http://stackoverflow.com/a/17873683/1270695) beschrieben habe. – A5C1D2H2I1M1N2O1R2T1

+0

Auch in Zukunft, bitte schneiden Sie diese lästigen '>' und '+' Symbole aus Ihrem Code, die es schwierig machen, Ihren Code zu kopieren und einzufügen, um es zu testen! – A5C1D2H2I1M1N2O1R2T1

Antwort

5

sollten Sie reshape2 verwenden, nicht reshape, da diese veraltet ist.

Ändern Sie auch cast von dcast oder acast.

as.data.frame(test_mx) 
      0   1   2   3 
1 -0.08120468 0.97593052 -0.006127179 -1.15107784 
2 -0.04165681 -1.02810193 0.004637454 0.99042403 
3 -0.87862063 0.07346341 1.019113669 -0.01769976 
+0

Danke! Das hat nicht nur die Umwandlung in einen Datenrahmen gelöst, sondern ich musste auch nicht durch die Machenschaften gehen, um die Zeilen- und Spaltennamen richtig zu machen. Ich habe hier ein vollständiges Lösungsbeispiel geschrieben: http://pastebin.com/B2uEPy8M. Wären Sie bereit, dies als Ihren Lösungscode zu verwenden, nur um ein vollständig wiederherstellbares Beispiel zu haben? – mpettis

11

Während @ agstudy Antwort Ihr Problem löst und bringt Sie mit den neuesten Pakete auf den neuesten Stand, es geht nicht, zu versuchen, zu verstehen, warum dies geschieht.

Um zu verstehen, warum, Schritt zurück zu Ihrer Linie test_mx = cast(melt(dat, id.vars="t"), variable ~ t). Ich werde hier zwei Objekte erstellen, damit wir einige Vergleiche durchführen können:

test_mx <- test_mx_cast <- cast(melt(dat, id.vars="t"), variable ~ t) 
class(test_mx) 
# [1] "cast_df" "data.frame" 
class(test_mx_cast) 
# [1] "cast_df" "data.frame" 

Hmm. Was ist das cast_df Klasse? Es stellt sich heraus, dass die "Umgestalten" -Methode mehrere neue Methoden definiert hat. Siehe zum Beispiel methods(as.data.frame) oder methods(as.matrix):

> methods(as.matrix) 
[1] as.matrix.cast_df  as.matrix.cast_matrix as.matrix.data.frame as.matrix.default  
[5] as.matrix.dist*  as.matrix.noquote  as.matrix.POSIXlt  as.matrix.raster*  

    Non-visible functions are asterisked 
> methods(as.data.frame) 
[1] as.data.frame.aovproj*  as.data.frame.array   as.data.frame.AsIs   
[4] as.data.frame.cast_df   as.data.frame.cast_matrix  as.data.frame.character  
[7] as.data.frame.complex   as.data.frame.data.frame  as.data.frame.Date   
[10] as.data.frame.default   as.data.frame.difftime  as.data.frame.factor   
[13] as.data.frame.ftable*   as.data.frame.function*  as.data.frame.idf*   
[16] as.data.frame.integer   as.data.frame.list   as.data.frame.logical   
[19] as.data.frame.logLik*   as.data.frame.matrix   as.data.frame.model.matrix 
[22] as.data.frame.numeric   as.data.frame.numeric_version as.data.frame.ordered   
[25] as.data.frame.POSIXct   as.data.frame.POSIXlt   as.data.frame.raw    
[28] as.data.frame.table   as.data.frame.ts    as.data.frame.vector   

    Non-visible functions are asterisked 

Hinweis oben ^^ das erste und zweites Verfahren für as.matrix und vierte und fünfte Verfahren zum as.data.frame.

Was bedeutet das? Nun, Sie gingen und schrieben mehrere Zeilen, nachdem Sie test_mx erstellt haben, um Ihre data.frame in eine matrix zu konvertieren. Das lag hauptsächlich daran, dass Sie sicherstellen wollten, dass Ihre erste Spalte als rownames endete und Ihre gesamte Matrix nicht zu einer Zeichenmatrix zwang.

tmp_rownames = as.character(test_mx[,1]) 
test_mx = test_mx[,-1] 
tmp_colnames = colnames(test_mx) 
test_mx = as.matrix(test_mx) 
rownames(test_mx) = tmp_rownames 
colnames(test_mx) = tmp_colnames 
test_mx 
#    0   1   2   3 
# a1 -0.079811371 0.82820704 -0.193860367 -1.1269632 
# b1 -0.009402418 -1.19348155 -0.004519269 0.8921427 
# c1 -0.784163111 -0.01340952 0.966208235 0.0135557 

Denn „umformen“ hat bereits eine angepasste as.matrix Methode definiert ist, haben Sie nicht wirklich brauchen, das zu tun!

as.matrix(test_mx_cast) 
#    0   1   2   3 
# a1 -0.079811371 0.82820704 -0.193860367 -1.1269632 
# b1 -0.009402418 -1.19348155 -0.004519269 0.8921427 
# c1 -0.784163111 -0.01340952 0.966208235 0.0135557 

Aber das beantwortet immer noch nicht alles. Um weiter zu verstehen, vergleichen Sie die beiden Matrizen jetzt:

> test_mx_cast_matrix <- as.matrix(test_mx_cast) 
> class(test_mx) 
[1] "cast_matrix" "matrix"  
> class(test_mx_cast_matrix) 
[1] "cast_matrix" "matrix"  
> str(test_mx) 
num [1:3, 1:4] -0.0798 -0.0094 -0.7842 0.8282 -1.1935 ... 
- attr(*, "dimnames")=List of 2 
    ..$ : chr [1:3] "a1" "b1" "c1" 
    ..$ : chr [1:4] "0" "1" "2" "3" 
> str(test_mx_cast_matrix) 
num [1:3, 1:4] -0.0798 -0.0094 -0.7842 0.8282 -1.1935 ... 
- attr(*, "dimnames")=List of 2 
    ..$ : chr [1:3] "a1" "b1" "c1" 
    ..$ : chr [1:4] "0" "1" "2" "3" 
- attr(*, "idvars")= chr "variable" 
- attr(*, "rdimnames")=List of 2 
    ..$ :'data.frame': 3 obs. of 1 variable: 
    .. ..$ variable: Factor w/ 3 levels "a1","b1","c1": 1 2 3 
    ..$ :'data.frame': 4 obs. of 1 variable: 
    .. ..$ t: int [1:4] 0 1 2 3 

Hmmm. Wenn wir as.matrix direkt verwenden, werden alle attributes, die das "reshape" -Paket hinzufügt, behalten, aber wenn wir den Prozess manuell machen, behauptet er immer noch, derselbe zu sein class, aber alle benutzerdefinierten attributes wurden entfernt.

Also was?

Nun, da R denkt, dass test_mx ein cast_matrix ist, wenn Sie as.data.frame nennen, ruft sie eigentlich as.data.frame.cast_matrix, nicht as.data.frame.matrix.

Betrachtet man, wie as.data.frame.cast_matrix definiert ist, diejenigen attributes sind wesentliche erstellen Sie Ihre data.frame, damit Ihre Fehler. Hier sind die Eingeweide der Funktion:

> as.data.frame.cast_matrix 
function (x, row.names, optional, ...) 
{ 
    unx <- unclass(x) 
    colnames(unx) <- rownames(rcolnames(x)) 
    r.df <- data.frame(rrownames(x), unx, check.names = FALSE) 
    class(r.df) <- c("cast_df", "data.frame") 
    attr(r.df, "idvars") <- attr(x, "idvars") 
    attr(r.df, "rdimnames") <- attr(x, "rdimnames") 
    rownames(r.df) <- 1:nrow(r.df) 
    r.df 
} 
<environment: namespace:reshape> 

Also, Sie haben jetzt drei Möglichkeiten:

  1. Upgrade auf „reshape2“ - Guter Rat, aber denken Sie daran, dass es immer noch eine gute Anzahl der Personen, die sich nicht um den Wechsel gekümmert haben.

  2. Use „umformen“ richtig, die ein bisschen mehr an der str erfordert suchen, class es und attributes der Objekte, die es schafft. Verwenden Sie es "richtig" hier gewesen wäre, as.data.frame(test_mx_cast_matrix) zu verwenden. Geben Sie die an, die Sie verwenden möchten (was ziemlich sicher ist, wenn Sie nicht wissen, ob Pakete neu definierte Methoden verwenden). Wenn neue Klassen erstellt werden, sollten Sie auch überprüfen, ob neue Methoden erstellt wurden). Vergleichen:

    > as.data.frame(test_mx)  ## Calls `as.data.frame.cast_matrix` ERROR! 
    Error in data.frame(rrownames(x), unx, check.names = FALSE) : 
        arguments imply differing number of rows: 0, 3 
    > as.data.frame.matrix(test_mx) ## Specifies the `as.data.frame` method. WORKS! 
           0   1   2   3 
    a1 -0.079811371 0.82820704 -0.193860367 -1.1269632 
    b1 -0.009402418 -1.19348155 -0.004519269 0.8921427 
    c1 -0.784163111 -0.01340952 0.966208235 0.0135557 
    

Sigh. Das Ende ....

+0

Haben Sie +1 für die Mühe. Das entspricht '1.3e-3' Stimmen für jedes Wort in Ihrer Antwort. – thelatemail

+0

@thelatemail, besser als eine 0 für jedes Wort! – A5C1D2H2I1M1N2O1R2T1

+0

Danke für die gründliche Antwort! Es scheint so, als wäre "richtiges Umformen" ein bisschen schwierig - wo lernst du etwas über die Konventionen der einfachsten Art, die Konversationen zu machen, anstatt eine Lösung zu hacken, wie ich es getan habe? – mpettis

Verwandte Themen