2016-05-03 19 views
1

Stellen Sie sich vor, ich habe ein Datenframe mit Spaltennamen wie Mary1, Mary2, Mary3, Bob1, Bob2, Bob3, Pam1, Pam2, Pam3 und so weiter, aber mit vielen mehr Spalten.R, data.table oder dplyr, Langformat Splitting Spaltennamen

Lassen Sie uns ein einfacher reproduzierbares Beispiel setzen.

set.seed(1) 
mydata <- data.frame() 
mydata <- rbind(mydata,c(1,round(runif(30),3))) 
mydata <- rbind(mydata,c(2,round(runif(30),3))) 
mydata <- rbind(mydata,c(3,round(runif(30),3))) 
colnames(mydata) <- c("id", paste0(rep(LETTERS[1:10], each=3), 1:3)) 

das gibt:

id A1 A2 A3 B1 B2 B3 C1 C2 C3 D1 D2 D3 E1 E2 E3 F1 F2 F3 G1 G2 G3 H1 H2 H3 I1 I2 I3 J1 J2 J3 ... 
1 0.266 0.372 0.573 0.908 0.202 0.898 0.945 0.661 0.629 0.062 0.206 0.177 0.687 0.384 0.770 0.498 0.718 0.992 0.380 0.777 0.935 0.212 0.652 0.126 0.267 0.386 0.013 0.382 0.870 0.340 ... 
2 0.482 0.600 0.494 0.186 0.827 0.668 0.794 0.108 0.724 0.411 0.821 0.647 0.783 0.553 0.530 0.789 0.023 0.477 0.732 0.693 0.478 0.861 0.438 0.245 0.071 0.099 0.316 0.519 0.662 0.407 ... 
3 0.913 0.294 0.459 0.332 0.651 0.258 0.479 0.766 0.084 0.875 0.339 0.839 0.347 0.334 0.476 0.892 0.864 0.390 0.777 0.961 0.435 0.713 0.400 0.325 0.757 0.203 0.711 0.122 0.245 0.143 ... 

Ich möchte eine lange Tabellenformat erhalten, wie folgt aus:

set.seed(1) 
mydata <- data.frame() 
mydata <- rbind(mydata,c(1,1,round(runif(10),3))) 
mydata <- rbind(mydata,c(1,2,round(runif(10),3))) 
mydata <- rbind(mydata,c(1,3,round(runif(10),3))) 
mydata <- rbind(mydata,c(2,1,round(runif(10),3))) 
mydata <- rbind(mydata,c(2,2,round(runif(10),3))) 
mydata <- rbind(mydata,c(2,3,round(runif(10),3))) 
colnames(mydata) <- c("id","N", LETTERS[1:10]) 

, das heißt:

id N  A  B  C  D  E  F  G  H  I  J 
    1 1 0.266 0.372 0.573 0.908 0.202 0.898 0.945 0.661 0.629 0.062 
    1 2 0.206 0.177 0.687 0.384 0.770 0.498 0.718 0.992 0.380 0.777 
    1 3 0.482 0.600 0.494 0.186 0.827 0.668 0.794 0.108 0.724 0.411 
    2 1 0.935 0.212 0.652 0.126 0.267 0.386 0.013 0.382 0.870 0.340 
    2 2 0.821 0.647 0.783 0.553 0.530 0.789 0.023 0.477 0.732 0.693 
    2 3 0.478 0.861 0.438 0.245 0.071 0.099 0.316 0.519 0.662 0.407 

Wie ich es bekommen kann mit data.table oder dplyr/tidyr? oder irgendeine andere einfache Option.

Wenn ich versuche,

melt(mydata, id=1) 

das Ergebnis ist eine einzelne Spalte.

Ich habe die offizielle Hilfe und die Vignetten überprüft, aber ich kann nur viel einfachere Beispiele finden, mit einer kleinen Anzahl von Spalten, gibt der Benutzer jeden von Hand, und ein einziges Beispiel für Muster(), aber ich kann Passen Sie es meinem Beispiel nicht an.

Andere Themen verwenden gsub, aber es ist verwirrend für mich.

Was ich wirklich tun möchte, ist ein bisschen komplizierter, aber ich denke, das ist der erste Schritt (ich werde es später erneut werfen). Stellen Sie sich vor, meine Spalten sind Mary1, Mary2, Bob1, Bob2, Pam1, Pam2 ... Ich möchte neue Spalten mit den Unterschieden der beiden oben genannten erstellen: Mary1-Mary2, Bob1-Bob2, Pam1-Pam2 ...

Zusammenfassen: Ich möchte nicht den Namen aller Spalten von Hand schreiben, sondern wähle automatisch die letzte Ziffer aus.

PD: OK, ich aktualisiere meine Frage. Es darf nicht nur für Namen arbeiten wie A1, A2 ... aber auch für längere Namen, wie

colnames(mydata) <- c("id", paste0(rep(LETTERS[1:10], each=3), rep(LETTERS[1:10], each=3), 1:3)) 

ich die Geschwindigkeit habe nichts dagegen, ich bin lookking für etwas einfach, nicht kryptisch.

+1

Ihr Problem scheint mehr und mehr über die Verwendung * regex * und le ss über die Umgestaltung. Ich würde vorschlagen, dass Sie lernen, Regex zu verwenden und basierend auf einer der folgenden Antworten zu entwickeln. – Arun

+1

Es lohnt sich die Zeit zu investieren, um einige reguläre Ausdrücke zu lernen.'gsub',' grep', 'grepl' und viele andere bieten eine großartige Möglichkeit, die Code-Größe zu reduzieren und Aufgaben auszuführen, die sonst unmöglich wären. Dies ist eine meiner Lieblings [Sites] (http://www.regular-expressions.info/). – lmo

+0

@Arun Ich stimme zu, aber schauen Sie sich rawr Lösung an, er verwendet keine komplexen Regex noch benötigt Uniques ... – skan

Antwort

3

Hier ist eine Lösung mit tidyr:

library(tidyr) 
mydata %>% 
    gather(key, value, -id) %>% 
    separate(key, into = c('key1', 'key2'), 
      sep = '(?<=[a-zA-Z])(?=[0-9])') %>% 
    spread(key1, value) 

resultierendem Ausgang:

id key2  A  B  C  D  E  F  G  H  I  J 
1 1 1 0.266 0.908 0.945 0.062 0.687 0.498 0.380 0.212 0.267 0.382 
2 1 2 0.372 0.202 0.661 0.206 0.384 0.718 0.777 0.652 0.386 0.870 
3 1 3 0.573 0.898 0.629 0.177 0.770 0.992 0.935 0.126 0.013 0.340 
4 2 1 0.482 0.186 0.794 0.411 0.783 0.789 0.732 0.861 0.071 0.519 
5 2 2 0.600 0.827 0.108 0.821 0.553 0.023 0.693 0.438 0.099 0.662 
6 2 3 0.494 0.668 0.724 0.647 0.530 0.477 0.478 0.245 0.316 0.407 
7 3 1 0.913 0.332 0.479 0.875 0.347 0.892 0.777 0.713 0.757 0.122 
8 3 2 0.294 0.651 0.766 0.339 0.334 0.864 0.961 0.400 0.203 0.245 
9 3 3 0.459 0.258 0.084 0.839 0.476 0.390 0.435 0.325 0.711 0.143 
+0

Sie haben es leicht gemacht, aber wenn ich es auf eigene Faust versuche, kombiniere ich viele Dinge und es funktioniert nur manchmal. Danke. – skan

+0

Aber es funktioniert nur für das einfache Beispiel, Spaltennamen mit einem einzigen Buchstaben + eine Zahl gemacht. Könnten Sie bitte für Spaltennamen wie Mary1, Mary2, Bob1, Bob2 ... erweitern? – skan

+1

Dies ist ineffizient, wie in meinem [UseR15] (http://user2015.math.aau.dk/presentations/93.pdf) Vortrag und Kreisverkehr gezeigt, wie in der [Umgestaltung Vignette] (https://github.com/ Rdatatable/data.table/wiki/Erste Schritte). – Arun

5

data.table::melt Verwendung:

require(data.table) 
n = unique(gsub("[0-9]+$", "", names(mydata)[-1L])) 
p = paste0("^", n) 

melt(setDT(mydata), measure=patterns(p), value.name=n, variable.name="N") 
# id N  A  B  C  D  E  F  G  H  I  J 
# 1: 1 1 0.266 0.908 0.945 0.062 0.687 0.498 0.380 0.212 0.267 0.382 
# 2: 2 1 0.482 0.186 0.794 0.411 0.783 0.789 0.732 0.861 0.071 0.519 
# 3: 3 1 0.913 0.332 0.479 0.875 0.347 0.892 0.777 0.713 0.757 0.122 
# 4: 1 2 0.372 0.202 0.661 0.206 0.384 0.718 0.777 0.652 0.386 0.870 
# 5: 2 2 0.600 0.827 0.108 0.821 0.553 0.023 0.693 0.438 0.099 0.662 
# 6: 3 2 0.294 0.651 0.766 0.339 0.334 0.864 0.961 0.400 0.203 0.245 
# 7: 1 3 0.573 0.898 0.629 0.177 0.770 0.992 0.935 0.126 0.013 0.340 
# 8: 2 3 0.494 0.668 0.724 0.647 0.530 0.477 0.478 0.245 0.316 0.407 
# 9: 3 3 0.459 0.258 0.084 0.839 0.476 0.390 0.435 0.325 0.711 0.143 
4
set.seed(1) 
mydata <- data.frame() 
mydata <- rbind(mydata,c(1,round(runif(30),3))) 
mydata <- rbind(mydata,c(2,round(runif(30),3))) 
mydata <- rbind(mydata,c(3,round(runif(30),3))) 
colnames(mydata) <- c("id", paste0(rep(LETTERS[1:10], each=3), 1:3)) 

reshape(mydata, dir = 'long', varying = names(mydata)[-1], sep = '', timevar = 'N') 

#  id N  A  B  C  D  E  F  G  H  I  J 
# 1.1 1 1 0.266 0.908 0.945 0.062 0.687 0.498 0.380 0.212 0.267 0.382 
# 2.1 2 1 0.482 0.186 0.794 0.411 0.783 0.789 0.732 0.861 0.071 0.519 
# 3.1 3 1 0.913 0.332 0.479 0.875 0.347 0.892 0.777 0.713 0.757 0.122 
# 1.2 1 2 0.372 0.202 0.661 0.206 0.384 0.718 0.777 0.652 0.386 0.870 
# 2.2 2 2 0.600 0.827 0.108 0.821 0.553 0.023 0.693 0.438 0.099 0.662 
# 3.2 3 2 0.294 0.651 0.766 0.339 0.334 0.864 0.961 0.400 0.203 0.245 
# 1.3 1 3 0.573 0.898 0.629 0.177 0.770 0.992 0.935 0.126 0.013 0.340 
# 2.3 2 3 0.494 0.668 0.724 0.647 0.530 0.477 0.478 0.245 0.316 0.407 
# 3.3 3 3 0.459 0.258 0.084 0.839 0.476 0.390 0.435 0.325 0.711 0.143 
+0

Ihre Methode scheint auch ohne Regex-Ausdrücke gut zu funktionieren. Ich habe etwas ähnliches mit Schmelze probiert und es funktioniert nicht – skan