2015-04-26 19 views
5

Ich versuche, eine Spalte in einer tbl_df zu erzeugen, die eine zufällige ganze Zahl von 0 oder 1 ist Dies ist der Code, den ich verwende:dplyr: Integer Sampling innerhalb mutieren

library(dplyr) 
set.seed(0) 

#Dummy data.frame to test 
df <- tbl_df(data.frame(x = rep(1:3, each = 4))) 

#Generate the random integer column 
df_test = df %>% 
    mutate(pop=sample(0:1, 1, replace=TRUE)) 

Aber dies scheint nicht zu arbeite so, wie ich es erwartet habe. Das von mir generierte Feld scheint nur aus Nullen zu bestehen. Liegt das an der Tatsache, dass die Anweisung innerhalb von mutate parallel ausgewertet wird und daher den gleichen Startwert für die erste zufällige Auslosung verwendet?

df_test 
Source: local data frame [12 x 2] 

    x pop 
1 1 0 
2 1 0 
3 1 0 
4 1 0 
5 2 0 
6 2 0 
7 2 0 
8 2 0 
9 3 0 
10 3 0 
11 3 0 
12 3 0 

Ich breche meinen Kopf über dies die letzten Stunden. Irgendeine Idee, was ist der Fehler in meinem Skript?

+1

Verwenden 'Probe (0: 1, 12, ersetzen = TRUE)' – DatamineR

+6

oder 'Probe (0: 1, n(), ersetzen = TRUE) ' –

Antwort

7

Wie der Code geschrieben wird, weisen Sie dem gesamten Vektor einen einzelnen Wert zu (das Ergebnis der Zufallszeichnung) (dies wird "Vektorrecycling" genannt).

Die beste Lösung in diesem Fall ist die Antwort von Steven Beaupré, eine randomisierte Vektor die Länge Ihrer data.frame erstellen:

df %>% 
    mutate(pop = sample(0:1, n(), replace = TRUE)) 

Im Allgemeinen, wenn Sie eine Funktion Zeile-für- anwenden möchten Zeile in dplyr - wie Sie dachten, würde hier passieren - können Sie rowwise() verwenden, obwohl in diesem Beispiel es nicht erforderlich ist.

Hier ist ein Beispiel für rowwise():

df2 <- data.frame(a = c(1,3,6), b = c(2,4,5)) 

df2 %>% 
    mutate(m = max(a,b)) 

    a b m 
1 1 2 6 
2 3 4 6 
3 6 5 6 

df2 %>% 
    rowwise() %>% 
    mutate(m = max(a,b)) 

    a b m 
1 1 2 2 
2 3 4 4 
3 6 5 6 

Da rowwise gruppiert die Daten, die von jeder Reihe Operationen möglicherweise langsamer sind, als ohne jede Gruppierung. Daher ist es meist besser, vektorisierte Funktionen wann immer möglich zu verwenden, anstatt Zeile für Zeile zu arbeiten.


Benchmarking:

Der Ansatz mit rowwise() ist etwa 30-fach langsamer:

library(microbenchmark) 
df <- tbl_df(data.frame(x = rep(1:1000, each = 4))) 
bench <- microbenchmark(
    vectorized = df2 <- df %>% mutate(pop = sample(0:1, n(), replace = TRUE)), 
    rowwise = df2 <- df %>% rowwise() %>% mutate(pop = sample(0:1, 1, replace = TRUE)), 
    times = 1000 
) 

options(microbenchmark.unit="relative") 
print(bench) 
autoplot(bench) 

Unit: relative 
     expr  min  lq  mean median  uq  max neval 
vectorized 1.00000 1.00000 1.00000 1.00000 1.00000 1.0000 1000 
    rowwise 42.53169 42.29486 36.94876 33.70456 34.92621 71.7682 1000 
+0

Das funktioniert gut. Der Ausdruck innerhalb von muate wird also nicht für jede Zeile ohne diesen Operator ausgewertet? Also gibt es eine Art von numpy wie Broadcasting passiert mit 'muate'? – sriramn

+0

Genau. Ich habe ein illustratives Beispiel für eine typische Anwendung von 'rowwise()' hinzugefügt. –

+0

'reihenweise' ist in diesem Fall nicht notwendig. Stattdessen wäre der Ansatz in Steven's Kommentar zu der Frage meiner Meinung nach am besten. –

Verwandte Themen