2017-12-02 2 views
-1

Ich habe ein data.frame mit Spaltennamen:R - Wie erstellt man eine neue Tabelle, indem man eine neue Spalte hinzufügt, indem man den Namen des Elements aus dem Spaltennamen extrahiert?

Machine1.workingTime, Machine2.workingTime, Machine3.workingTime, 
Machine1.producedItems, Machine2.producedItems, ... 

Dieser Rahmen, indem Zeit mit mehr Maschinen erweitern. Ich brauche ein R-Skript zu machen, wo ich diese Lösung bekommen haben:

workingTime, producedItems, MachineNum 

Wo MachineNum ist die Zahl in der Spalte, von wo aus ich die Daten erhalten (zB wenn ich Machine2.workingTime Spalte erhalten und fügen. die neu erstellte Spalte „Arbeitszeit-“, die „MachineNum“ würde 2 sein

ich durch die ganze data.frame laufen haben und die Zusammenführung der Spalten in neue Spalten, die den Teil des Namens des alten ursprünglichen Namen (zB Arbeitszeit-) und Filtern Sie die MachineNum aus dem ersten Teil des alten ursprünglichen Spaltennamens

Ich habe die letzten Stunden versucht und gesucht, aber ich konnte keine Lösung finden.

+0

Bitte geben Sie ein Codebeispiel an, das Ihren Datenrahmen (oder erfundene Daten ähnlich Ihrem Datenrahmen) enthält und zeigt, wie weit Sie gekommen sind und wo Sie stecken geblieben sind. –

+0

Es ist nicht klar, ob dies Spaltennamen oder Werte in einer Spalte sind. Was ist 'MachineNum'? – akrun

+0

Ich denke, die Schlüsselwörter für Sie sind lange Form im Vergleich zu Wide-Form-Daten und wie man von auf die andere konvertieren. Wenn Sie Beispieldaten angeben, erhalten Sie wahrscheinlich viel bessere Antworten. – snoram

Antwort

0

Ich denke (hoffe), das ist über das, was Sie suchen. Ich weiß, dass meine Antwort nicht die prägnanteste ist und freue mich darauf, andere sauberere Antworten zu sehen.

library(data.table) # for melt() and merge(), other package have similar func. 

# Dummy data.frame 
df <- data.frame(date = Sys.Date() - 800:1, 
       matrix(sample(0:10000, 2400), ncol = 6)) 
colnames(df)[-1] <- paste0("m", 1:3, c(rep(".wt", 3), rep(".pi", 3))) 
head(df) 
     date m1.wt m2.wt m3.wt m1.pi m2.pi m3.pi 
1 2015-09-24 6271 2491 6525 6680 7708 2949 
2 2015-09-25 1173 5794 5616 7402 3274 8997 
3 2015-09-26 516 6659 2144 8739 7168 1704 
4 2015-09-27 583 2499 4768 9501 2710 6800 
5 2015-09-28 2433 8622 6492 7124 4127 233 
6 2015-09-29 3409 662 6952 3824 5755 9479 

# Now first take working time (filter using regex) to long form 
df_wt <- melt(df[, c("date", grep("wt$", colnames(df), value = TRUE))], 
       id.vars = c("date"), 
       value.name = "workingTime", 
       variable.name = "MachineNum") 
df_wt$MachineNum <- gsub("m([0-9]).+", "\\1", df_wt$MachineNum) 
head(df_wt) 
     date MachineNum workingTime 
1 2015-09-24   1  6271 
2 2015-09-25   1  1173 
3 2015-09-26   1   516 
4 2015-09-27   1   583 
5 2015-09-28   1  2433 
6 2015-09-29   1  3409 

# Same for produced item 
df_pi <- melt(df[, c("date", grep("pi$", colnames(df), value = TRUE))], 
       id.vars = c("date"), 
       value.name = "producedItems", 
       variable.name = "MachineNum") 
df_pi$MachineNum <- gsub("m([0-9]).+", "\\1", df_pi$MachineNum) 
head(df_pi) 
     date MachineNum producedItems 
1 2015-09-24   1   6680 
2 2015-09-25   1   7402 
3 2015-09-26   1   8739 
4 2015-09-27   1   9501 
5 2015-09-28   1   7124 
6 2015-09-29   1   3824 

# Now merge everything 
df_long <- merge(df_wt, df_pi) 
head(df_long) 
     date MachineNum workingTime producedItems 
1 2015-09-24   1  6271   6680 
2 2015-09-24   2  2491   7708 
3 2015-09-24   3  6525   2949 
4 2015-09-25   1  1173   7402 
5 2015-09-25   2  5794   3274 
6 2015-09-25   3  5616   8997 
+0

df_wt $ MachineNum <- gsub ("m ([0-9]). +", "\\ 1", df_wt $ MachineNum) dies scheint nicht zu funktionieren. Ich bekomme Fehler in '$ <-. Data.frame' (' * tmp * ', testCaseNumber, Wert = Zeichen (0)): Ersatz hat 0 Zeilen, Daten hat 8347837. Spaltenname ist Machine_01.workingTime und ich nicht brauche ein beliebiges Datum zu verwenden. also habe ich es ohne id.vars = c ("date") ausprobiert und 1 spalte mit workingTime von nur einer maschine bekommen – Rnooby

+0

Wenn du kein datum hast denke ich dass du eine id variable brauchst um die beobachtungen zu verfolgen ... – snoram

+0

Kann ich die Anfangsnummer irgendwie verwenden? – Rnooby

0

Hier ist ein Ansatz mit der reshape2 Bibliothek.

machine1.workingTime <- 1:10 
machine2.workingTime <- 21:30 
machine1.producedItems <- 101:110 
machine2.producedItems <- 201:210 
date <- c("2017-01-01","2017-01-02","2017-01-03","2017-01-04","2017-01-05","2017-01-06", 
      "2017-01-07","2017-01-08","2017-01-09","2017-01-10") 


    theData <- data.frame(date, 
         machine1.producedItems, 
         machine1.workingTime, 
         machine2.producedItems, 
         machine2.workingTime 
        ) 

library(reshape2) 

meltedData <- melt(theData,measure.vars=2:5) 
meltedData$variable <- as.character(meltedData$variable) 

# now, extract machine numbers and variable names 
variableNames <- strsplit(as.character(meltedData$variable),"[.]") 
# token after the . is variable name 
meltedData$columnName <- unlist(lapply(variableNames,function(x) x[2])) 
# since all variables start with word 'machine' we can set chars 8+ as ID 
meltedData$machineId <- as.numeric(unlist(lapply(variableNames,function(x) y <- substr(x[1],8,nchar(x[1]))))) 

theResult <- dcast(meltedData,machineId + date ~ columnName,value.var="value") 
head(theResult) 

Die Ergebnisse sind:

> head(theResult) 
    machineId  date producedItems workingTime 
1   1 2017-01-01   101   1 
2   1 2017-01-02   102   2 
3   1 2017-01-03   103   3 
4   1 2017-01-04   104   4 
5   1 2017-01-05   105   5 
6   1 2017-01-06   106   6 
> 

UPDATE (02Dec2017): auf die Kommentare reagieren, wenn es keine andere Kennung mehrere Zeilen für eine Maschine zur eindeutigen Unterscheidung kann man eine Aggregation verwenden Funktion, die zu einer Beobachtung pro Maschine führt.

theResult <- dcast(meltedData,machineId ~ columnName, 
        fun.aggregate=mean,value.var="value") 
head(theResult) 

Die Ergebnisse sind wie folgt.

> head(theResult) 
    machineId producedItems workingTime 
1   1   105.5   5.5 
2   2   205.5  25.5 
> 

UPDATE (02Dec2017): auf Kommentare reagieren, eine Lösung, die eine eindeutige laufende Nummer verwendet Zeilen von Daten zu unterscheiden, sieht wie folgt aus.

machine1.workingTime <- 1:10 
machine2.workingTime <- 21:30 
machine1.producedItems <- 101:110 
machine2.producedItems <- 201:210 
id <- 1:length(machine1.workingTime) 

theData <- data.frame(id, 
         machine1.producedItems, 
         machine1.workingTime, 
         machine2.producedItems, 
         machine2.workingTime 
) 

meltedData <- melt(theData,measure.vars=2:5) 
head(meltedData) 
meltedData$variable <- as.character(meltedData$variable) 

# now, extract machine numbers and variable names 
variableNames <- strsplit(as.character(meltedData$variable),"[.]") 
meltedData$columnName <- unlist(lapply(variableNames,function(x) x[2])) 
meltedData$machineId <- as.numeric(unlist(lapply(variableNames,function(x) y <- substr(x[1],8,nchar(x[1]))))) 

theResult <- dcast(meltedData,machineId + id ~ columnName,value.var="value") 
head(theResult) 

... und der Ausgang.

+0

Also, das scheint zu funktionieren, bis theResult <-dcast ... Ich entferne "+ Datum", da ich kein Datum brauche. Aber das funktioniert nicht ohne Datum. Die geschmolzenen Daten scheinen korrekt zu sein. Sie müssen es nur von lang formatierten Daten in kurz formatierte Daten umwandeln !? Es scheint nicht zu funktionieren ohne einen einzigartigen Wert anstelle des Datums !? – Rnooby

+0

@Rnooby - Sofern nicht nur eine Zeile im Datenrahmen vorhanden ist, müssen Sie mehrere Zeilen in der Ausgabe von 'dcast() 'unterscheiden. Die Lösung von @snoram hebt das gleiche Problem hervor: Sie benötigen eine Art ID-Variable, um mehrere Zeilen für jede Rechner-ID zu unterscheiden, oder Sie müssen eine Aggregationsfunktion wie 'sum()' oder 'mean()' verwenden . –

+0

Kann ich die Startnummer irgendwie verwenden? Ich bin sehr neu in R und das ist irgendwie schwierig, es selbst herauszufinden. Danke Ihnen allen für Ihre Hilfe. – Rnooby

Verwandte Themen