2016-08-08 5 views
0

ich einen Datenrahmen haben, die mit diesem Code erstellt werden können:Erstellen von Eingangspaar Daten Name-Wert-Rahmen mit Begrenzungszeichen

input <- data.frame('ID'=c(1:3), 
         Destination=c("A\r\nB", "C", "D\r\nE\r\nF"), 
         Topic=c("W", "X", "Y\r\nZ")) 

Es sieht aus wie:

ID Destination Topic 
1 1  A\r\nB  W 
2 2   C  X 
3 3 D\r\nE\r\nF Y\r\nZ 

Ich möchte einen Ausgangsdatenrahmen erstellen, die wie folgt aussieht:

desiredOutput <- data.frame( 
    ID = c(1,1,1,2,2,3,3,3,3,3) , 
    name=c("Destination", "Destination", "Topic", "Destination", "Topic", 
      "Destination", "Destination", "Destination" , "Topic", "Topic"), 
    value=c("A","B", "W", "C", "X", "D", "E", "F", "Y", "Z")) 

    ID  name value 
1 1 Destination  A 
2 1 Destination  B 
3 1  Topic  W 
4 2 Destination  C 
5 2  Topic  X 
6 3 Destination  D 
7 3 Destination  E 
8 3 Destination  F 
9 3  Topic  Y 
10 3  Topic  Z 

Jedes Mal, wenn der Begrenzer \r\n auftritt, Ich möchte den Inhalt in separate Zeilen mit der richtigen ID, dem Namen der Spalte und dem entsprechenden Wert aufteilen.

Ich kann eine einzelne Spalte in eine Liste unter Verwendung strsplit teilen, aber ich weiß nicht, wie man den Inhalt in einen Datenrahmen wie oben abgesehen von dem Versuch schreibt, eine Schleife zu schreiben. Ich erwarte das tidyr Paket könnte hilfreich sein.

strsplit(input$Destination, split = "\r\n") 

Wie kann das gemacht werden, idealerweise ohne eine Schleife?

Antwort

1

Mit tidyr, gather zu lange Form, dann separate_rows verwenden, um die verbundenen Elemente zu trennen:

library(tidyr) 

input %>% gather(name, value, -ID) %>% separate_rows(value) 
## ID  name value 
## 1 1 Destination  A 
## 2 1 Destination  B 
## 3 2 Destination  C 
## 4 3 Destination  D 
## 5 3 Destination  E 
## 6 3 Destination  F 
## 7 1  Topic  W 
## 8 2  Topic  X 
## 9 3  Topic  Y 
## 10 3  Topic  Z 

Hinweis: Wenn Ihre Daten Faktoren anstelle von Zeichen ist, tidyr wird Sie warnen, wie es nötigt Zeichen, um neu zu ordnen. Es wird unabhängig davon funktionieren, aber wenn Sie Warnungen hassen, erzwingen Sie vor dem Umformen den Charakter manuell.

+1

Schön. Ich dachte dasselbe mit data.table wie in 'library (data.table); schmelze (setDT (input), 1, value.factor = FALSE) [, unlist (strsplit (wert, "\ r \ n")), by = variable] 'aber ich mag deine syntax besser hier –

+0

Das ist sehr elegant, aber gibt mir einige zusätzliche Zeilen, wo Daten nicht aufgeteilt werden sollten. Ich habe ein Beispiel, das aussieht wie 'A_B \ r \ nC_D'. Es sollte nicht durch das '_' getrennt werden, nur durch' \ r \ n' – Bobby

+2

Ah, 'getrennt' nimmt an, dass nicht-alphanumerische Zeichen Separatoren sind. Um zu beschränken, geben Sie einfach an: 'separate_rows (Wert, sep = '\ r \ n')' – alistaire

1

Hier ist eine Option data.table

library(data.table) 
melt(setDT(input), id.var = "ID", variable.name = "name")[, 
     .(value = unlist(strsplit(value, "\\s+"))), .(ID, name)][order(ID)] 
#  ID  name value 
#1: 1 Destination  A 
#2: 1 Destination  B 
#3: 1  Topic  W 
#4: 2 Destination  C 
#5: 2  Topic  X 
#6: 3 Destination  D 
#7: 3 Destination  E 
#8: 3 Destination  F 
#9: 3  Topic  Y 
#10: 3  Topic  Z 

EDIT: Eine ähnliche Lösung von @DavidArenburg in einer anderen Lösung kommentiert wurde (was ich nicht früher sehen).

Verwandte Themen