2015-04-26 13 views
5

Próbuję wygenerować kolumny w tbl_df że jest losowa całkowitą 0 lub 1. Jest to kod używam:dplyr: Integer próbkowania ciągu mutować

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)) 

Ale to nie wydaje się pracować tak, jak się spodziewałem. Generowane pole wydaje się być zerami. Czy to dlatego, że oświadczenie w numerze mutate jest oceniane równolegle, a tym samym kończy się przy użyciu tego samego materiału siewnego dla pierwszego losowego losowania?

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 

W ciągu ostatnich kilku godzin łamie mi to głowę. Masz pojęcie, co jest wadą mojego skryptu?

+1

Zastosowanie 'próbki (1: 0, 12, wymienić = PRAWDA)' – DatamineR

+6

lub 'próbki (0: 1, n(), zastąp = TRUE) ' –

Odpowiedz

7

Sposób w jaki napisany jest twój kod, przypisujesz pojedynczą wartość (wynik losowego losowania) całemu wektorowi (nazywa się to "recyklingiem wektorowym").

Najlepszym rozwiązaniem w tym przypadku jest odpowiedź Steven Beaupre, tworząc z randomizowanym wektor długość data.frame:

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

Generalnie, jeśli chcesz zastosować funkcję wiersz po kroku rząd w dplyr - tak jak myślałeś, że stanie się tutaj - możesz użyć rowwise(), chociaż w tym przykładzie nie jest to wymagane.

Oto przykład 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 

Ponieważ rowwise grupy danych przez każdej operacji rzędu są potencjalnie wolniej niż bez grupowania. Dlatego lepiej jest używać funkcji wektoryzacji, gdy tylko jest to możliwe, zamiast obsługiwać wiersz po rzędzie.


pomiaru:

Podejście z rowwise() około 30x wolniej:

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

To działa dobrze. Więc wyrażenie wewnątrz 'mutate' nie jest oceniane dla każdego wiersza bez tego operatora? Czy istnieje jakaś forma zdumiewającej transmisji rozgrywającej się z 'mutate'? – sriramn

+0

Dokładnie. Dodałem przykład ilustrujący bardziej typową aplikację 'rowwise()'. –

+0

"Rowwise" nie jest w tym przypadku konieczne. Zamiast tego podejście w komentarzu Stevena do tego pytania byłoby moim zdaniem najlepsze. –

Powiązane problemy