2013-04-18 11 views
6

mam ramki danych tak:R - Jak dodać indeks wiersza do ramki danych, w oparciu o kombinację czynników

df <- data.frame(
    Dim1 = c("A","A","A","A","A","A","B","B"), 
    Dim2 = c(100,100,100,100,200,200,100,200), 
    Value = sample(1:10, 8) 
     ) 

    Dim1 Dim2 Value 
1 A 100  3 
2 A 100  6 
3 A 100  7 
4 A 100  4 
5 A 200  8 
6 A 200  9 
7 B 100  2 
8 B 200 10 

(kolumna Wartość jest tylko w celu zilustrowania, że ​​każdy rząd jest punkt pomiarowy , rzeczywista wartość nie ma znaczenia.) Ostatecznie, co chciałbym zrobić, to wykreślić wartości w stosunku do ich indeksu w ramach podzbioru zdefiniowanego przez Dim1 i Dim2. Z tego powodu, myślę, że trzeba dołączyć nową kolumnę zawierającą indeksy, który wyglądałby następująco (dodane puste linie między wierszami, aby to oczywiste co podzbiory są):

Dim1 Dim2 Value Index 
1 A 100  1  1 
2 A 100  9  2 
3 A 100  4  3 
4 A 100 10  4 

5 A 200  7  1 
6 A 200  3  2 

7 B 100  5  1 

8 B 200  8  1 

Jak mogę to zrobić elegancko w R? Pochodzę z Pythona, a moim domyślnym podejściem jest zapętlanie się przez kombinacje Dim1 & Dim2, śledzenie liczby wierszy w każdym z nich i przypisywanie do tej pory maksimum napotkanego w każdym wierszu. Próbowałem to rozgryźć, ale mój wektor-fu jest słaby.

+0

Czy to, co chce zrobić? 'df $ index <- c (1,2,3,4,1,2,1,1)' –

+0

@Jdbaba W tym konkretnym przykładzie tak. Zasadniczo nie, ponieważ potrzebuję abstrakcyjnej funkcji, która będzie działać z większym obiektem data.frame z większą liczbą zmiennych czynnikowych, itp. – user2296603

+0

Ponieważ odpowiedź na to pytanie była pozytywna, czy istnieje jakiś sposób, aby tytuł mógł być bardziej pouczający? Dla mnie wiedza, jak to zrobić ma bardzo podstawowe znaczenie i chciałabym, aby ludzie mogli ją znaleźć. – user2296603

Odpowiedz

5

to prawdopodobnie będzie wyglądać oszustwo ponieważ jestem przechodzącej wektor do funkcji którą następnie całkowicie zignorować wyjątkiem dostać swoją długość:

df$Index <- ave(1:nrow(df), df$Dim1, factor(df$Dim2), FUN=function(x) 1:length(x)) 

Funkcja ave zwraca wektor tej samej długości co pierwszy argument, ale obliczony w kategoriach zdefiniowanych przez wszystkie czynniki między pierwszym argumentem a argumentem o nazwie FUN. (Często zapominam o umieszczeniu "FUN =" w mojej funkcji i otrzymuję tajemniczy komunikat o błędzie wzdłuż linii unique() applies only to vectors, ponieważ próbował on ustalić, ile unikalnych wartości posiada anonimowa funkcja, i to się nie udaje

faktycznie inny jeszcze bardziej kompaktowy sposób wyrażania function(x) 1:length(x) użyciu funkcji seq_along whch jest prawdopodobnie bezpieczniejsze, ponieważ byłoby to nie poprawnie, jeśli uchwalił wektor zerowej długości, podczas gdy anonimowy formularz funkcja zawiedzie niewłaściwie wracając 1:0 zamiast numeric(0):

ave(1:nrow(df), df$Dim1, factor(df$Dim2), FUN=seq_along) 
4

Proszę bardzo, używając data.table:

library(data.table) 
df <- data.table(
    Dim1 = c("A","A","A","A","A","A","B","B"), 
    Dim2 = c(100,100,100,100,200,200,100,200), 
    Value = sample(1:10, 8) 
     ) 

df[, index := seq_len(.N), by = list(Dim1, Dim2)] 
+0

użyj 'seq_len (.N)' zamiast '1: .N' (w tym przypadku .N zawsze będzie mieć 1 lub więcej, seq_len jest szybszy i bezpieczniejszy) – mnel

+0

ok, naprawiony, dzięki – eddi

+0

@eddi Dzięki, to też robi to, czego potrzebuję! Myślę, że na razie wolę rozwiązanie zamieszczone powyżej, ponieważ działa z data.frames i jestem całkowicie obeznany z data.tables. – user2296603

0

Czy to właśnie chcesz osiągnąć?

library(ggplot2) 
df <- data.frame(
    Dim1 = c("A","A","A","A","A","A","B","B"), 
    Dim2 = c(100,100,100,100,200,200,100,200), 
    Value = sample(1:10, 8) 
) 
df$index <- c(1,2,3,4,1,2,1,1) 

ggplot(df,aes(x=index,y=Value))+geom_point()+facet_wrap(Dim1~Dim2) 

Wyjście jest w następujący sposób: enter image description here

+0

W końcu tak! Poza tym, że czuję się komfortowo z ggplot2, ale nie wiem, jak utworzyć funkcję, która automatycznie sortuje kolumnę Index. – user2296603

Powiązane problemy