2014-10-22 15 views
5

Funkcja mutate z pakietu R "dplyr" ma szczególną funkcję recyklingu czynników, ponieważ wydaje się zwracać czynnik as.numeric. W poniższym przykładzie y staje się to, czego można się spodziewać, natomiast z jest c(1,1)Dziwny recykling czynników w dplyr :: mutate - bug lub funkcja?

library(dplyr) 
df <- data_frame(x=1:2) 
glimpse(df %>% mutate(y="A", z=factor("B"))) 
# Variables: 
# $ x (int) 1, 2 
# $ y (chr) "A", "A" 
# $ z (int) 1, 1 

Czy istnieje uzasadnienie tego, czy jest to błąd?

(używam R 3.1.1 i dplyr 0.3.0.1.)


EDIT:

Po wysłaniu tego jako problemu na github, Romain Francois naprawić go w ciągu kilku godzin! Jeśli powyższe jest więc używać problem devtools::install_github aby pobrać najnowszą wersję:

library(devtools) 
install_github("hadley/dplyr") 

a następnie

library(dplyr) 
df <- data_frame(x=1:2) 
glimpse(df %>% mutate(y="A", z=factor("B"))) 
# Variables: 
# $ x (int) 1, 2 
# $ y (chr) "A", "A" 
# $ z (fctr) B, B 

Dobra robota Romain!

+0

To zachowanie wydaje się być spowodowane recyklingiem wektorowym. Jeśli określisz współczynnik długości 2, np. 'Przebłysk (df%>% mutate (y =" A ", z = współczynnik (c (" B "," C "))))', zmienna 'z' będzie klasy czynnikowej. –

+0

Jednym ze sposobów uzyskania zmiennej czynnikowej byłoby 'df%>% do (data.frame (., Y =" A ", z = współczynnik (" B "), stringiAsFactors = FALSE))' – akrun

+0

@akrun Dlaczego ' mutować "nie jest właściwym wyborem? Jakieś pomysły? – jazzurro

Odpowiedz

12

dplyr używa C++ do wykonania rzeczywistej operacji mutate. Followingtherabbithole i zauważając, że jest to ungrouped mutation, możemy skorzystać z naszego sprawdzonego debuggera, aby zwrócić uwagę na następujące rzeczy.

debugonce(dplyr:::mutate_impl) 
# Inside of mutate_impl we do: 
class(dots[[2]]$expr) # which is a "call"! 

Teraz znamy typ naszego lazy expression. Mamy eval połączenie i notice jest to supported type (niestety, roszczenia z roszczeń R TYPEOF, będziemy potrzebować do rozróżnienia).

Co dalej? Mamy returned the result i skończymy. Jeśli już wypróbowałeś (df %>% mutate(y="A", z=factor(c("A","B"))))[[3]], będziesz wiedzieć, że chodzi o recykling.

Specifically, C++ Gatherer object (co should really być sprawdzanie Rf_isFactor oprócz bieżącej jego daty kontroli na INTSXP S) przy użyciu C++ templating do force a Vector<INTSXP> zostać utworzony (pośrednio poprzez inicjalizacji konstruktora - zauważył połączenie w ConstantGathererImpl arity 2) nie pamiętając o przeniesieniu czynnika "etykieta".

TLDR: W języku R C++ liczby całkowite i współczynniki mają ten sam wewnętrzny typ, co makro TYPEOF, a współczynniki są przypadkami dziwnych krawędzi.

Możesz przesłać prośbę o zwolnienie do dplyr, jest ona aktywnie rozwijana, a hadley i Romain są miłymi facetami. Będziesz musiał dodać instrukcję if: here.

+0

Dzięki @Robert Krzyzanowski. Nie odważę się zacząć bawić się z kodem C++, ale dodałem to jako problem na github: https://github.com/hadley/dplyr/issues/715 –

Powiązane problemy