2016-11-14 3 views
1

Ich habe ein Array und ich möchte es basierend auf den Dimnamen schmelzen. Das Problem ist, dass die Bemaßungsnamen große numerische Werte sind und daher machen sie Charakter, sie zu einer falschen ID siehe das Beispiel umwandeln würde:Schmelzen Sie ein Array und machen numerische Werte Zeichen

test <- array(1:18, dim = c(3,3,2), dimnames = list(c(00901291282245454545454,329293929929292,2929992929922929), 
                c("a", "b", "c"), 
                c("d", "e"))) 

library(reshape2) 
library(data.table) 
test2 <- data.table(melt(test)) 
test2[, Var1 := as.character(Var1)] 

> test2 
Var1 Var2 Var3 value 
1: 9.01291282245455e+20 a d  1 
2:  329293929929292 a d  2 
3:  2929992929922929 a d  3 
4: 9.01291282245455e+20 b d  4 
5:  329293929929292 b d  5 
6:  2929992929922929 b d  6 
7: 9.01291282245455e+20 c d  7 
8:  329293929929292 c d  8 
9:  2929992929922929 c d  9 
10: 9.01291282245455e+20 a e 10 
11:  329293929929292 a e 11 
12:  2929992929922929 a e 12 
13: 9.01291282245455e+20 b e 13 
14:  329293929929292 b e 14 
15:  2929992929922929 b e 15 
16: 9.01291282245455e+20 c e 16 
17:  329293929929292 c e 17 
18:  2929992929922929 c e 18 

Wie kann ich mit dem großen IDs Charakter mache die erste Spalte? Was ich gerade mache ist, einen Buchstaben in die Dimnamen einzufügen und dann zu schmelzen, um daraus ein Zeichen zu machen und dann einen Teilstring zu nehmen, was wirklich ineffizient ist. Es ist wichtig, dass es eine effiziente Lösung ist, da der Datensatz Millionen von Zeilen umfasst. Es gibt zwei Probleme, zuerst werden die Nullen gelöscht, wenn sie sich vor der ID befinden, und sie werden in ein e + 20 Zeichen umgewandelt.

+1

Optionen (scipen = 99) löst das e + 20 Problem –

+0

die 0 am Start wird abreißen, wenn es eine numerische Spalte ist. Ich denke nicht, dass wir es vermeiden können. Wenn Sie Daten aus CSV-Dateien usw. importieren, geben Sie diese Spalte selbst als Zeichen an, um dieses Problem zu vermeiden –

Antwort

1

Sie benötigen dimnames als character zu definieren und dann melt.array slighly ändern, die aufgerufen wird, wenn Sie melt auf array tun:

test <- array(1:18, dim = c(3,3,2), dimnames = list(c("00901291282245454545454", "329293929929292", "2929992929922929"), 
                c("a", "b", "c"), 
                c("d", "e"))) 

anpassen melt.array einen Parameter hinzuzufügen, die entscheiden erlaubt, ob Sie die Konvertierung wollen oder nicht:

melt.array2 <- function (data, varnames = names(dimnames(data)), conv=TRUE, ...) 
{ 
    values <- as.vector(data) 
    dn <- dimnames(data) 
    if (is.null(dn)) 
     dn <- vector("list", length(dim(data))) 
    dn_missing <- sapply(dn, is.null) 
    dn[dn_missing] <- lapply(dim(data), function(x) 1:x)[dn_missing] 
    if(conv){ # conv is the new parameter to know if conversion needs to be done 
     char <- sapply(dn, is.character) 
     dn[char] <- lapply(dn[char], type.convert) 
    } 
    indices <- do.call(expand.grid, dn) 
    names(indices) <- varnames 
    data.frame(indices, value = values) 
} 

Probieren Sie die neue Funktion auf Ihrem Beispiel (mit conv=FALSE):

head(melt.array2(test, conv=FALSE)) 
         # X1 X2 X3 value 
# 1 00901291282245454545454 a d  1 
# 2   329293929929292 a d  2 
# 3   2929992929922929 a d  3 
# 4 00901291282245454545454 b d  4 
# 5   329293929929292 b d  5 
# 6   2929992929922929 b d  6 

EDIT

In der Entwicklungsversion von reshape2 (devtools::install_github("hadley/reshape") wird melt.array anders definiert und Sie Parameter as.is die Konvertierung zu vermeiden verwenden:

melt(test, as.is=TRUE) 

geben Sie das gleiche Ergebnis wie oben (mit Var1 usw. anstelle von X1 usw.).

Verwandte Themen