2016-04-24 17 views
0

Ich habe 2 Datenrahmen, die erste Spalte von einem ist eine Liste (df A), die erste Spalte des anderen enthält Elemente aus der Liste, aber in einigen Fällen Jede Zeile hat mehrere Elemente (df B). Was ich tun möchte, durch wird gehen und neue Zeilen von df A für jedes Element erstellen, tritt das in der ersten Spalte von df B.Erstellen neuer Datenrahmen Zeilen basierend auf einer Spalte aus einem anderen Datenrahmen

DF A

dfA 
    Index X 
1 1 alpha 
2 2 beta 
3 3 gamma 
4 4 delta 

DF B

dfB 
    list X 
1 1 4 alpha 
2 3 2 1 beta 
3 4 1 2 gamma 
4 3  delta 

Wunsch
dfC 
    Index x 
1 1  alpha 
2 4  alpha 
3 3  beta 
4 2  beta 
5 1  beta 
6 4  gamma 
7 1  gamma 
8 2  gamma 
9 3  delta 

Die eigentlichen Daten ich verwende: DF A

dput(head(allwines)) 
structure(list(Wine = c("Albariño", "Aligoté", "Amarone", "Arneis", 
"Asti Spumante", "Auslese"), Description = c("Spanish white wine grape that makes crisp, refreshing, and light-bodied wines.", 
"White wine grape grown in Burgundy making medium-bodied, crisp, dry wines with spicy character.", 
"From Italy’s Veneto Region a strong, dry, long- lived red, made from a blend of partially dried red grapes.", 
"A light-bodied dry wine the Piedmont Region of Italy", "From the Piedmont Region of Italy, A semidry sparkling wine produced from the Moscato di Canelli grape in the village of Asti", 
"German white wine from grapes that are very ripe and thus high in sugar" 
)), .Names = c("Wine", "Description"), row.names = c(NA, 6L), class = "data.frame") 

DF B

> dput(head(cheesePairing)) 
structure(list(Wine = c("Cabernet Sauvignon\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Pinot Noir\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Sauvignon Blanc\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Zinfandel", 
"Chianti\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Pinot Noir\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Sangiovese", 
"Chardonnay", "Bardolino\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Malbec\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Riesling\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Rioja\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Sauvignon Blanc", 
"Tempranillo", "Asti Spumante"), Cheese = c("Abbaye De Belloc Cheese", 
"Ardrahan cheese", "Asadero cheese", "Asiago cheese", "Azeitao", 
"Baby Swiss Cheese"), Suggestions = c("Pair with apples, sliced pears OR a sampling of olives and thin sliced salami. Pass around slices of baguette.", 
"Serve with a substantial wheat cracker and apples or grapes.", 
"Rajas (blistered chile strips) fresh corn tortillas", "Table water crackers, raw nuts (almond, walnuts)", 
"Nutty brown bread, grapes", "Server with dried fruits, whole grain, nutty breads, nuts" 
)), .Names = c("Wine", "Cheese", "Suggestions"), row.names = c(NA, 
6L), class = "data.frame") 
+0

Es wäre hilfreich, wenn Sie Ihre Frage bearbeiten könnten, um Ihre Beispieldaten in ein R-Parse-Format aufzunehmen. Z.B. 'dput (dfA)' und 'dput (dfB)'. –

+0

@CurtF. Ich fügte meine Beispieldaten hinzu, ich war besorgt, dass es zu verwirrend sein könnte, also hatte ich es entfernt und das erfundene Beispiel eingefügt. –

+1

Ich bin mir nicht sicher, was die Verwendung von 'DFA' ist. die Weine in 'DFB' haben eine Menge extra Leerzeichen in ihnen, so können Sie das für Kommas' cheesePairing $ Wine <- gsub ('\\ s {2,}', ',', df $ Wine) 'herausfiltern und verwende nun eine der Antworten in [diese Frage] (http://stackoverflow.com/questions/28285169/split-comma-separated-column-entry-into-rows) oder andere ähnliche – rawr

Antwort

2

Aufbauend auf Curts Antwort fand ich eine effizientere Lösung ... vorausgesetzt, ich interpretiere Ihr Ziel richtig.

Mein kommentierter Code ist unten. Sie sollten in der Lage sein, dies so zu tun, wie es ist und den gewünschten dfC zu bekommen. Eine Sache zu beachten ist, dass ich angenommen habe (basierend auf Ihren tatsächlichen Daten), dass die Trennzeichenaufteilung dfB $ Index "\ r \ n" ist.

# set up fake data 
dfA<-data.frame(Index=c('1','2','3','4'), X=c('alpha','beta','gamma','delta')) 
dfB<-data.frame(Index=c('1 \r\n 4','3 \r\n 2 \r\n 1','4 \r\n 1 \r\n 2','3'), X=c('alpha','beta','gamma','delta')) 

dfA$Index<-as.character(dfA$Index) 
dfA$X<-as.character(dfA$X) 
dfB$Index<-as.character(dfB$Index) 
dfB$X<-as.character(dfB$X) 


dfB_index_parsed<-strsplit(x=dfB$Index,"\r\n") # split Index of dfB by delimiter "\r\n" and store in a list 
names(dfB_index_parsed)<-dfB$X 
dfB_split_num<-lapply(dfB_index_parsed, length) # find the number of splits per row of dfB and store in a list 
dfB_split_num_vec<-do.call('c', dfB_split_num) # convert number of splits above from list to vector 

g<-do.call('c',dfB_index_parsed) # store all split values in a single vector 
g<-gsub(' ','',g) # remove trailing/leading spaces that occur after split 
names(g)<-rep(names(dfB_split_num_vec), dfB_split_num_vec) # associate each split Index from dfB with X from dfB 
g<-g[g %in% dfA$Index] # check which dfB$Index are in dfA$Index 

dfC<-data.frame(Index=g, X=names(g)) # construct data.frame 
+0

Ich endete mit einem leeren Datenrahmen, aber die ersten paar Schritte scheinen in die richtige Richtung zu gehen.Aus irgendeinem Grund hat das Scraping eine Menge extra erstellt, so dass im dritten Schritt die Anzahl der Splits komplett aus ist. Ich werde versuchen, alles leer zu entfernen, und sehen, ob das hilft –

+0

Oh komisch. Ich kopiere einfach meinen Code in eine separate R-Sitzung und es lief gut. Wie auch immer, froh zu hören, dass es etwas hilfreich ist. Ich denke, dass die Funktionen strsplit() und gsub() für jede Strategie zur Lösung dieses Problems entscheidend sein werden. regexpr() kann auch hilfreich sein. Überprüfen Sie außerdem, ob das von Ihnen verwendete Scraping-Paket eine integrierte Funktion zum Behandeln dieser Scraper-Ergebnisse enthält. – AOGSTA

+0

Gibt es Hinweise darauf, dass dies tatsächlich effizienter ist? So oder so, nette Antwort und +1 von mir. –

0

Lassen Sie mich zunächst auf Ihre Frage eine funktionale Antwort. Ich bezweifle, dass meine Antwort sehr effizient ist, aber es funktioniert.

# construct toy data 
dfA <- data.frame(index = 1:4, X = letters[1:4]) 

dfB <- data.frame(X = letters[1:4]) 
dfB$list_elements <- list(c(1, 4), c(3, 2, 1), c(4, 1, 2), c(3)) 

# define function that provides solution 

unlist_merge_df <- function(listed_df, reference_df){ 
    # reference_df assumed to have columns "X" and "index" 
    # listed_df assumed to have column "list_elements" 
    df_out <- data.frame(index = c(), X = c()) 
    my_list <- listed_df$list_elements 
    for(idx in 1:length(my_list)){ 
     df_out <- rbind(df_out, 
         data.frame(index = my_list[[idx]], 
            X = listed_df[idx, 'X']) 
         ) 
    } 
    return(df_out) 
} 

# call the function 
dfC <- unlist_merge_df(dfB, dfA) 

# show output in human and R-parseable formats 
dfC 

dput(dfC) 

Die Ausgabe lautet:

index X 
1 1 a 
2 4 a 
3 3 b 
4 2 b 
5 1 b 
6 4 c 
7 1 c 
8 2 c 
9 3 d 

structure(list(index = c(1, 4, 3, 2, 1, 4, 1, 2, 3), X = structure(c(1L, 
1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L), .Label = c("a", "b", "c", "d" 
), class = "factor")), .Names = c("index", "X"), row.names = c(NA, 
9L), class = "data.frame") 

Zweitens möchte ich sagen, dass die Situation, die Sie in sind nicht sehr wünschens ist. Wenn Sie es vermeiden können, sollten Sie wahrscheinlich. Entweder verwenden Sie überhaupt keine Datenrahmen und verwenden nur Listen oder vermeiden es, den aufgelisteten Datenrahmen vollständig zu konstruieren (wenn Sie können) und konstruieren direkt die gewünschte Ausgabe.

+1

danke, ich weiß, das ist keine ideale situation. Ich habe die Daten durch Web-Scraping und versuche, es für eine Datenbank nutzbar zu machen, aber es sieht so aus, als müsste ich nur mit der Art und Weise und in meinen Datenbankabfragen ein wenig expliziter machen, wenn ich dies ausführe. –

Verwandte Themen