2016-01-28 13 views
5

Mam kolumnę wypełnioną innymi nazwami kolumn. Chcę uzyskać wartość w każdej z nazw kolumn.Użyj ciągu, aby wybrać kolumnę w wierszu w dplyr (lub base R)

# three columns with values and one "key" column 
library(dplyr) 
data = data.frame(
    x = runif(10), 
    y = runif(10), 
    z = runif(10), 
    key = sample(c('x', 'y', 'z'), 10, replace=TRUE) 
) 

# now get the value named in 'key' 
data = data %>% mutate(value = VALUE_AT_COLUMN(key)) 

Jestem całkiem pewien, że odpowiedź ma coś z leniwej wersji eval z mutować, ale nie mogę dla życia mnie rysunek.

Każda pomoc zostanie doceniona.

+1

Możesz także spróbować "danych [c (" x "," y "," z ")] [cbind (seq_len (nrow (dane)), dopasowanie (klucz danych $, nazwy (dane))) ] ', aby uniknąć grupowania według każdego wiersza (z, prawdopodobnie, niższym kosztem konwersji pośredniej do" macierzy "). –

+0

@alexis_laz Wolę bardziej rozszerzalne podejście, które nie wymaga umieszczenia w wykazie każdej kolumny. – sharoz

+1

W zależności od sposobu uporządkowania kolumn, powinno być wiele sposobów programowego ich wyodrębnienia; 'dane [1: 3]', 'dane [unikalne (klucz danych $)]', 'dane [! nazwy (dane)% w%" klucz "]' itd. –

Odpowiedz

5

Oto rozwiązanie Baza R:

data$value = diag(as.matrix(data[,data$key])) 
+1

Interesujące, choć wydaje mi się, że to wcale nie jest pamięć. –

+2

Nie! Może istnieć bardziej wydajna metoda pamięci, ale jeśli idziesz o wydajność, powinieneś zajrzeć do 'data.table' lub' dplyr'. Jeśli nie chcesz ładować więcej pakietów, a twoje dane nie są masowe, to zadziała. –

6

Możemy wypróbować data.table. Konwertuj "data.frame" na "data.table" (setDT(data)), pogrupowane według sekwencji wierszy, używamy .SD do podziału kolumn określonych przez 'klucz'.

library(data.table) 
setDT(data)[, .SD[, key[[1L]], with=FALSE] ,1:nrow(data)] 

Albo inna opcja jest get po konwersji „klucza” do character klasy (jak to factor) po grupowania według kolejności wierszy jak w poprzednim przypadku.

setDT(data)[, get(as.character(key)), 1:nrow(data)] 

Oto jedna opcja z do

library(dplyr) 
data %>% 
    group_by(rn = row_number()) %>% 
    do(data.frame(., value= .[[.$key]])) 
+0

Mogę to zrobić za pomocą innych bibliotek, ale staram się uniknąć konieczności importowania kolejnej biblioteki ramek danych. – sharoz

+0

@sharoz Jest to możliwe z 'dplyr' przy użyciu' do', – akrun

+2

Czy możesz to opublikować jako odpowiedź? – sharoz

4

To na pewno czuje się jak nie powinno być rozwiązaniem baza R do tego, ale najlepsze co mogłem zrobić to z tidyr, najpierw przekształcić dane do szerokiej formy, a następnie filtruj tylko te obserwacje, które pasują do pożądanego klucza.

data %>% 
    add_rownames("index") %>% 
    gather(var, value, -index, -key) %>% 
    filter(key == var) 

roztworze bazowym R, który praktycznie działa:

data[cbind(seq_along(data$key), data$key)] 

dane podane, to nie działa, ale, ponieważ wykorzystuje się matrycę, ma dwie poważne problemy. Jednym z nich jest to, że kolejność czynnika ma znaczenie, ponieważ po prostu to wymusza i wybiera kolumny według poziomu czynnika, a nie według nazwy kolumny. Drugi jest taki, że wynik wyjściowy to character, a nie numeric, ponieważ przy konwersji do macierzy typ character jest wybrany ze względu na kolumnę key. Kluczowym problemem jest to, że nie ma data.frame analogowo zachowania matrycy

podczas indeksowania tablice przez [ "pojedynczy argument„i”może być macierz jako liczbę kolumn są wymiary x ' ; wynikiem jest wektor z elementami odpowiadającymi zestawom indeksów w każdym rzędzie "i".

Biorąc pod uwagę te problemy, to pewnie go z roztworem tidyr, ponieważ fakt, że kolumny są zmiennie wybieralne oznacza, że ​​prawdopodobnie reprezentują różne spostrzeżenia dotyczące tej samej jednostce obserwowanej.

5

dla pamięci wydajne i szybkie rozwiązanie, należy zaktualizować oryginalne dane.Tabela wykonując łączyć w sposób następujący:

data[.(key2 = unique(key)), val := get(key2), on=c(key="key2"), by=.EACHI][] 

Dla każdego key2 rzędach w celu dopasowania data$key oblicza. Wiersze te są aktualizowane wartościami z kolumny zawartej w key2. Na przykład key2="x" pasuje do wierszy 1,2,6,8,10. Odpowiednie wartości data$x to data$x[c(1,2,6,8,10)]. by=.EACHI zapewnia, że ​​wyrażenie get(key2) jest wykonywane dla każdej wartości key2.

Ponieważ ta operacja jest wykonywana tylko w przypadku wartości unikatowych, powinna być znacznie szybsza niż w przypadku, gdy wykonywana jest w rzędzie. A ponieważ data.table jest aktualizowana przez odniesienie, powinna być dość wydajna pod względem pamięci (i to również przyczynia się do prędkości).

Powiązane problemy