2015-05-07 10 views
5

jak pójdę temat korzystania mutate (moje przypuszczenie, że szukam standardowej oceny w moim przypadku, a więc mutate_, ale nie jestem do końca pewny siebie w tej kwestii) przy użyciu funkcji, która akceptuje listę nazw zmiennych, takich jak ten:dplyr: średnia ocena dla mutować z cytowanych nazw zmiennych

createSum = function(data, variableNames) { 
    data %>% 
    mutate_(sumvar = interp(~ sum(var, na.rm = TRUE), 
          var = as.name(paste(as.character(variableNames), collapse =",")))) 

} 

Oto MWE że paski funkcję do swojej podstawowej logiki i pokazuje, co usiłuję osiągnąć:

library(dplyr) 
library(lazyeval) 

# function to make random table with given column names 
makeTable = function(colNames, sampleSize) { 
    liSample = lapply(colNames, function(week) { 
    sample = rnorm(sampleSize) 
    }) 
    names(liSample) = as.character(colNames) 
    return(tbl_df(data.frame(liSample, check.names = FALSE))) 
} 

# create some sample data with the column name patterns required 
weekDates = seq.Date(from = as.Date("2014-01-01"), 
        to = as.Date("2014-08-01"), by = "week") 
dfTest = makeTable(weekDates, 10) 

# test mutate on this table 
dfTest %>% 
    mutate_(sumvar = interp(~ sum(var, na.rm = TRUE), 
          var = as.name(paste(as.character(weekDates), collapse =",")))) 

Oczekiwany wyjście tutaj jest to, co będzie zwrócony przez:

rowSums(dfTest[, as.character(weekDates)]) 
+0

Definiując 'makeTable', a następnie wywołaj 'makeDataFrame'. Czy to ma być ta sama funkcja? Pomocne byłoby opisanie oczekiwanego wyniku dla tego przykładowego wejścia (ustawienie materiału wyjściowego na dane jest powtarzalne). – MrFlick

+0

@MrFlick Dzięki. Zmieniono nazwę funkcji. Nic dziwnego się nie spodziewa, po prostu "suma" wszystkich zmiennych, których nazwy zmiennych są przekazywane do funkcji, według wiersza. Aktualizacja z oczekiwanym wynikiem. – tchakravarty

Odpowiedz

5

myślę, że to jest to, co jesteś po

createSum = function(data, variableNames) { 
    data %>% 
     mutate_(sumvar = paste(as.character(variableNames), collapse ="+")) 
} 
createSum(dfTest, weekDates) 

gdzie po prostu podać wartość znaków zamiast interp ponieważ nie można przekazać listę nazw jako pojedynczy parametr do funkcji. Plus, sum() zrobiłby niepożądane zwijanie, ponieważ operacje nie są wykonywane w wierszach, są one przekazywane w kolumnach wektorów naraz.

Innym problemem z tym przykładem jest ustawienie check.names=FALSE w pliku data.frame, co oznacza, że ​​zostały utworzone nazwy kolumn, które nie mogą być prawidłowymi symbolami. Można wyraźnie owinąć nazw zmiennych w powrót kleszczy jeśli lubisz

createSum(dfTest , paste0("`", weekDates,"`")) 

ale generalnie lepiej byłoby nie korzystać z nieprawidłowych nazw.

+0

Dzięki, to by działało, ale co, gdyby funkcja nie miała poręcznego symbolu operatora? Po drugie, w jaki więc sposób przekazałbym listę argumentów po nazwie do "..." w funkcji? Jedyne przykłady standardowej oceny, jakie widziałem, dotyczą jednej nazwy zmiennej. – tchakravarty

+0

Nie jest łatwo mówić o hipotetycznej, każda funkcja może być inna. Ale ta metoda budowania ciągów powinna działać dla wielu innych funkcji ('suma' jest nieco wyjątkiem). Tylko wklej może wyglądać jak "paste0 (" funname (", wklej (vars, collapse =", "),") ")' – MrFlick

+0

Tak, jak się obawiałem, to wygląda na okropną składnię (bez twojej winy!) . Nie sądzę jednak, abym bardzo dobrze rozumiał ten paradygmat - wszystko, co chcę zrobić, to ocenić symbole zmiennych w środowisku 'data_frame'. Z pewnością istnieje lepszy sposób, aby to zrobić bez uciekania się do kłopotliwego budowania ekspresji lub 'eval (parse (text =)'. – tchakravarty

1

Nie wiem, czy to jest „oficjalnie usankcjonowane” dplyr sposób, ale jest to możliwość:

weekDates = as.character(weekDates) # more convenient 

dfTest %>% mutate(sumvar = Reduce(`+`, lapply(weekDates, get, .))) 
#or 
dfTest %>% mutate(sumvar = rowSums(as.data.frame(lapply(weekDates, get, .)))) 

To niesie potencjalnie znaczące pogorszenie się wyników, w zależności od konkretnego użycia - oprócz dplyr 's regularne kopiowanie wszystkich danych Myślę, że również kopiuje go po raz drugi podczas tego wewnętrznego obliczenia. Możesz zajrzeć do data.table, aby uniknąć dodatkowego kopiowania, dodając kolumny w miejscu (i używając .SDcols, aby uniknąć drugiej kopii) + uzyskasz prawdopodobnie lepszą składnię.

Powiązane problemy