2016-11-10 16 views
0

Von ?dplyr::bind_cols:Gibt es eine Möglichkeit, dplyrs bind_cols zu erhalten, um die Anzahl der Zeilen wie in cbind zu erweitern?

Dies ist eine effiziente Implementierung des gemeinsamen Muster von do.call (rbind, dfs) ​​oder do.call (cbind, DFS) für die Bindung von vielen Datenrahmen in einem

jedoch mit Beispieldaten:

tmp_df1 <- data.frame(a = 1) 
tmp_df2 <- data.frame(b = c(-2, 2)) 
tmp_df3 <- data.frame(c = runif(10)) 

Der Befehl do.call(cbind, list(tmp_df1, tmp_df2, tmp_df3)) erzeugt:

a b   c 
1 1 -2 0.8473307 
2 1 2 0.8031552 
3 1 -2 0.3057430 
4 1 2 0.6344999 
5 1 -2 0.7870753 
6 1 2 0.9453199 
7 1 -2 0.6642231 
8 1 2 0.9708049 
9 1 -2 0.7189576 
10 1 2 0.9217087 

Das heißt, Zeilen von tmp_df1 und tmp_df2 werden recycelt, um der Anzahl der Zeilen in tmp_df3 zu entsprechen.

In dplyr:

> bind_cols(tmp_df1, tmp_df2, tmp_df3) 
Error in eval(substitute(expr), envir, enclos) : 
    incompatible number of rows (2, expecting 1) 

Der Grund, warum ich so etwas wie dies tun möchte, ist, weil ich in einer Situation unter ähnlichen bin:

df_normal_param <- df(mu = rnorm(10), sigma = runif(10)) 

df_normal_sample_list <- lapply(1:10, function(i) 
         with(df_normal_param, 
           data.frame(sam = rnorm(100, mu[i], sigma[i])) 

und ich möchte die Argumente befestigen um jeden Eintrag von df_normal_sample_list zu den Ausgängen zu erstellen, z

df_normal_sample_list <- lapply(1:10, function(i) 
         cbind(df_normal_param[i,], df_normal_sample_list[[i]])) 
+1

Eines der Beispiele weist ausdrücklich darauf hin, dass es nicht tun, was Sie wollen: '# Zeilen brauchen, wenn Spalte-Bindi übereinstimmen ng bind_cols (data.frame (x = 1), data.frame (y = 1: 2)) so würde ich feststellen, dass es eine absichtliche Designentscheidung ist, die innerhalb von dplyr schwer zu umgehen sein wird. – joran

+1

'tidyr :: fill()' ist das nächste, was ich mir zum Ausfüllen von fehlenden Werten vorstellen kann. Normalerweise werden Datenbanktabellen basierend auf einer Sortierposition zusammengefügt, um * schlechte * Ergebnisse zu erhalten. habe ein Gefühl, dass der Grund für das Sicherheitsband ist. –

+0

In meinem Fall ist es sicher und gewünscht. Ich habe eine Funktion 'f (x, y, z)', die einen Datenrahmen mit mehreren Zeilen erzeugt. Ich habe einen anderen Datenrahmen mit den Spalten x, y, z, so dass jede Zeile dieses Datenrahmens die Argumente für die Funktion "f" liefert. Ich möchte die Argumente, die zur Erzeugung der Ausgabe von "f" mit der Ausgabe von "f" verwendet wurden, "binden", um später eine Analyse durchzuführen. – Alex

Antwort

2

Sie argumentieren in einem Kommentar, dass dieses Verhalten sicher ist, stimme ich überhaupt nicht zu. Es scheint sicher zu sein, für diesen speziellen Fall, aber es ist wahrscheinlich, dass Sie Probleme irgendwo auf der Straße verursachen. Aus diesem Grund glaube ich, dass die Antwort auf Ihre Frage ("Gibt es eine Möglichkeit, dplyrs bind_cols zu erweitern, um die Anzahl der Zeilen wie in cbind zu erweitern?") Einfach ist: nein, und sie haben es wahrscheinlich so absichtlich gebaut.

Stattdessen würde ich vorschlagen, dass Sie expliziter in Ihrem Ansatz sind, und nur die Spalten hinzufügen, die Sie wollen, richtig, wie Sie die Daten erstellen, die Sie erstellen. Zum Beispiel könnten Sie diesen Schritt direkt in Ihrem Anruf enthalten (hier apply mit zu klären, was wo geht)

df <- data.frame(mu = rnorm(3), sigma = runif(3)) 

df_normal_sample_list <- apply(df, 1, function(x){ 
    data.frame(
    mu = x["mu"] 
    , sigma = x["sigma"] 
    , sam = rnorm(3, x["mu"], x["sigma"]) 
) 
}) 

Returns

[[1]] 
      mu  sigma  sam 
1 -0.6982395 0.1690402 -0.592286 
2 -0.6982395 0.1690402 -0.516948 
3 -0.6982395 0.1690402 -0.804366 

[[2]] 
     mu  sigma  sam 
1 -1.698747 0.2597186 -1.830950 
2 -1.698747 0.2597186 -2.087393 
3 -1.698747 0.2597186 -1.961376 

[[3]] 
     mu  sigma  sam 
1 0.9913492 0.3069877 0.9629801 
2 0.9913492 0.3069877 1.2279697 
3 0.9913492 0.3069877 1.1222780 

Dann wird anstelle der Bindung der Spalten, dann die Zeilen, Sie können nur die Zeilen am Ende binden (auch von dplyr)

bind_rows(df_normal_sample_list) 
+0

Und für die alternierenden Werte filtern Sie einfach alle geraden Zeilen '% 2 == 0', bevor Sie den Wert in –

+0

zuweisen Können Sie bitte ein Beispiel geben, wo Sie denken, dass dies mir Probleme auf der Straße geben wird? – Alex

+1

Das wahrscheinlichste Szenario ist, wenn sich Ihr 'df_normal_param' ändert, bevor Sie das Kombinieren durchführen. Dies könnte passieren, wenn Sie etwas ändern und vergessen, 'df_normal_sample_list' neu zu erstellen oder wenn ein Fehler beim Erstellen der neuen' df_normal_sample_list' auftritt und Sie es nicht fangen, also versehentlich zu einer alten Version zusammenführen. Es ist auch sehr leicht, eine Änderung in der Erstellung Ihrer Ausgabe zu verpassen, die etwas ändert (z. B. Anzahl der Zeilen pro Gruppe). Ich bin auch auf wesentliche Probleme mit Funktionen gestoßen, die gelegentlich NULL oder NA zurückgeben - je nach Details werden diese von 'cbind' sehr unterschiedlich gehandhabt. –

Verwandte Themen